crypt32: Split the test for ret and last error up.
[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     /* check with NULL integer buffer.  Windows XP incorrectly returns an
106      * NTSTATUS.
107      */
108     ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
109      &bufSize);
110     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
111      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
112     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
113     {
114         /* encode as normal integer */
115         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
116          NULL, NULL, &bufSize);
117         ok(ret, "Expected success, got %d\n", GetLastError());
118         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
119          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
120         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
121         if (buf)
122         {
123             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
124              buf[0]);
125             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
126              buf[1], ints[i].encoded[1]);
127             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
128              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
129             LocalFree(buf);
130         }
131         /* encode as multibyte integer */
132         blob.cbData = sizeof(ints[i].val);
133         blob.pbData = (BYTE *)&ints[i].val;
134         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
135          0, NULL, NULL, &bufSize);
136         ok(ret, "Expected success, got %d\n", GetLastError());
137         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
139         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
140         if (buf)
141         {
142             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
143              buf[0]);
144             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
145              buf[1], ints[i].encoded[1]);
146             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
147              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
148             LocalFree(buf);
149         }
150     }
151     /* encode a couple bigger ints, just to show it's little-endian and leading
152      * sign bytes are dropped
153      */
154     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
155     {
156         blob.cbData = strlen((const char*)bigInts[i].val);
157         blob.pbData = (BYTE *)bigInts[i].val;
158         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
159          0, NULL, NULL, &bufSize);
160         ok(ret, "Expected success, got %d\n", GetLastError());
161         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
163         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
164         if (buf)
165         {
166             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
167              buf[0]);
168             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
169              buf[1], bigInts[i].encoded[1]);
170             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
171              bigInts[i].encoded[1] + 1),
172              "Encoded value didn't match expected\n");
173             LocalFree(buf);
174         }
175     }
176     /* and, encode some uints */
177     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
178     {
179         blob.cbData = strlen((const char*)bigUInts[i].val);
180         blob.pbData = (BYTE*)bigUInts[i].val;
181         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
182          0, NULL, NULL, &bufSize);
183         ok(ret, "Expected success, got %d\n", GetLastError());
184         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
186         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
187         if (buf)
188         {
189             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
190              buf[0]);
191             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
192              buf[1], bigUInts[i].encoded[1]);
193             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
194              bigUInts[i].encoded[1] + 1),
195              "Encoded value didn't match expected\n");
196             LocalFree(buf);
197         }
198     }
199 }
200
201 static void test_decodeInt(DWORD dwEncoding)
202 {
203     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
204     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
205     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
206     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
207     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
208     BYTE *buf = NULL;
209     DWORD bufSize = 0;
210     int i;
211     BOOL ret;
212
213     /* CryptDecodeObjectEx with NULL bufSize crashes..
214     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
215      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
216      */
217     /* check bogus encoding */
218     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
219      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
220     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
221      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
222     /* check with NULL integer buffer */
223     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
224      &bufSize);
225     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
226      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
227     /* check with a valid, but too large, integer */
228     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
229      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
230     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
231      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
232     /* check with a DER-encoded string */
233     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
234      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
235     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
236      "Expected CRYPT_E_ASN1_BADTAG, got %d\n", GetLastError());
237     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
238     {
239         /* When the output buffer is NULL, this always succeeds */
240         SetLastError(0xdeadbeef);
241         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
243          &bufSize);
244         ok(ret && GetLastError() == NOERROR,
245          "Expected success and NOERROR, got %d\n", GetLastError());
246         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
247          ints[i].encoded, ints[i].encoded[1] + 2,
248          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
249         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
250         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
251         ok(buf != NULL, "Expected allocated buffer\n");
252         if (buf)
253         {
254             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
255              ints[i].val, *(int *)buf);
256             LocalFree(buf);
257         }
258     }
259     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
260     {
261         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
262          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
263          &bufSize);
264         ok(ret && GetLastError() == NOERROR,
265          "Expected success and NOERROR, got %d\n", GetLastError());
266         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
267          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
268          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
269         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
270         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
271         ok(buf != NULL, "Expected allocated buffer\n");
272         if (buf)
273         {
274             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
275
276             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
277              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
278              blob->cbData);
279             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
280              "Unexpected value\n");
281             LocalFree(buf);
282         }
283     }
284     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
285     {
286         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
287          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
288          &bufSize);
289         ok(ret && GetLastError() == NOERROR,
290          "Expected success and NOERROR, got %d\n", GetLastError());
291         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
292          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
293          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
294         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
295         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
296         ok(buf != NULL, "Expected allocated buffer\n");
297         if (buf)
298         {
299             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
300
301             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
302              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
303              blob->cbData);
304             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
305              "Unexpected value\n");
306             LocalFree(buf);
307         }
308     }
309     /* Decode the value 1 with long-form length */
310     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
311      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
312     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
313     if (buf)
314     {
315         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
316         LocalFree(buf);
317     }
318     /* check with extra bytes at the end */
319     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
320      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
321     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
322     if (buf)
323     {
324         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
325         LocalFree(buf);
326     }
327     /* Try to decode some bogus large items */
328     /* The buffer size is smaller than the encoded length, so this should fail
329      * with CRYPT_E_ASN1_EOD if it's being decoded.
330      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
331      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
332      * So this test unfortunately isn't useful.
333     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
334      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
335     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
336      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
337      */
338     /* This will try to decode the buffer and overflow it, check that it's
339      * caught.
340      */
341     if (0)
342     {
343     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
344     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
345      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
346     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
347      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
348     }
349 }
350
351 static const BYTE bin18[] = {0x0a,0x01,0x01};
352 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
353
354 /* These are always encoded unsigned, and aren't constrained to be any
355  * particular value
356  */
357 static const struct encodedInt enums[] = {
358  { 1,    bin18 },
359  { -128, bin19 },
360 };
361
362 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
363  * X509_ENUMERATED.
364  */
365 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
366  szOID_CRL_REASON_CODE };
367
368 static void test_encodeEnumerated(DWORD dwEncoding)
369 {
370     DWORD i, j;
371
372     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
373     {
374         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
375         {
376             BOOL ret;
377             BYTE *buf = NULL;
378             DWORD bufSize = 0;
379
380             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
381              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
382              &bufSize);
383             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
384             if (buf)
385             {
386                 ok(buf[0] == 0xa,
387                  "Got unexpected type %d for enumerated (expected 0xa)\n",
388                  buf[0]);
389                 ok(buf[1] == enums[j].encoded[1],
390                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
391                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
392                  enums[j].encoded[1] + 1),
393                  "Encoded value of 0x%08x didn't match expected\n",
394                  enums[j].val);
395                 LocalFree(buf);
396             }
397         }
398     }
399 }
400
401 static void test_decodeEnumerated(DWORD dwEncoding)
402 {
403     DWORD i, j;
404
405     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
406     {
407         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
408         {
409             BOOL ret;
410             DWORD bufSize = sizeof(int);
411             int val;
412
413             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
414              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
415              (BYTE *)&val, &bufSize);
416             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
417             ok(bufSize == sizeof(int),
418              "Got unexpected size %d for enumerated\n", bufSize);
419             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
420              val, enums[j].val);
421         }
422     }
423 }
424
425 struct encodedFiletime
426 {
427     SYSTEMTIME sysTime;
428     const BYTE *encodedTime;
429 };
430
431 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
432  const struct encodedFiletime *time)
433 {
434     FILETIME ft = { 0 };
435     BYTE *buf = NULL;
436     DWORD bufSize = 0;
437     BOOL ret;
438
439     ret = SystemTimeToFileTime(&time->sysTime, &ft);
440     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
441     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
442      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
443     /* years other than 1950-2050 are not allowed for encodings other than
444      * X509_CHOICE_OF_TIME.
445      */
446     if (structType == X509_CHOICE_OF_TIME ||
447      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
448     {
449         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
450          GetLastError());
451         ok(buf != NULL, "Expected an allocated buffer\n");
452         if (buf)
453         {
454             ok(buf[0] == time->encodedTime[0],
455              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
456              buf[0]);
457             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
458              time->encodedTime[1], bufSize);
459             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
460              "Got unexpected value for time encoding\n");
461             LocalFree(buf);
462         }
463     }
464     else
465         ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
466          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
467 }
468
469 static const char *printSystemTime(const SYSTEMTIME *st)
470 {
471     static char buf[25];
472
473     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
474      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
475     return buf;
476 }
477
478 static const char *printFileTime(const FILETIME *ft)
479 {
480     static char buf[25];
481     SYSTEMTIME st;
482
483     FileTimeToSystemTime(ft, &st);
484     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
485      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
486     return buf;
487 }
488
489 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
490 {
491     SYSTEMTIME st;
492
493     FileTimeToSystemTime(got, &st);
494     ok(expected->wYear == st.wYear &&
495      expected->wMonth == st.wMonth &&
496      expected->wDay == st.wDay &&
497      expected->wHour == st.wHour &&
498      expected->wMinute == st.wMinute &&
499      expected->wSecond == st.wSecond &&
500      abs(expected->wMilliseconds - st.wMilliseconds) <= 1,
501      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
502      printSystemTime(expected), printFileTime(got));
503 }
504
505 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
506  const struct encodedFiletime *time)
507 {
508     FILETIME ft = { 0 };
509     DWORD size = sizeof(ft);
510     BOOL ret;
511
512     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
513      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
514     /* years other than 1950-2050 are not allowed for encodings other than
515      * X509_CHOICE_OF_TIME.
516      */
517     if (structType == X509_CHOICE_OF_TIME ||
518      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
519     {
520         ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
521          GetLastError());
522         compareTime(&time->sysTime, &ft);
523     }
524     else
525         ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
526          "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
527 }
528
529 static const BYTE bin20[] = {
530     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
531 static const BYTE bin21[] = {
532     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
533 static const BYTE bin22[] = {
534     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
535
536 static const struct encodedFiletime times[] = {
537  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
538  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
539  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
540 };
541
542 static void test_encodeFiletime(DWORD dwEncoding)
543 {
544     DWORD i;
545
546     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
547     {
548         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
549         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
550         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
551     }
552 }
553
554 static const BYTE bin23[] = {
555     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
556 static const BYTE bin24[] = {
557     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
558 static const BYTE bin25[] = {
559     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
560 static const BYTE bin26[] = {
561     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
562 static const BYTE bin27[] = {
563     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
564 static const BYTE bin28[] = {
565     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
566 static const BYTE bin29[] = {
567     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
568 static const BYTE bin30[] = {
569     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
570 static const BYTE bin31[] = {
571     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
572 static const BYTE bin32[] = {
573     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
574 static const BYTE bin33[] = {
575     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
576 static const BYTE bin34[] = {
577     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
578 static const BYTE bin35[] = {
579     0x17,0x08, '4','5','0','6','0','6','1','6'};
580 static const BYTE bin36[] = {
581     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
582 static const BYTE bin37[] = {
583     0x18,0x04, '2','1','4','5'};
584 static const BYTE bin38[] = {
585     0x18,0x08, '2','1','4','5','0','6','0','6'};
586
587 static void test_decodeFiletime(DWORD dwEncoding)
588 {
589     static const struct encodedFiletime otherTimes[] = {
590      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
591      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
592      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
593      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
594      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
595      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
596      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
597      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
598      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
599      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
600      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
601      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
602     };
603     /* An oddball case that succeeds in Windows, but doesn't seem correct
604      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
605      */
606     static const unsigned char *bogusTimes[] = {
607      /* oddly, this succeeds on Windows, with year 2765
608      "\x18" "\x0f" "21r50606161000Z",
609       */
610      bin35,
611      bin36,
612      bin37,
613      bin38,
614     };
615     DWORD i, size;
616     FILETIME ft1 = { 0 }, ft2 = { 0 };
617     BOOL ret;
618
619     /* Check bogus length with non-NULL buffer */
620     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
621     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
622     size = 1;
623     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
624      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
625     ok(!ret && GetLastError() == ERROR_MORE_DATA,
626      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
627     /* Normal tests */
628     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
629     {
630         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
631         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
632         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
633     }
634     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
635     {
636         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
637         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
638         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
639     }
640     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
641     {
642         size = sizeof(ft1);
643         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
644          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
645         ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
646          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
647     }
648 }
649
650 static const char commonName[] = "Juan Lang";
651 static const char surName[] = "Lang";
652
653 static const BYTE emptySequence[] = { 0x30, 0 };
654 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
655 static const BYTE twoRDNs[] = {
656     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
657     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
658     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
659 static const BYTE encodedTwoRDNs[] = {
660 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
661 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
662 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
663 0x6e,0x67,0x00,
664 };
665
666 static const BYTE us[] = { 0x55, 0x53 };
667 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
668  0x74, 0x61 };
669 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
670  0x6f, 0x6c, 0x69, 0x73 };
671 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
672  0x76, 0x65, 0x72, 0x73 };
673 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
674  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
675 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
676  0x73, 0x74 };
677 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
678  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
679
680 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
681 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
682
683 static CHAR oid_us[]            = "2.5.4.6",
684             oid_minnesota[]     = "2.5.4.8",
685             oid_minneapolis[]   = "2.5.4.7",
686             oid_codeweavers[]   = "2.5.4.10",
687             oid_wine[]          = "2.5.4.11",
688             oid_localhostAttr[] = "2.5.4.3",
689             oid_aric[]          = "1.2.840.113549.1.9.1";
690 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
691                                     { RDNA(minnesota) },
692                                     { RDNA(minneapolis) },
693                                     { RDNA(codeweavers) },
694                                     { RDNA(wine) },
695                                     { RDNA(localhostAttr) },
696                                     { RDNIA5(aric) } };
697 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
698                                            { RDNA(localhostAttr) },
699                                            { RDNA(minnesota) },
700                                            { RDNA(minneapolis) },
701                                            { RDNA(codeweavers) },
702                                            { RDNA(wine) },
703                                            { RDNIA5(aric) } };
704
705 #undef RDNIA5
706 #undef RDNA
707
708 static const BYTE encodedRDNAttrs[] = {
709 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
710 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
711 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
712 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
713 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
714 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
715 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
716 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
717 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
718 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
719 };
720
721 static void test_encodeName(DWORD dwEncoding)
722 {
723     CERT_RDN_ATTR attrs[2];
724     CERT_RDN rdn;
725     CERT_NAME_INFO info;
726     static CHAR oid_common_name[] = szOID_COMMON_NAME,
727                 oid_sur_name[]    = szOID_SUR_NAME;
728     BYTE *buf = NULL;
729     DWORD size = 0;
730     BOOL ret;
731
732     /* Test with NULL pvStructInfo */
733     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
734      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
735     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
736      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
737     /* Test with empty CERT_NAME_INFO */
738     info.cRDN = 0;
739     info.rgRDN = NULL;
740     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
741      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
742     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
743     if (buf)
744     {
745         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
746          "Got unexpected encoding for empty name\n");
747         LocalFree(buf);
748     }
749     /* Test with bogus CERT_RDN */
750     info.cRDN = 1;
751     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
752      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
753     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
754      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
755     /* Test with empty CERT_RDN */
756     rdn.cRDNAttr = 0;
757     rdn.rgRDNAttr = NULL;
758     info.cRDN = 1;
759     info.rgRDN = &rdn;
760     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
761      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
762     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
763     if (buf)
764     {
765         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
766          "Got unexpected encoding for empty RDN array\n");
767         LocalFree(buf);
768     }
769     /* Test with bogus attr array */
770     rdn.cRDNAttr = 1;
771     rdn.rgRDNAttr = NULL;
772     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
773      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
774     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
775      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
776     /* oddly, a bogus OID is accepted by Windows XP; not testing.
777     attrs[0].pszObjId = "bogus";
778     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
779     attrs[0].Value.cbData = sizeof(commonName);
780     attrs[0].Value.pbData = (BYTE *)commonName;
781     rdn.cRDNAttr = 1;
782     rdn.rgRDNAttr = attrs;
783     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
784      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
785     ok(!ret, "Expected failure, got success\n");
786      */
787     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
788      * the encoded attributes to be swapped.
789      */
790     attrs[0].pszObjId = oid_common_name;
791     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
792     attrs[0].Value.cbData = sizeof(commonName);
793     attrs[0].Value.pbData = (BYTE *)commonName;
794     attrs[1].pszObjId = oid_sur_name;
795     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
796     attrs[1].Value.cbData = sizeof(surName);
797     attrs[1].Value.pbData = (BYTE *)surName;
798     rdn.cRDNAttr = 2;
799     rdn.rgRDNAttr = attrs;
800     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
801      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
802     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
803     if (buf)
804     {
805         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
806          "Got unexpected encoding for two RDN array\n");
807         LocalFree(buf);
808     }
809     /* A name can be "encoded" with previously encoded RDN attrs. */
810     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
811     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
812     attrs[0].Value.cbData = sizeof(twoRDNs);
813     rdn.cRDNAttr = 1;
814     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
815      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
816     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
817     if (buf)
818     {
819         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
820         ok(!memcmp(buf, encodedTwoRDNs, size),
821          "Unexpected value for re-endoded two RDN array\n");
822         LocalFree(buf);
823     }
824     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
825     rdn.cRDNAttr = 1;
826     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
827     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
828      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
829     ok(!ret && GetLastError() == E_INVALIDARG,
830      "Expected E_INVALIDARG, got %08x\n", GetLastError());
831     /* Test a more complex name */
832     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
833     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
834     info.cRDN = 1;
835     info.rgRDN = &rdn;
836     buf = NULL;
837     size = 0;
838     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
839      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
840     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
841     if (ret)
842     {
843         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
844         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
845         LocalFree(buf);
846     }
847 }
848
849 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
850 static WCHAR surNameW[] = { 'L','a','n','g',0 };
851
852 static const BYTE twoRDNsNoNull[] = {
853  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
854  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
855  0x20,0x4c,0x61,0x6e,0x67 };
856 static const BYTE anyType[] = {
857  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
858  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
859  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
860  0x61,0x4c,0x67,0x6e };
861
862 static void test_encodeUnicodeName(DWORD dwEncoding)
863 {
864     CERT_RDN_ATTR attrs[2];
865     CERT_RDN rdn;
866     CERT_NAME_INFO info;
867     static CHAR oid_common_name[] = szOID_COMMON_NAME,
868                 oid_sur_name[]    = szOID_SUR_NAME;
869     BYTE *buf = NULL;
870     DWORD size = 0;
871     BOOL ret;
872
873     /* Test with NULL pvStructInfo */
874     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
875      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
876     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
877      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
878     /* Test with empty CERT_NAME_INFO */
879     info.cRDN = 0;
880     info.rgRDN = NULL;
881     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
882      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
883     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
884     if (buf)
885     {
886         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
887          "Got unexpected encoding for empty name\n");
888         LocalFree(buf);
889     }
890     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
891      * encoding (the NULL).
892      */
893     attrs[0].pszObjId = oid_common_name;
894     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
895     attrs[0].Value.cbData = sizeof(commonNameW);
896     attrs[0].Value.pbData = (BYTE *)commonNameW;
897     rdn.cRDNAttr = 1;
898     rdn.rgRDNAttr = attrs;
899     info.cRDN = 1;
900     info.rgRDN = &rdn;
901     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
902      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
903     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
904      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
905     ok(size == 9, "Unexpected error index %08x\n", size);
906     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
907      * forces the order of the encoded attributes to be swapped.
908      */
909     attrs[0].pszObjId = oid_common_name;
910     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
911     attrs[0].Value.cbData = 0;
912     attrs[0].Value.pbData = (BYTE *)commonNameW;
913     attrs[1].pszObjId = oid_sur_name;
914     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
915     attrs[1].Value.cbData = 0;
916     attrs[1].Value.pbData = (BYTE *)surNameW;
917     rdn.cRDNAttr = 2;
918     rdn.rgRDNAttr = attrs;
919     info.cRDN = 1;
920     info.rgRDN = &rdn;
921     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
922      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
923     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
924     if (buf)
925     {
926         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
927          "Got unexpected encoding for two RDN array\n");
928         LocalFree(buf);
929     }
930     /* A name can be "encoded" with previously encoded RDN attrs. */
931     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
932     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
933     attrs[0].Value.cbData = sizeof(twoRDNs);
934     rdn.cRDNAttr = 1;
935     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
937     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
938     if (buf)
939     {
940         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
941         ok(!memcmp(buf, encodedTwoRDNs, size),
942          "Unexpected value for re-endoded two RDN array\n");
943         LocalFree(buf);
944     }
945     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
946     rdn.cRDNAttr = 1;
947     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
948     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
949      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
950     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
951     if (buf)
952     {
953         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
954         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
955         LocalFree(buf);
956     }
957 }
958
959 static void compareNameValues(const CERT_NAME_VALUE *expected,
960  const CERT_NAME_VALUE *got)
961 {
962     ok(got->dwValueType == expected->dwValueType,
963      "Expected string type %d, got %d\n", expected->dwValueType,
964      got->dwValueType);
965     ok(got->Value.cbData == expected->Value.cbData,
966      "String type %d: unexpected data size, got %d, expected %d\n",
967      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
968     if (got->Value.cbData && got->Value.pbData)
969         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
970          min(got->Value.cbData, expected->Value.cbData)),
971          "String type %d: unexpected value\n", expected->dwValueType);
972 }
973
974 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
975  const CERT_RDN_ATTR *got)
976 {
977     if (expected->pszObjId && strlen(expected->pszObjId))
978     {
979         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
980          expected->pszObjId);
981         if (got->pszObjId)
982         {
983             ok(!strcmp(got->pszObjId, expected->pszObjId),
984              "Got unexpected OID %s, expected %s\n", got->pszObjId,
985              expected->pszObjId);
986         }
987     }
988     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
989      (const CERT_NAME_VALUE *)&got->dwValueType);
990 }
991
992 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
993 {
994     ok(got->cRDNAttr == expected->cRDNAttr,
995      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
996     if (got->cRDNAttr)
997     {
998         DWORD i;
999
1000         for (i = 0; i < got->cRDNAttr; i++)
1001             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1002     }
1003 }
1004
1005 static void compareNames(const CERT_NAME_INFO *expected,
1006  const CERT_NAME_INFO *got)
1007 {
1008     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1009      expected->cRDN, got->cRDN);
1010     if (got->cRDN)
1011     {
1012         DWORD i;
1013
1014         for (i = 0; i < got->cRDN; i++)
1015             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1016     }
1017 }
1018
1019 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1020 static const BYTE twoRDNsExtraBytes[] = {
1021     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1022     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1023     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1024
1025 static void test_decodeName(DWORD dwEncoding)
1026 {
1027     BYTE *buf = NULL;
1028     DWORD bufSize = 0;
1029     BOOL ret;
1030     CERT_RDN rdn;
1031     CERT_NAME_INFO info = { 1, &rdn };
1032
1033     /* test empty name */
1034     bufSize = 0;
1035     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1036      emptySequence[1] + 2,
1037      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1038      (BYTE *)&buf, &bufSize);
1039     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1040     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1041      * decoder works the same way, so only test the count.
1042      */
1043     if (buf)
1044     {
1045         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1046         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1047          "Expected 0 RDNs in empty info, got %d\n",
1048          ((CERT_NAME_INFO *)buf)->cRDN);
1049         LocalFree(buf);
1050     }
1051     /* test empty name with indefinite-length encoding */
1052     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1053      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1054      (BYTE *)&buf, &bufSize);
1055     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1056     if (ret)
1057     {
1058         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1059         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1060          "Expected 0 RDNs in empty info, got %d\n",
1061          ((CERT_NAME_INFO *)buf)->cRDN);
1062         LocalFree(buf);
1063     }
1064     /* test empty RDN */
1065     bufSize = 0;
1066     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1067      emptyRDNs[1] + 2,
1068      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1069      (BYTE *)&buf, &bufSize);
1070     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1071     if (buf)
1072     {
1073         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1074
1075         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1076          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1077          "Got unexpected value for empty RDN\n");
1078         LocalFree(buf);
1079     }
1080     /* test two RDN attrs */
1081     bufSize = 0;
1082     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1083      twoRDNs[1] + 2,
1084      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1085      (BYTE *)&buf, &bufSize);
1086     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1087     if (buf)
1088     {
1089         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1090                     oid_common_name[] = szOID_COMMON_NAME;
1091
1092         CERT_RDN_ATTR attrs[] = {
1093          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1094           (BYTE *)surName } },
1095          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1096           (BYTE *)commonName } },
1097         };
1098
1099         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1100         rdn.rgRDNAttr = attrs;
1101         compareNames(&info, (CERT_NAME_INFO *)buf);
1102         LocalFree(buf);
1103     }
1104     /* test that two RDN attrs with extra bytes succeeds */
1105     bufSize = 0;
1106     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1107      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1108     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1109     /* And, a slightly more complicated name */
1110     buf = NULL;
1111     bufSize = 0;
1112     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1113      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1114     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1115     if (ret)
1116     {
1117         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1118         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1119         compareNames(&info, (CERT_NAME_INFO *)buf);
1120         LocalFree(buf);
1121     }
1122 }
1123
1124 static void test_decodeUnicodeName(DWORD dwEncoding)
1125 {
1126     BYTE *buf = NULL;
1127     DWORD bufSize = 0;
1128     BOOL ret;
1129     CERT_RDN rdn;
1130     CERT_NAME_INFO info = { 1, &rdn };
1131
1132     /* test empty name */
1133     bufSize = 0;
1134     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1135      emptySequence[1] + 2,
1136      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1137      (BYTE *)&buf, &bufSize);
1138     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1139     if (buf)
1140     {
1141         ok(bufSize == sizeof(CERT_NAME_INFO),
1142          "Got wrong bufSize %d\n", bufSize);
1143         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1144          "Expected 0 RDNs in empty info, got %d\n",
1145          ((CERT_NAME_INFO *)buf)->cRDN);
1146         LocalFree(buf);
1147     }
1148     /* test empty RDN */
1149     bufSize = 0;
1150     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1151      emptyRDNs[1] + 2,
1152      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1153      (BYTE *)&buf, &bufSize);
1154     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1155     if (buf)
1156     {
1157         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1158
1159         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1160          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1161          "Got unexpected value for empty RDN\n");
1162         LocalFree(buf);
1163     }
1164     /* test two RDN attrs */
1165     bufSize = 0;
1166     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1167      sizeof(twoRDNsNoNull),
1168      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1169      (BYTE *)&buf, &bufSize);
1170     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1171     if (buf)
1172     {
1173         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1174                     oid_common_name[] = szOID_COMMON_NAME;
1175
1176         CERT_RDN_ATTR attrs[] = {
1177          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1178          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1179          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1180          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1181         };
1182
1183         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1184         rdn.rgRDNAttr = attrs;
1185         compareNames(&info, (CERT_NAME_INFO *)buf);
1186         LocalFree(buf);
1187     }
1188 }
1189
1190 struct EncodedNameValue
1191 {
1192     CERT_NAME_VALUE value;
1193     const BYTE *encoded;
1194     DWORD encodedSize;
1195 };
1196
1197 static const char bogusIA5[] = "\x80";
1198 static const char bogusPrintable[] = "~";
1199 static const char bogusNumeric[] = "A";
1200 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1201 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1202 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1203 static BYTE octetCommonNameValue[] = {
1204  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1205 static BYTE numericCommonNameValue[] = {
1206  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1207 static BYTE printableCommonNameValue[] = {
1208  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1209 static BYTE t61CommonNameValue[] = {
1210  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1211 static BYTE videotexCommonNameValue[] = {
1212  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1213 static BYTE ia5CommonNameValue[] = {
1214  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1215 static BYTE graphicCommonNameValue[] = {
1216  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1217 static BYTE visibleCommonNameValue[] = {
1218  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1219 static BYTE generalCommonNameValue[] = {
1220  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1221 static BYTE bmpCommonNameValue[] = {
1222  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1223  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1224 static BYTE utf8CommonNameValue[] = {
1225  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1226
1227 static struct EncodedNameValue nameValues[] = {
1228  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1229      octetCommonNameValue, sizeof(octetCommonNameValue) },
1230  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1231      numericCommonNameValue, sizeof(numericCommonNameValue) },
1232  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1233      printableCommonNameValue, sizeof(printableCommonNameValue) },
1234  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1235      t61CommonNameValue, sizeof(t61CommonNameValue) },
1236  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1237      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1238  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1239      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1240  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1241      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1242  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1243      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1244  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1245      generalCommonNameValue, sizeof(generalCommonNameValue) },
1246  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1247      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1248  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1249      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1250  /* The following tests succeed under Windows, but really should fail,
1251   * they contain characters that are illegal for the encoding.  I'm
1252   * including them to justify my lazy encoding.
1253   */
1254  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1255      sizeof(bin42) },
1256  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1257      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1258  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1259      bin44, sizeof(bin44) },
1260 };
1261
1262 static void test_encodeNameValue(DWORD dwEncoding)
1263 {
1264     BYTE *buf = NULL;
1265     DWORD size = 0, i;
1266     BOOL ret;
1267     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1268
1269     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1270     value.Value.pbData = printableCommonNameValue;
1271     value.Value.cbData = sizeof(printableCommonNameValue);
1272     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1273      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1274     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1275     if (buf)
1276     {
1277         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1278          size);
1279         ok(!memcmp(buf, printableCommonNameValue, size),
1280          "Unexpected encoding\n");
1281         LocalFree(buf);
1282     }
1283     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1284     {
1285         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1286          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1287          &size);
1288         ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1289          nameValues[i].value.dwValueType, GetLastError());
1290         if (buf)
1291         {
1292             ok(size == nameValues[i].encodedSize,
1293              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1294             ok(!memcmp(buf, nameValues[i].encoded, size),
1295              "Got unexpected encoding\n");
1296             LocalFree(buf);
1297         }
1298     }
1299 }
1300
1301 static void test_decodeNameValue(DWORD dwEncoding)
1302 {
1303     int i;
1304     BYTE *buf = NULL;
1305     DWORD bufSize = 0;
1306     BOOL ret;
1307
1308     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1309     {
1310         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1311          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1312          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1313          (BYTE *)&buf, &bufSize);
1314         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1315          nameValues[i].value.dwValueType, GetLastError());
1316         if (buf)
1317         {
1318             compareNameValues(&nameValues[i].value,
1319              (const CERT_NAME_VALUE *)buf);
1320             LocalFree(buf);
1321         }
1322     }
1323 }
1324
1325 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1326 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1327 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1328  'h','q','.','o','r','g',0 };
1329 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1330  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1331  0x6f, 0x72, 0x67 };
1332 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1333  0x575b, 0 };
1334 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1335 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1336  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1337 static const BYTE localhost[] = { 127, 0, 0, 1 };
1338 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1339  0x01 };
1340 static const unsigned char encodedCommonName[] = {
1341     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1342 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1343 static const BYTE encodedDirectoryName[] = {
1344 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1345 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1346
1347 static void test_encodeAltName(DWORD dwEncoding)
1348 {
1349     CERT_ALT_NAME_INFO info = { 0 };
1350     CERT_ALT_NAME_ENTRY entry = { 0 };
1351     BYTE *buf = NULL;
1352     DWORD size = 0;
1353     BOOL ret;
1354     char oid[] = "1.2.3";
1355
1356     /* Test with empty info */
1357     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1358      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1359     if (buf)
1360     {
1361         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1362         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1363         LocalFree(buf);
1364     }
1365     /* Test with an empty entry */
1366     info.cAltEntry = 1;
1367     info.rgAltEntry = &entry;
1368     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1369      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1370     ok(!ret && GetLastError() == E_INVALIDARG,
1371      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1372     /* Test with an empty pointer */
1373     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1374     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1375      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1376     if (buf)
1377     {
1378         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1379         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1380         LocalFree(buf);
1381     }
1382     /* Test with a real URL */
1383     U(entry).pwszURL = (LPWSTR)url;
1384     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1385      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1386     if (buf)
1387     {
1388         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1389         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1390         LocalFree(buf);
1391     }
1392     /* Now with the URL containing an invalid IA5 char */
1393     U(entry).pwszURL = (LPWSTR)nihongoURL;
1394     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1395      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1396     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1397      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1398     /* The first invalid character is at index 7 */
1399     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1400      "Expected invalid char at index 7, got %d\n",
1401      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1402     /* Now with the URL missing a scheme */
1403     U(entry).pwszURL = (LPWSTR)dnsName;
1404     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1405      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1406     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1407     if (buf)
1408     {
1409         /* This succeeds, but it shouldn't, so don't worry about conforming */
1410         LocalFree(buf);
1411     }
1412     /* Now with a DNS name */
1413     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1414     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1415      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1416     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1417     if (buf)
1418     {
1419         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1420         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1421         LocalFree(buf);
1422     }
1423     /* Test with an IP address */
1424     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1425     U(entry).IPAddress.cbData = sizeof(localhost);
1426     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1427     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1428      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1429     if (buf)
1430     {
1431         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1432         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1433         LocalFree(buf);
1434     }
1435     /* Test with OID */
1436     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1437     U(entry).pszRegisteredID = oid;
1438     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1439      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1440     if (buf)
1441     {
1442         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1443         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1444         LocalFree(buf);
1445     }
1446     /* Test with directory name */
1447     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1448     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1449     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1450     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1451      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1452     if (buf)
1453     {
1454         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1455         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1456         LocalFree(buf);
1457     }
1458 }
1459
1460 static void test_decodeAltName(DWORD dwEncoding)
1461 {
1462     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1463      0x00, 0x00, 0x01 };
1464     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1465      0x01 };
1466     BOOL ret;
1467     BYTE *buf = NULL;
1468     DWORD bufSize = 0;
1469     CERT_ALT_NAME_INFO *info;
1470
1471     /* Test some bogus ones first */
1472     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1473      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1474      NULL, (BYTE *)&buf, &bufSize);
1475     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1476      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1477     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1478      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1479      &bufSize);
1480     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1481      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1482     /* Now expected cases */
1483     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1484      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1485      &bufSize);
1486     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1487     if (buf)
1488     {
1489         info = (CERT_ALT_NAME_INFO *)buf;
1490
1491         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1492          info->cAltEntry);
1493         LocalFree(buf);
1494     }
1495     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1496      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1497      &bufSize);
1498     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1499     if (buf)
1500     {
1501         info = (CERT_ALT_NAME_INFO *)buf;
1502
1503         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1504          info->cAltEntry);
1505         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1506          "Expected CERT_ALT_NAME_URL, got %d\n",
1507          info->rgAltEntry[0].dwAltNameChoice);
1508         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1509          "Expected empty URL\n");
1510         LocalFree(buf);
1511     }
1512     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1513      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1514     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1515     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1516      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1517      &bufSize);
1518     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1519     if (buf)
1520     {
1521         info = (CERT_ALT_NAME_INFO *)buf;
1522
1523         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1524          info->cAltEntry);
1525         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1526          "Expected CERT_ALT_NAME_URL, got %d\n",
1527          info->rgAltEntry[0].dwAltNameChoice);
1528         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1529         LocalFree(buf);
1530     }
1531     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1532      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1533      &bufSize);
1534     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1535     if (buf)
1536     {
1537         info = (CERT_ALT_NAME_INFO *)buf;
1538
1539         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1540          info->cAltEntry);
1541         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1542          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1543          info->rgAltEntry[0].dwAltNameChoice);
1544         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1545          "Unexpected DNS name\n");
1546         LocalFree(buf);
1547     }
1548     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1549      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1550      &bufSize);
1551     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1552     if (buf)
1553     {
1554         info = (CERT_ALT_NAME_INFO *)buf;
1555
1556         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1557          info->cAltEntry);
1558         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1559          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1560          info->rgAltEntry[0].dwAltNameChoice);
1561         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1562          "Unexpected IP address length %d\n",
1563           U(info->rgAltEntry[0]).IPAddress.cbData);
1564         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1565          sizeof(localhost)), "Unexpected IP address value\n");
1566         LocalFree(buf);
1567     }
1568     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1569      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1570      &bufSize);
1571     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1572     if (buf)
1573     {
1574         info = (CERT_ALT_NAME_INFO *)buf;
1575
1576         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1577          info->cAltEntry);
1578         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1579          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1580          info->rgAltEntry[0].dwAltNameChoice);
1581         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1582            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1583         LocalFree(buf);
1584     }
1585     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1586      encodedDirectoryName, sizeof(encodedDirectoryName),
1587      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1588     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1589     if (buf)
1590     {
1591         info = (CERT_ALT_NAME_INFO *)buf;
1592
1593         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1594          info->cAltEntry);
1595         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1596          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1597          info->rgAltEntry[0].dwAltNameChoice);
1598         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1599          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1600           U(info->rgAltEntry[0]).DirectoryName.cbData);
1601         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1602          encodedCommonName, sizeof(encodedCommonName)),
1603          "Unexpected directory name value\n");
1604         LocalFree(buf);
1605     }
1606 }
1607
1608 struct UnicodeExpectedError
1609 {
1610     DWORD   valueType;
1611     LPCWSTR str;
1612     DWORD   errorIndex;
1613     DWORD   error;
1614 };
1615
1616 static const WCHAR oneW[] = { '1',0 };
1617 static const WCHAR aW[] = { 'a',0 };
1618 static const WCHAR quoteW[] = { '"', 0 };
1619
1620 static struct UnicodeExpectedError unicodeErrors[] = {
1621  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1622  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1623  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1624  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1625  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1626  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1627 };
1628
1629 struct UnicodeExpectedResult
1630 {
1631     DWORD           valueType;
1632     LPCWSTR         str;
1633     CRYPT_DATA_BLOB encoded;
1634 };
1635
1636 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1637 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1638 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1639 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1640 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1641 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1642 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1643 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1644 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1645 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1646 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1647 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1648  0x5b };
1649 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1650  0x6f,0x5b };
1651 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1652  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1653 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1654  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1655
1656 static struct UnicodeExpectedResult unicodeResults[] = {
1657  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1658  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1659  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1660  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1661  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1662  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1663  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1664  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1665  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1666  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1667  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1668  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1669  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1670 };
1671
1672 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1673  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1674  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1675 };
1676
1677 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1678 {
1679     BYTE *buf = NULL;
1680     DWORD size = 0, i;
1681     BOOL ret;
1682     CERT_NAME_VALUE value;
1683
1684     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1685      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1686     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1687      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1688     /* Have to have a string of some sort */
1689     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1690     value.Value.pbData = NULL;
1691     value.Value.cbData = 0;
1692     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1693      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1694     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1695      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1696     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1697     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1698      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1699     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1700      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1701     value.dwValueType = CERT_RDN_ANY_TYPE;
1702     value.Value.pbData = (LPBYTE)oneW;
1703     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1704      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1705     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1706      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1707     value.Value.cbData = sizeof(oneW);
1708     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1709      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1710     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1711      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1712     /* An encoded string with specified length isn't good enough either */
1713     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1714     value.Value.pbData = oneUniversal;
1715     value.Value.cbData = sizeof(oneUniversal);
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     /* More failure checking */
1721     value.Value.cbData = 0;
1722     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1723     {
1724         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1725         value.dwValueType = unicodeErrors[i].valueType;
1726         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1727          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1728         ok(!ret && GetLastError() == unicodeErrors[i].error,
1729          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1730          unicodeErrors[i].error, GetLastError());
1731         ok(size == unicodeErrors[i].errorIndex,
1732          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1733          size);
1734     }
1735     /* cbData can be zero if the string is NULL-terminated */
1736     value.Value.cbData = 0;
1737     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1738     {
1739         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1740         value.dwValueType = unicodeResults[i].valueType;
1741         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1742          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1743         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1744         if (buf)
1745         {
1746             ok(size == unicodeResults[i].encoded.cbData,
1747              "Value type %d: expected size %d, got %d\n",
1748              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1749             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1750              "Value type %d: unexpected value\n", value.dwValueType);
1751             LocalFree(buf);
1752         }
1753     }
1754     /* These "encode," but they do so by truncating each unicode character
1755      * rather than properly encoding it.  Kept separate from the proper results,
1756      * because the encoded forms won't decode to their original strings.
1757      */
1758     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1759     {
1760         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1761         value.dwValueType = unicodeWeirdness[i].valueType;
1762         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1763          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1764         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1765         if (buf)
1766         {
1767             ok(size == unicodeWeirdness[i].encoded.cbData,
1768              "Value type %d: expected size %d, got %d\n",
1769              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1770             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1771              "Value type %d: unexpected value\n", value.dwValueType);
1772             LocalFree(buf);
1773         }
1774     }
1775 }
1776
1777 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1778 {
1779     if (n <= 0) return 0;
1780     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1781     return *str1 - *str2;
1782 }
1783
1784 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1785 {
1786     DWORD i;
1787
1788     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1789     {
1790         BYTE *buf = NULL;
1791         BOOL ret;
1792         DWORD size = 0;
1793
1794         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1795          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1796          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1797         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1798         if (ret && buf)
1799         {
1800             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1801
1802             ok(value->dwValueType == unicodeResults[i].valueType,
1803              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1804              value->dwValueType);
1805             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1806              value->Value.cbData / sizeof(WCHAR)),
1807              "Unexpected decoded value for index %d (value type %d)\n", i,
1808              unicodeResults[i].valueType);
1809             LocalFree(buf);
1810         }
1811     }
1812 }
1813
1814 struct encodedOctets
1815 {
1816     const BYTE *val;
1817     const BYTE *encoded;
1818 };
1819
1820 static const unsigned char bin46[] = { 'h','i',0 };
1821 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1822 static const unsigned char bin48[] = {
1823      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1824 static const unsigned char bin49[] = {
1825      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1826 static const unsigned char bin50[] = { 0 };
1827 static const unsigned char bin51[] = { 0x04,0x00,0 };
1828
1829 static const struct encodedOctets octets[] = {
1830     { bin46, bin47 },
1831     { bin48, bin49 },
1832     { bin50, bin51 },
1833 };
1834
1835 static void test_encodeOctets(DWORD dwEncoding)
1836 {
1837     CRYPT_DATA_BLOB blob;
1838     DWORD i;
1839
1840     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1841     {
1842         BYTE *buf = NULL;
1843         BOOL ret;
1844         DWORD bufSize = 0;
1845
1846         blob.cbData = strlen((const char*)octets[i].val);
1847         blob.pbData = (BYTE*)octets[i].val;
1848         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1849          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1850         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1851         if (buf)
1852         {
1853             ok(buf[0] == 4,
1854              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1855             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1856              buf[1], octets[i].encoded[1]);
1857             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1858              octets[i].encoded[1] + 1), "Got unexpected value\n");
1859             LocalFree(buf);
1860         }
1861     }
1862 }
1863
1864 static void test_decodeOctets(DWORD dwEncoding)
1865 {
1866     DWORD i;
1867
1868     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1869     {
1870         BYTE *buf = NULL;
1871         BOOL ret;
1872         DWORD bufSize = 0;
1873
1874         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1875          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1876          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1877         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1878         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1879          "Expected size >= %d, got %d\n",
1880            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1881         ok(buf != NULL, "Expected allocated buffer\n");
1882         if (buf)
1883         {
1884             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1885
1886             if (blob->cbData)
1887                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1888                  "Unexpected value\n");
1889             LocalFree(buf);
1890         }
1891     }
1892 }
1893
1894 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1895
1896 struct encodedBits
1897 {
1898     DWORD cUnusedBits;
1899     const BYTE *encoded;
1900     DWORD cbDecoded;
1901     const BYTE *decoded;
1902 };
1903
1904 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1905 static const unsigned char bin53[] = { 0xff,0xff };
1906 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1907 static const unsigned char bin55[] = { 0xff,0xfe };
1908 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1909 static const unsigned char bin57[] = { 0xfe };
1910 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1911
1912 static const struct encodedBits bits[] = {
1913     /* normal test cases */
1914     { 0, bin52, 2, bin53 },
1915     { 1, bin54, 2, bin55 },
1916     /* strange test case, showing cUnusedBits >= 8 is allowed */
1917     { 9, bin56, 1, bin57 },
1918     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1919     { 17, bin58, 0, NULL },
1920 };
1921
1922 static void test_encodeBits(DWORD dwEncoding)
1923 {
1924     DWORD i;
1925
1926     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1927     {
1928         CRYPT_BIT_BLOB blob;
1929         BOOL ret;
1930         BYTE *buf = NULL;
1931         DWORD bufSize = 0;
1932
1933         blob.cbData = sizeof(bytesToEncode);
1934         blob.pbData = (BYTE *)bytesToEncode;
1935         blob.cUnusedBits = bits[i].cUnusedBits;
1936         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1937          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1938         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1939         if (buf)
1940         {
1941             ok(bufSize == bits[i].encoded[1] + 2,
1942              "Got unexpected size %d, expected %d\n", bufSize,
1943              bits[i].encoded[1] + 2);
1944             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1945              "Unexpected value\n");
1946             LocalFree(buf);
1947         }
1948     }
1949 }
1950
1951 static void test_decodeBits(DWORD dwEncoding)
1952 {
1953     static const BYTE ber[] = "\x03\x02\x01\xff";
1954     static const BYTE berDecoded = 0xfe;
1955     DWORD i;
1956     BOOL ret;
1957     BYTE *buf = NULL;
1958     DWORD bufSize = 0;
1959
1960     /* normal cases */
1961     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1962     {
1963         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1964          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1965          &bufSize);
1966         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1967         if (buf)
1968         {
1969             CRYPT_BIT_BLOB *blob;
1970
1971             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1972                "Got unexpected size %d\n", bufSize);
1973             blob = (CRYPT_BIT_BLOB *)buf;
1974             ok(blob->cbData == bits[i].cbDecoded,
1975              "Got unexpected length %d, expected %d\n", blob->cbData,
1976              bits[i].cbDecoded);
1977             if (blob->cbData && bits[i].cbDecoded)
1978                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1979                  "Unexpected value\n");
1980             LocalFree(buf);
1981         }
1982     }
1983     /* special case: check that something that's valid in BER but not in DER
1984      * decodes successfully
1985      */
1986     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1987      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1988     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1989     if (buf)
1990     {
1991         CRYPT_BIT_BLOB *blob;
1992
1993         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1994            "Got unexpected size %d\n", bufSize);
1995         blob = (CRYPT_BIT_BLOB *)buf;
1996         ok(blob->cbData == sizeof(berDecoded),
1997            "Got unexpected length %d\n", blob->cbData);
1998         if (blob->cbData)
1999             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2000         LocalFree(buf);
2001     }
2002 }
2003
2004 struct Constraints2
2005 {
2006     CERT_BASIC_CONSTRAINTS2_INFO info;
2007     const BYTE *encoded;
2008 };
2009
2010 static const unsigned char bin59[] = { 0x30,0x00 };
2011 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2012 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2013 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2014 static const struct Constraints2 constraints2[] = {
2015  /* empty constraints */
2016  { { FALSE, FALSE, 0}, bin59 },
2017  /* can be a CA */
2018  { { TRUE,  FALSE, 0}, bin60 },
2019  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2020   * but that's not the case
2021   */
2022  { { FALSE, TRUE,  0}, bin61 },
2023  /* can be a CA and has path length constraints set */
2024  { { TRUE,  TRUE,  1}, bin62 },
2025 };
2026
2027 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2028 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2029  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2030  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2031  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2032 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2033  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2034  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2035  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2036  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2037
2038 static void test_encodeBasicConstraints(DWORD dwEncoding)
2039 {
2040     DWORD i, bufSize = 0;
2041     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2042     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2043      (LPBYTE)encodedDomainName };
2044     BOOL ret;
2045     BYTE *buf = NULL;
2046
2047     /* First test with the simpler info2 */
2048     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2049     {
2050         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2051          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2052          &bufSize);
2053         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2054         if (buf)
2055         {
2056             ok(bufSize == constraints2[i].encoded[1] + 2,
2057              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2058              bufSize);
2059             ok(!memcmp(buf, constraints2[i].encoded,
2060              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2061             LocalFree(buf);
2062         }
2063     }
2064     /* Now test with more complex basic constraints */
2065     info.SubjectType.cbData = 0;
2066     info.fPathLenConstraint = FALSE;
2067     info.cSubtreesConstraint = 0;
2068     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2069      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2070     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2071     if (buf)
2072     {
2073         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2074         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2075          "Unexpected value\n");
2076         LocalFree(buf);
2077     }
2078     /* None of the certs I examined had any subtree constraint, but I test one
2079      * anyway just in case.
2080      */
2081     info.cSubtreesConstraint = 1;
2082     info.rgSubtreesConstraint = &nameBlob;
2083     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2084      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2085     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2086     if (buf)
2087     {
2088         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2089         ok(!memcmp(buf, constraintWithDomainName,
2090          sizeof(constraintWithDomainName)), "Unexpected value\n");
2091         LocalFree(buf);
2092     }
2093     /* FIXME: test encoding with subject type. */
2094 }
2095
2096 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2097
2098 static void test_decodeBasicConstraints(DWORD dwEncoding)
2099 {
2100     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2101      0xff };
2102     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2103     DWORD i;
2104     BOOL ret;
2105     BYTE *buf = NULL;
2106     DWORD bufSize = 0;
2107
2108     /* First test with simpler info2 */
2109     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2110     {
2111         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2112          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2113          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2114         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2115          GetLastError());
2116         if (buf)
2117         {
2118             CERT_BASIC_CONSTRAINTS2_INFO *info =
2119              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2120
2121             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2122              "Unexpected value for item %d\n", i);
2123             LocalFree(buf);
2124         }
2125     }
2126     /* Check with the order of encoded elements inverted */
2127     buf = (PBYTE)1;
2128     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2129      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2130      &bufSize);
2131     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2132      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2133     ok(!buf, "Expected buf to be set to NULL\n");
2134     /* Check with a non-DER bool */
2135     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2136      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2137      (BYTE *)&buf, &bufSize);
2138     ok(ret, "pCryptDecodeObjectEx failed: %08x\n", GetLastError());
2139     if (buf)
2140     {
2141         CERT_BASIC_CONSTRAINTS2_INFO *info =
2142          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2143
2144         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2145         LocalFree(buf);
2146     }
2147     /* Check with a non-basic constraints value */
2148     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2149      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2150      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2151     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2152      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2153     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2154     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2155      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2156      (BYTE *)&buf, &bufSize);
2157     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2158     if (buf)
2159     {
2160         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2161
2162         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2163         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2164         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2165         LocalFree(buf);
2166     }
2167     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2168      constraintWithDomainName, sizeof(constraintWithDomainName),
2169      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2170     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2171     if (buf)
2172     {
2173         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2174
2175         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2176         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2177         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2178         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2179         {
2180             ok(info->rgSubtreesConstraint[0].cbData ==
2181              sizeof(encodedDomainName), "Wrong size %d\n",
2182              info->rgSubtreesConstraint[0].cbData);
2183             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2184              sizeof(encodedDomainName)), "Unexpected value\n");
2185         }
2186         LocalFree(buf);
2187     }
2188 }
2189
2190 /* These are terrible public keys of course, I'm just testing encoding */
2191 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2192 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2193 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2194 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2195 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2196 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2197 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2198 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2199
2200 struct EncodedRSAPubKey
2201 {
2202     const BYTE *modulus;
2203     size_t modulusLen;
2204     const BYTE *encoded;
2205     size_t decodedModulusLen;
2206 };
2207
2208 struct EncodedRSAPubKey rsaPubKeys[] = {
2209     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2210     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2211     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2212     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2213 };
2214
2215 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2216 {
2217     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2218     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2219     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2220     BOOL ret;
2221     BYTE *buf = NULL;
2222     DWORD bufSize = 0, i;
2223
2224     /* Try with a bogus blob type */
2225     hdr->bType = 2;
2226     hdr->bVersion = CUR_BLOB_VERSION;
2227     hdr->reserved = 0;
2228     hdr->aiKeyAlg = CALG_RSA_KEYX;
2229     rsaPubKey->magic = 0x31415352;
2230     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2231     rsaPubKey->pubexp = 65537;
2232     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2233      sizeof(modulus1));
2234
2235     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2236      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2237      &bufSize);
2238     ok(!ret && GetLastError() == E_INVALIDARG,
2239      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2240     /* Now with a bogus reserved field */
2241     hdr->bType = PUBLICKEYBLOB;
2242     hdr->reserved = 1;
2243     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2244      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2245      &bufSize);
2246     if (buf)
2247     {
2248         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2249          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2250         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2251         LocalFree(buf);
2252     }
2253     /* Now with a bogus blob version */
2254     hdr->reserved = 0;
2255     hdr->bVersion = 0;
2256     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2257      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2258      &bufSize);
2259     if (buf)
2260     {
2261         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2262          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2263         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2264         LocalFree(buf);
2265     }
2266     /* And with a bogus alg ID */
2267     hdr->bVersion = CUR_BLOB_VERSION;
2268     hdr->aiKeyAlg = CALG_DES;
2269     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2270      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2271      &bufSize);
2272     if (buf)
2273     {
2274         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2275          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2276         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2277         LocalFree(buf);
2278     }
2279     /* Check a couple of RSA-related OIDs */
2280     hdr->aiKeyAlg = CALG_RSA_KEYX;
2281     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2282      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2283     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2284      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2285     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2286      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2287     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2288      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2289     /* Finally, all valid */
2290     hdr->aiKeyAlg = CALG_RSA_KEYX;
2291     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2292     {
2293         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2294          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2295         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2296          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2297         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2298         if (buf)
2299         {
2300             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2301              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2302              bufSize);
2303             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2304              "Unexpected value\n");
2305             LocalFree(buf);
2306         }
2307     }
2308 }
2309
2310 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2311 {
2312     DWORD i;
2313     LPBYTE buf = NULL;
2314     DWORD bufSize = 0;
2315     BOOL ret;
2316
2317     /* Try with a bad length */
2318     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2319      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2320      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2321     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2322      "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2323     /* Try with a couple of RSA-related OIDs */
2324     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2325      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2326      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2327     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2328      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2329     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2330      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2331      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2332     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2333      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2334     /* Now try success cases */
2335     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2336     {
2337         bufSize = 0;
2338         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2339          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2340          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2341         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2342         if (buf)
2343         {
2344             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2345             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2346
2347             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2348              rsaPubKeys[i].decodedModulusLen,
2349              "Wrong size %d\n", bufSize);
2350             ok(hdr->bType == PUBLICKEYBLOB,
2351              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2352              hdr->bType);
2353             ok(hdr->bVersion == CUR_BLOB_VERSION,
2354              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2355              CUR_BLOB_VERSION, hdr->bVersion);
2356             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2357              hdr->reserved);
2358             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2359              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2360             ok(rsaPubKey->magic == 0x31415352,
2361              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2362             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2363              "Wrong bit len %d\n", rsaPubKey->bitlen);
2364             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2365              rsaPubKey->pubexp);
2366             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2367              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2368              "Unexpected modulus\n");
2369             LocalFree(buf);
2370         }
2371     }
2372 }
2373
2374 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2375  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2376  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2377
2378 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2379  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2380  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2381  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2382
2383 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2384 {
2385     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2386     CRYPT_SEQUENCE_OF_ANY seq;
2387     DWORD i;
2388     BOOL ret;
2389     BYTE *buf = NULL;
2390     DWORD bufSize = 0;
2391
2392     /* Encode a homogeneous sequence */
2393     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2394     {
2395         blobs[i].cbData = ints[i].encoded[1] + 2;
2396         blobs[i].pbData = (BYTE *)ints[i].encoded;
2397     }
2398     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2399     seq.rgValue = blobs;
2400
2401     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2402      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2403     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2404     if (buf)
2405     {
2406         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2407         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2408         LocalFree(buf);
2409     }
2410     /* Change the type of the first element in the sequence, and give it
2411      * another go
2412      */
2413     blobs[0].cbData = times[0].encodedTime[1] + 2;
2414     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2415     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2416      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2417     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2418     if (buf)
2419     {
2420         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2421         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2422          "Unexpected value\n");
2423         LocalFree(buf);
2424     }
2425 }
2426
2427 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2428 {
2429     BOOL ret;
2430     BYTE *buf = NULL;
2431     DWORD bufSize = 0;
2432
2433     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2434      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2435     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2436     if (buf)
2437     {
2438         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2439         DWORD i;
2440
2441         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2442          "Wrong elements %d\n", seq->cValue);
2443         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2444         {
2445             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2446              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2447              seq->rgValue[i].cbData);
2448             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2449              ints[i].encoded[1] + 2), "Unexpected value\n");
2450         }
2451         LocalFree(buf);
2452     }
2453     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2454      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2455      &bufSize);
2456     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2457     if (buf)
2458     {
2459         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2460
2461         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2462          "Wrong elements %d\n", seq->cValue);
2463         /* Just check the first element since it's all that changed */
2464         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2465          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2466          seq->rgValue[0].cbData);
2467         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2468          times[0].encodedTime[1] + 2), "Unexpected value\n");
2469         LocalFree(buf);
2470     }
2471 }
2472
2473 struct encodedExtensions
2474 {
2475     CERT_EXTENSIONS exts;
2476     const BYTE *encoded;
2477 };
2478
2479 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2480 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2481 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2482 static CERT_EXTENSION criticalExt =
2483  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2484 static CERT_EXTENSION nonCriticalExt =
2485  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2486
2487 static const BYTE ext0[] = { 0x30,0x00 };
2488 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2489                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2490 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2491                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2492
2493 static const struct encodedExtensions exts[] = {
2494  { { 0, NULL }, ext0 },
2495  { { 1, &criticalExt }, ext1 },
2496  { { 1, &nonCriticalExt }, ext2 },
2497 };
2498
2499 static void test_encodeExtensions(DWORD dwEncoding)
2500 {
2501     DWORD i;
2502
2503     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2504     {
2505         BOOL ret;
2506         BYTE *buf = NULL;
2507         DWORD bufSize = 0;
2508
2509         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2510          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2511         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2512         if (buf)
2513         {
2514             ok(bufSize == exts[i].encoded[1] + 2,
2515              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2516             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2517              "Unexpected value\n");
2518             LocalFree(buf);
2519         }
2520     }
2521 }
2522
2523 static void test_decodeExtensions(DWORD dwEncoding)
2524 {
2525     DWORD i;
2526
2527     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2528     {
2529         BOOL ret;
2530         BYTE *buf = NULL;
2531         DWORD bufSize = 0;
2532
2533         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2534          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2535          NULL, (BYTE *)&buf, &bufSize);
2536         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2537         if (buf)
2538         {
2539             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2540             DWORD j;
2541
2542             ok(ext->cExtension == exts[i].exts.cExtension,
2543              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2544              ext->cExtension);
2545             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2546             {
2547                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2548                  exts[i].exts.rgExtension[j].pszObjId),
2549                  "Expected OID %s, got %s\n",
2550                  exts[i].exts.rgExtension[j].pszObjId,
2551                  ext->rgExtension[j].pszObjId);
2552                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2553                  exts[i].exts.rgExtension[j].Value.pbData,
2554                  exts[i].exts.rgExtension[j].Value.cbData),
2555                  "Unexpected value\n");
2556             }
2557             LocalFree(buf);
2558         }
2559     }
2560 }
2561
2562 /* MS encodes public key info with a NULL if the algorithm identifier's
2563  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2564  * it encodes them by omitting the algorithm parameters.  This latter approach
2565  * seems more correct, so accept either form.
2566  */
2567 struct encodedPublicKey
2568 {
2569     CERT_PUBLIC_KEY_INFO info;
2570     const BYTE *encoded;
2571     const BYTE *encodedNoNull;
2572     CERT_PUBLIC_KEY_INFO decoded;
2573 };
2574
2575 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2576  0xe, 0xf };
2577 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2578
2579 static const unsigned char bin64[] = {
2580     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2581 static const unsigned char bin65[] = {
2582     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2583 static const unsigned char bin66[] = {
2584     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2585 static const unsigned char bin67[] = {
2586     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2587 static const unsigned char bin68[] = {
2588     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2589     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2590 static const unsigned char bin69[] = {
2591     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2592     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2593 static const unsigned char bin70[] = {
2594     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2595     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2596     0x0f};
2597 static const unsigned char bin71[] = {
2598     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2599     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2600     0x0f};
2601 static unsigned char bin72[] = { 0x05,0x00};
2602
2603 static CHAR oid_bogus[] = "1.2.3",
2604             oid_rsa[]   = szOID_RSA;
2605
2606 static const struct encodedPublicKey pubKeys[] = {
2607  /* with a bogus OID */
2608  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2609   bin64, bin65,
2610   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2611  /* some normal keys */
2612  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2613   bin66, bin67,
2614   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2615  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2616   bin68, bin69,
2617   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2618  /* with add'l parameters--note they must be DER-encoded */
2619  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2620   (BYTE *)aKey, 0 } },
2621   bin70, bin71,
2622   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2623   (BYTE *)aKey, 0 } } },
2624 };
2625
2626 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2627 {
2628     DWORD i;
2629
2630     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2631     {
2632         BOOL ret;
2633         BYTE *buf = NULL;
2634         DWORD bufSize = 0;
2635
2636         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2637          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2638          &bufSize);
2639         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2640         if (buf)
2641         {
2642             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2643              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2644              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2645              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2646             if (bufSize == pubKeys[i].encoded[1] + 2)
2647                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2648                  "Unexpected value\n");
2649             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2650                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2651                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2652             LocalFree(buf);
2653         }
2654     }
2655 }
2656
2657 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2658  const CERT_PUBLIC_KEY_INFO *got)
2659 {
2660     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2661      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2662      got->Algorithm.pszObjId);
2663     ok(expected->Algorithm.Parameters.cbData ==
2664      got->Algorithm.Parameters.cbData,
2665      "Expected parameters of %d bytes, got %d\n",
2666      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2667     if (expected->Algorithm.Parameters.cbData)
2668         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2669          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2670          "Unexpected algorithm parameters\n");
2671     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2672      "Expected public key of %d bytes, got %d\n",
2673      expected->PublicKey.cbData, got->PublicKey.cbData);
2674     if (expected->PublicKey.cbData)
2675         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2676          got->PublicKey.cbData), "Unexpected public key value\n");
2677 }
2678
2679 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2680 {
2681     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2682      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2683      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2684      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2685     DWORD i;
2686     BOOL ret;
2687     BYTE *buf = NULL;
2688     DWORD bufSize = 0;
2689
2690     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2691     {
2692         /* The NULL form decodes to the decoded member */
2693         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2694          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2695          NULL, (BYTE *)&buf, &bufSize);
2696         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2697         if (buf)
2698         {
2699             comparePublicKeyInfo(&pubKeys[i].decoded,
2700              (CERT_PUBLIC_KEY_INFO *)buf);
2701             LocalFree(buf);
2702         }
2703         /* The non-NULL form decodes to the original */
2704         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2705          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2706          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2707         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2708         if (buf)
2709         {
2710             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2711             LocalFree(buf);
2712         }
2713     }
2714     /* Test with bogus (not valid DER) parameters */
2715     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2716      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2717      NULL, (BYTE *)&buf, &bufSize);
2718     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2719      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2720 }
2721
2722 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2723  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2724  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2725  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2726  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2727 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2728  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2729  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2730  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2731  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2732 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2733  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2734  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2735  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2736  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2737 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2738  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2739  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2740  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2741  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2742  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2743  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2744 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2745  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2746  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2747  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2748  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2749  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2750  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2751 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2752  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2753  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2754  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2755  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2756  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2757  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2758  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2759  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2760  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2761 static const BYTE v1CertWithPubKey[] = {
2762 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2763 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2764 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2765 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2766 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2767 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2768 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2769 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2770 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2771 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2772 0x01,0x01 };
2773 static const BYTE v1CertWithPubKeyNoNull[] = {
2774 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2775 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2776 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2777 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2778 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2779 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2780 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2781 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2782 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2783 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2784 static const BYTE v1CertWithSubjectKeyId[] = {
2785 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,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,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2788 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2789 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2790 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2791 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2792 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2793 0x4c,0x61,0x6e,0x67,0x00 };
2794
2795 static const BYTE serialNum[] = { 0x01 };
2796
2797 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2798 {
2799     BOOL ret;
2800     BYTE *buf = NULL;
2801     DWORD size = 0;
2802     CERT_INFO info = { 0 };
2803     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2804     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2805     CERT_EXTENSION ext;
2806
2807     /* Test with NULL pvStructInfo */
2808     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2809      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2810     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2811      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2812     /* Test with a V1 cert */
2813     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2814      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2815     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2816     if (buf)
2817     {
2818         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2819          v1Cert[1] + 2, size);
2820         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2821         LocalFree(buf);
2822     }
2823     /* Test v2 cert */
2824     info.dwVersion = CERT_V2;
2825     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2826      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2827     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2828     if (buf)
2829     {
2830         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2831         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2832         LocalFree(buf);
2833     }
2834     /* Test v3 cert */
2835     info.dwVersion = CERT_V3;
2836     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2837      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2838     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2839     if (buf)
2840     {
2841         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2842         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2843         LocalFree(buf);
2844     }
2845     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2846      * API doesn't prevent it)
2847      */
2848     info.dwVersion = CERT_V1;
2849     info.cExtension = 1;
2850     info.rgExtension = &criticalExt;
2851     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2852      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2853     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2854     if (buf)
2855     {
2856         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2857         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2858         LocalFree(buf);
2859     }
2860     /* test v1 cert with a serial number */
2861     info.SerialNumber.cbData = sizeof(serialNum);
2862     info.SerialNumber.pbData = (BYTE *)serialNum;
2863     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2864      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2865     if (buf)
2866     {
2867         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2868         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2869         LocalFree(buf);
2870     }
2871     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2872     info.Issuer.cbData = sizeof(encodedCommonName);
2873     info.Issuer.pbData = (BYTE *)encodedCommonName;
2874     info.Subject.cbData = sizeof(encodedCommonName);
2875     info.Subject.pbData = (BYTE *)encodedCommonName;
2876     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2877      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2878     if (buf)
2879     {
2880         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2881         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2882         LocalFree(buf);
2883     }
2884     /* Add a public key */
2885     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2886     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2887     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2888     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2889      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2890     if (buf)
2891     {
2892         ok(size == sizeof(v1CertWithPubKey) ||
2893          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2894         if (size == sizeof(v1CertWithPubKey))
2895             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2896         else if (size == sizeof(v1CertWithPubKeyNoNull))
2897             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2898              "Got unexpected value\n");
2899         LocalFree(buf);
2900     }
2901     /* Remove the public key, and add a subject key identifier extension */
2902     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2903     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2904     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2905     ext.pszObjId = oid_subject_key_identifier;
2906     ext.fCritical = FALSE;
2907     ext.Value.cbData = sizeof(octetCommonNameValue);
2908     ext.Value.pbData = (BYTE *)octetCommonNameValue;
2909     info.cExtension = 1;
2910     info.rgExtension = &ext;
2911     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2912      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2913     if (buf)
2914     {
2915         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2916         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2917         LocalFree(buf);
2918     }
2919 }
2920
2921 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2922 {
2923     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2924      v1CertWithConstraints, v1CertWithSerial };
2925     BOOL ret;
2926     BYTE *buf = NULL;
2927     DWORD size = 0, i;
2928
2929     /* Test with NULL pbEncoded */
2930     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2931      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2932     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2933      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2934     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2935      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2936     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2937      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2938     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2939      * minimum a cert must have a non-zero serial number, an issuer, and a
2940      * subject.
2941      */
2942     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2943     {
2944         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2945          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2946          (BYTE *)&buf, &size);
2947         ok(!ret, "Expected failure\n");
2948     }
2949     /* Now check with serial number, subject and issuer specified */
2950     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2951      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2952     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2953     if (buf)
2954     {
2955         CERT_INFO *info = (CERT_INFO *)buf;
2956
2957         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2958         ok(info->SerialNumber.cbData == 1,
2959          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2960         ok(*info->SerialNumber.pbData == *serialNum,
2961          "Expected serial number %d, got %d\n", *serialNum,
2962          *info->SerialNumber.pbData);
2963         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2964          "Wrong size %d\n", info->Issuer.cbData);
2965         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2966          "Unexpected issuer\n");
2967         ok(info->Subject.cbData == sizeof(encodedCommonName),
2968          "Wrong size %d\n", info->Subject.cbData);
2969         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2970          info->Subject.cbData), "Unexpected subject\n");
2971         LocalFree(buf);
2972     }
2973     /* Check again with pub key specified */
2974     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2975      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
2976      (BYTE *)&buf, &size);
2977     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2978     if (buf)
2979     {
2980         CERT_INFO *info = (CERT_INFO *)buf;
2981
2982         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2983         ok(info->SerialNumber.cbData == 1,
2984          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2985         ok(*info->SerialNumber.pbData == *serialNum,
2986          "Expected serial number %d, got %d\n", *serialNum,
2987          *info->SerialNumber.pbData);
2988         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2989          "Wrong size %d\n", info->Issuer.cbData);
2990         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2991          "Unexpected issuer\n");
2992         ok(info->Subject.cbData == sizeof(encodedCommonName),
2993          "Wrong size %d\n", info->Subject.cbData);
2994         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2995          info->Subject.cbData), "Unexpected subject\n");
2996         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
2997          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
2998          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
2999         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3000          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3001         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3002          sizeof(aKey)), "Unexpected public key\n");
3003         LocalFree(buf);
3004     }
3005 }
3006
3007 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3008  0xe, 0xf };
3009
3010 static const BYTE signedBigCert[] = {
3011  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3012  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3013  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3014  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3015  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3016  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3017  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3018  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3019  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3020  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3021  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3022  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3023
3024 static void test_encodeCert(DWORD dwEncoding)
3025 {
3026     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3027      * also that bigCert is a NULL-terminated string, so don't count its
3028      * last byte (otherwise the signed cert won't decode.)
3029      */
3030     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3031      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3032     BOOL ret;
3033     BYTE *buf = NULL;
3034     DWORD bufSize = 0;
3035
3036     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3037      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
3038     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3039     if (buf)
3040     {
3041         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3042         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3043         LocalFree(buf);
3044     }
3045 }
3046
3047 static void test_decodeCert(DWORD dwEncoding)
3048 {
3049     BOOL ret;
3050     BYTE *buf = NULL;
3051     DWORD size = 0;
3052
3053     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3054      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3055     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3056     if (buf)
3057     {
3058         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3059
3060         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3061          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3062         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3063          "Unexpected cert\n");
3064         ok(info->Signature.cbData == sizeof(hash),
3065          "Wrong signature size %d\n", info->Signature.cbData);
3066         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3067          "Unexpected signature\n");
3068         LocalFree(buf);
3069     }
3070     /* A signed cert decodes as a CERT_INFO too */
3071     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3072      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3073     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3074     if (buf)
3075     {
3076         CERT_INFO *info = (CERT_INFO *)buf;
3077
3078         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3079         ok(info->SerialNumber.cbData == 1,
3080          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3081         ok(*info->SerialNumber.pbData == *serialNum,
3082          "Expected serial number %d, got %d\n", *serialNum,
3083          *info->SerialNumber.pbData);
3084         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3085          "Wrong size %d\n", info->Issuer.cbData);
3086         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3087          "Unexpected issuer\n");
3088         ok(info->Subject.cbData == sizeof(encodedCommonName),
3089          "Wrong size %d\n", info->Subject.cbData);
3090         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3091          info->Subject.cbData), "Unexpected subject\n");
3092         LocalFree(buf);
3093     }
3094 }
3095
3096 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3097 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3098  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3099  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3100 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3101  0x00, 0x03 };
3102 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3103  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3104  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3105 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3106  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3107  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3108  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3109  0x2e, 0x6f, 0x72, 0x67 };
3110 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3111  CRL_REASON_AFFILIATION_CHANGED;
3112
3113 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3114 {
3115     CRL_DIST_POINTS_INFO info = { 0 };
3116     CRL_DIST_POINT point = { { 0 } };
3117     CERT_ALT_NAME_ENTRY entry = { 0 };
3118     BOOL ret;
3119     BYTE *buf = NULL;
3120     DWORD size = 0;
3121
3122     /* Test with an empty info */
3123     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3124      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3125     ok(!ret && GetLastError() == E_INVALIDARG,
3126      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3127     /* Test with one empty dist point */
3128     info.cDistPoint = 1;
3129     info.rgDistPoint = &point;
3130     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3131      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3132     if (buf)
3133     {
3134         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3135         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3136         LocalFree(buf);
3137     }
3138     /* A dist point with an invalid name */
3139     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3140     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3141     U(entry).pwszURL = (LPWSTR)nihongoURL;
3142     U(point.DistPointName).FullName.cAltEntry = 1;
3143     U(point.DistPointName).FullName.rgAltEntry = &entry;
3144     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3145      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3146     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3147      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3148     /* The first invalid character is at index 7 */
3149     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3150      "Expected invalid char at index 7, got %d\n",
3151      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3152     /* A dist point with (just) a valid name */
3153     U(entry).pwszURL = (LPWSTR)url;
3154     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3155      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3156     if (buf)
3157     {
3158         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3159         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3160         LocalFree(buf);
3161     }
3162     /* A dist point with (just) reason flags */
3163     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3164     point.ReasonFlags.cbData = sizeof(crlReason);
3165     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3166     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3167      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3168     if (buf)
3169     {
3170         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3171         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3172         LocalFree(buf);
3173     }
3174     /* A dist point with just an issuer */
3175     point.ReasonFlags.cbData = 0;
3176     point.CRLIssuer.cAltEntry = 1;
3177     point.CRLIssuer.rgAltEntry = &entry;
3178     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3179      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3180     if (buf)
3181     {
3182         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3183         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3184         LocalFree(buf);
3185     }
3186     /* A dist point with both a name and an issuer */
3187     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3188     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3189      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3190     if (buf)
3191     {
3192         ok(size == sizeof(distPointWithUrlAndIssuer),
3193          "Wrong size %d\n", size);
3194         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3195         LocalFree(buf);
3196     }
3197 }
3198
3199 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3200 {
3201     BOOL ret;
3202     BYTE *buf = NULL;
3203     DWORD size = 0;
3204     PCRL_DIST_POINTS_INFO info;
3205     PCRL_DIST_POINT point;
3206     PCERT_ALT_NAME_ENTRY entry;
3207
3208     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3209      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3210      (BYTE *)&buf, &size);
3211     if (ret)
3212     {
3213         info = (PCRL_DIST_POINTS_INFO)buf;
3214         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3215          "Wrong size %d\n", size);
3216         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3217          info->cDistPoint);
3218         point = info->rgDistPoint;
3219         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3220          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3221          point->DistPointName.dwDistPointNameChoice);
3222         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3223         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3224         LocalFree(buf);
3225     }
3226     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3227      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3228      (BYTE *)&buf, &size);
3229     if (ret)
3230     {
3231         info = (PCRL_DIST_POINTS_INFO)buf;
3232         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3233          "Wrong size %d\n", size);
3234         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3235          info->cDistPoint);
3236         point = info->rgDistPoint;
3237         ok(point->DistPointName.dwDistPointNameChoice ==
3238          CRL_DIST_POINT_FULL_NAME,
3239          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3240          point->DistPointName.dwDistPointNameChoice);
3241         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3242          "Expected 1 name entry, got %d\n",
3243          U(point->DistPointName).FullName.cAltEntry);
3244         entry = U(point->DistPointName).FullName.rgAltEntry;
3245         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3246          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3247         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
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      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3254      NULL, (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_NO_NAME,
3265          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3266          point->DistPointName.dwDistPointNameChoice);
3267         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3268          "Expected reason length\n");
3269         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3270          "Unexpected reason\n");
3271         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3272         LocalFree(buf);
3273     }
3274     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3275      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3276      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3277     if (ret)
3278     {
3279         info = (PCRL_DIST_POINTS_INFO)buf;
3280         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3281          "Wrong size %d\n", size);
3282         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3283          info->cDistPoint);
3284         point = info->rgDistPoint;
3285         ok(point->DistPointName.dwDistPointNameChoice ==
3286          CRL_DIST_POINT_FULL_NAME,
3287          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3288          point->DistPointName.dwDistPointNameChoice);
3289         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3290          "Expected 1 name entry, got %d\n",
3291          U(point->DistPointName).FullName.cAltEntry);
3292         entry = U(point->DistPointName).FullName.rgAltEntry;
3293         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3294          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3295         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3296         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3297         ok(point->CRLIssuer.cAltEntry == 1,
3298          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3299         entry = point->CRLIssuer.rgAltEntry;
3300         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3301          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3302         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3303         LocalFree(buf);
3304     }
3305 }
3306
3307 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3308 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3309 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3310  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3311  0x67 };
3312
3313 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3314 {
3315     BOOL ret;
3316     BYTE *buf = NULL;
3317     DWORD size = 0;
3318     CRL_ISSUING_DIST_POINT point = { { 0 } };
3319     CERT_ALT_NAME_ENTRY entry;
3320
3321     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3322      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3323     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3324     {
3325         skip("no X509_ISSUING_DIST_POINT encode support\n");
3326         return;
3327     }
3328     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3329      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3330     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3331      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3332     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3333     if (buf)
3334     {
3335         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3336         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3337         LocalFree(buf);
3338     }
3339     /* nonsensical flags */
3340     point.fOnlyContainsUserCerts = TRUE;
3341     point.fOnlyContainsCACerts = TRUE;
3342     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3343      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3344     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3345     if (buf)
3346     {
3347         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3348         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3349         LocalFree(buf);
3350     }
3351     /* unimplemented name type */
3352     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3353     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3354     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3355      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3356     ok(!ret && GetLastError() == E_INVALIDARG,
3357      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3358     /* empty name */
3359     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3360     U(point.DistPointName).FullName.cAltEntry = 0;
3361     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3362      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3363     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3364     if (buf)
3365     {
3366         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3367         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3368         LocalFree(buf);
3369     }
3370     /* name with URL entry */
3371     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3372     U(entry).pwszURL = (LPWSTR)url;
3373     U(point.DistPointName).FullName.cAltEntry = 1;
3374     U(point.DistPointName).FullName.rgAltEntry = &entry;
3375     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3376      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3377     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3378     if (buf)
3379     {
3380         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3381         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3382         LocalFree(buf);
3383     }
3384 }
3385
3386 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3387  const CERT_ALT_NAME_ENTRY *got)
3388 {
3389     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3390      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3391      got->dwAltNameChoice);
3392     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3393     {
3394         switch (got->dwAltNameChoice)
3395         {
3396         case CERT_ALT_NAME_RFC822_NAME:
3397         case CERT_ALT_NAME_DNS_NAME:
3398         case CERT_ALT_NAME_EDI_PARTY_NAME:
3399         case CERT_ALT_NAME_URL:
3400         case CERT_ALT_NAME_REGISTERED_ID:
3401             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3402              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3403              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3404              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3405              "Unexpected name\n");
3406             break;
3407         case CERT_ALT_NAME_X400_ADDRESS:
3408         case CERT_ALT_NAME_DIRECTORY_NAME:
3409         case CERT_ALT_NAME_IP_ADDRESS:
3410             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3411                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3412             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3413                        U(*got).IPAddress.cbData), "Unexpected value\n");
3414             break;
3415         }
3416     }
3417 }
3418
3419 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3420  const CERT_ALT_NAME_INFO *got)
3421 {
3422     DWORD i;
3423
3424     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3425      expected->cAltEntry, got->cAltEntry);
3426     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3427         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3428 }
3429
3430 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3431  const CRL_DIST_POINT_NAME *got)
3432 {
3433     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3434      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3435     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3436         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3437 }
3438
3439 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3440  const CRL_ISSUING_DIST_POINT *got)
3441 {
3442     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3443     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3444      "Unexpected fOnlyContainsUserCerts\n");
3445     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3446      "Unexpected fOnlyContainsCACerts\n");
3447     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3448      "Unexpected reason flags\n");
3449     ok(got->fIndirectCRL == expected->fIndirectCRL,
3450      "Unexpected fIndirectCRL\n");
3451 }
3452
3453 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3454 {
3455     BOOL ret;
3456     BYTE *buf = NULL;
3457     DWORD size = 0;
3458     CRL_ISSUING_DIST_POINT point = { { 0 } };
3459
3460     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3461      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3462      (BYTE *)&buf, &size);
3463     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3464     {
3465         skip("no X509_ISSUING_DIST_POINT decode support\n");
3466         return;
3467     }
3468     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3469     if (ret)
3470     {
3471         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3472         LocalFree(buf);
3473     }
3474     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3475      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3476      (BYTE *)&buf, &size);
3477     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3478     if (ret)
3479     {
3480         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3481         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3482         LocalFree(buf);
3483     }
3484     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3485      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3486      (BYTE *)&buf, &size);
3487     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3488     if (ret)
3489     {
3490         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3491         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3492         U(point.DistPointName).FullName.cAltEntry = 0;
3493         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3494         LocalFree(buf);
3495     }
3496     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3497      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3498     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3499     if (ret)
3500     {
3501         CERT_ALT_NAME_ENTRY entry;
3502
3503         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3504         U(entry).pwszURL = (LPWSTR)url;
3505         U(point.DistPointName).FullName.cAltEntry = 1;
3506         U(point.DistPointName).FullName.rgAltEntry = &entry;
3507         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3508         LocalFree(buf);
3509     }
3510 }
3511
3512 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3513  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3514  0x30, 0x5a };
3515 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3516  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3517  0x30, 0x30, 0x30, 0x30, 0x5a };
3518 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3519  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3520  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3521  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3522  0x5a };
3523 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3524  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3525  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3526  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3527  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3528  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3529 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3530  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3531  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3532  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3533  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3534  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3535 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3536  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3537  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3538  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3539  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3540  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3541  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3542 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3543  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3544  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3545  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3546  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3547  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3548  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3549 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3550  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3551  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3552  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3553  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3554  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3555  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3556 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3557  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3558  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3559  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3560  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3561  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3562  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3563
3564 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3565 {
3566     BOOL ret;
3567     BYTE *buf = NULL;
3568     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3569     DWORD size = 0;
3570     CRL_INFO info = { 0 };
3571     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3572     CERT_EXTENSION ext;
3573
3574     /* Test with a V1 CRL */
3575     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3576      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3577     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3578     if (buf)
3579     {
3580         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3581         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3582         LocalFree(buf);
3583     }
3584     /* Test v2 CRL */
3585     info.dwVersion = CRL_V2;
3586     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3587      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3588     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3589     if (buf)
3590     {
3591         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3592          v2CRL[1] + 2, size);
3593         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3594         LocalFree(buf);
3595     }
3596     /* v1 CRL with a name */
3597     info.dwVersion = CRL_V1;
3598     info.Issuer.cbData = sizeof(encodedCommonName);
3599     info.Issuer.pbData = (BYTE *)encodedCommonName;
3600     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3601      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3602     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3603     if (buf)
3604     {
3605         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3606         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3607         LocalFree(buf);
3608     }
3609     /* v1 CRL with a name and a NULL entry pointer */
3610     info.cCRLEntry = 1;
3611     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3612      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3613     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3614      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3615     /* now set an empty entry */
3616     info.rgCRLEntry = &entry;
3617     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3618      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3619     if (buf)
3620     {
3621         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3622          "Wrong size %d\n", size);
3623         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3624          "Got unexpected value\n");
3625         LocalFree(buf);
3626     }
3627     /* an entry with a serial number */
3628     entry.SerialNumber.cbData = sizeof(serialNum);
3629     entry.SerialNumber.pbData = (BYTE *)serialNum;
3630     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3631      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3632     if (buf)
3633     {
3634         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3635          "Wrong size %d\n", size);
3636         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3637          "Got unexpected value\n");
3638         LocalFree(buf);
3639     }
3640     /* an entry with an extension */
3641     entry.cExtension = 1;
3642     entry.rgExtension = &criticalExt;
3643     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3644      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3645     ok(ret, "pCryptEncodeObjectEx failed: %08x\n", GetLastError());
3646     if (buf)
3647     {
3648         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3649         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3650         LocalFree(buf);
3651     }
3652     /* a CRL with an extension */
3653     entry.cExtension = 0;
3654     info.cExtension = 1;
3655     info.rgExtension = &criticalExt;
3656     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3657      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3658     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3659     if (buf)
3660     {
3661         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3662         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3663         LocalFree(buf);
3664     }
3665     /* a v2 CRL with an extension, this time non-critical */
3666     info.dwVersion = CRL_V2;
3667     info.rgExtension = &nonCriticalExt;
3668     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3669      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3670     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3671     if (buf)
3672     {
3673         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3674         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3675         LocalFree(buf);
3676     }
3677     /* a v2 CRL with an issuing dist point extension */
3678     ext.pszObjId = oid_issuing_dist_point;
3679     ext.fCritical = TRUE;
3680     ext.Value.cbData = sizeof(urlIDP);
3681     ext.Value.pbData = (LPBYTE)urlIDP;
3682     entry.rgExtension = &ext;
3683     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3684      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3685     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3686     if (buf)
3687     {
3688         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3689         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3690         LocalFree(buf);
3691     }
3692 }
3693
3694 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3695  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3696  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3697  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3698  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3699  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3700  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3701  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3702  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3703  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3704  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3705  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3706  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3707  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3708  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3709  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3710  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3711  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3712  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3713  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3714  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3715  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3716  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3717  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3718  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3719  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3720  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3721  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3722  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3723  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3724  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3725  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3726  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3727  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3728  0xcd };
3729 static const BYTE verisignCRLWithLotsOfEntries[] = {
3730 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3731 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3732 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3733 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3734 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3735 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3736 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3737 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3738 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3739 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3740 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3741 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3742 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3743 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3744 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3745 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3746 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3747 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3748 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3749 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3750 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3751 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3752 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3753 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3754 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3755 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3756 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3757 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3758 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3759 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3760 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3761 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3762 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3763 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3764 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3765 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3766 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3767 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3768 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3769 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3770 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3771 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3772 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3773 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3774 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3775 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3776 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3777 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3778 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3779 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3780 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3781 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3782 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3783 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3784 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3785 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3786 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3787 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3788 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3789 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3790 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3791 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3792 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3793 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3794 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3795 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3796 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3797 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3798 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3799 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3800 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3801 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3802 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3803 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3804 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3805 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3806 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3807 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3808 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3809 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3810 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3811 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3812 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3813 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3814 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3815 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3816 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3817 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3818 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3819 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3820 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3821 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3822 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3823 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3824 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3825 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3826 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3827 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3828 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3829 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3830 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3831 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3832 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3833 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3834 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3835 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3836 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3837 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3838 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3839 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3840 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3841 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3842 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3843 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3844 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3845 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3846 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3847 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3848 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3849 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3850 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3851 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3852 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3853 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3854 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3855 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3856 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3857 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3858 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3859 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3860 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3861 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3862 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3863 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3864 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3865 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3866 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3867 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3868 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3869 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3870 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3871 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3872 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3873 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3874 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3875 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3876 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3877 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3878 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3879 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3880 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3881 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3882 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3883 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3884 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3885 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3886 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3887 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3888 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3889 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3890 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3891 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3892 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3893 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3894 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3895 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3896 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3897 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3898 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3899 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3900 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3901 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3902 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3903 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3904 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3905 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3906 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3907 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3908 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3909 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3910 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3911 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3912 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3913 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3914 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3915 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3916 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3917 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3918 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3919 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3920 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3921 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3922 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3923 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3924 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3925 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3926 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3927 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3928 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3929 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3930 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3931 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3932 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3933 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3934 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3935 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3936 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3937 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3938 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3939 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3940 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3941 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3942 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3943 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3944 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3945 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3946 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3947 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3948 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3949 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3950 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3951 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3952 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3953 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3954 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3955 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3956 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3957 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3958 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3959 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3960 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3961 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3962 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3963 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3964 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3965 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3966 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3967 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3968 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3969 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3970 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3971 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3972 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3973 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3974 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3975 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3976 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3977 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3978 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3979 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3980 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3981 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3982 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3983 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3984 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3985 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3986 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3987 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3988 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3989 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3990 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3991 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3992 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3993 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3994 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3995 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3996 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3997 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3998 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3999 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4000 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4001 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4002 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4003 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4004 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4005 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4006 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4007 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4008 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4009 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4010 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4011 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4012 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4013 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4014 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4015 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4016 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4017 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4018 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4019 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4020 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4021 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4022 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4023 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4024 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4025 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4026 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4027 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4028 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4029 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4030 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4031 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4032 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4033 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4034 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4035 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4036 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4037 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4038 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4039 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4040 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4041 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4042 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4043 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4044 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4045 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4046 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4047 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4048 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4049 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4050 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4051 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4052 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4053 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4054 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4055 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4056 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4057 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4058 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4059 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4060 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4061 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4062 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4063 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4064 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4065 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4066 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4067 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4068 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4069 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4070 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4071 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4072 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4073 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4074 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4075 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4076 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4077 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4078 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4079 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4080 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4081 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4082 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4083 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4084 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4085 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4086 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4087 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4088 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4089 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4090 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4091 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4092 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4093 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4094 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4095 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4096 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4097 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4098 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4099 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4100 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4101 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4102 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4103 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4104 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4105 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4106 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4107 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4108 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4109 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4110 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4111 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4112 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4113 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4114 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4115 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4116 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4117 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4118 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4119 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4120 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4121 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4122 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4123 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4124 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4125 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4126 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4127 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4128 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4129 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4130 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4131 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4132 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4133 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4134 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4135 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4136 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4137 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4138 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4139 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4140 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4141 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4142 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4143 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4144 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4145 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4146 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4147 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4148 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4149 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4150 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4151 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4152 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4153 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4154 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4155 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4156 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4157 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4158 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4159 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4160 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4161 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4162 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4163 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4164 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4165 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4166 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4167 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4168 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4169 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4170 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4171 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4172 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4173 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4174 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4175 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4176 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4177 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4178 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4179 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4180 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4181 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4182 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4183 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4184 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4185 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4186 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4187 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4188 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4189 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4190 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4191 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4192 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4193 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4194 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4195 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4196 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4197 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4198 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4199 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4200 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4201 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4202 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4203 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4204 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4205 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4206 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4207 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4208 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4209 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4210 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4211 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4212 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4213 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4214 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4215 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4216 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4217 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4218 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4219 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4220 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4221 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4222 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4223 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4224 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4225 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4226 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4227 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4228 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4229 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4230 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4231 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4232 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4233 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4234 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4235 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4236 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4237 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4238
4239 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4240 {
4241     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4242     BOOL ret;
4243     BYTE *buf = NULL;
4244     DWORD size = 0, i;
4245
4246     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4247     {
4248         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4249          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4250          (BYTE *)&buf, &size);
4251         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4252          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4253     }
4254     /* at a minimum, a CRL must contain an issuer: */
4255     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4256      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4257      (BYTE *)&buf, &size);
4258     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4259     if (buf)
4260     {
4261         CRL_INFO *info = (CRL_INFO *)buf;
4262
4263         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4264         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4265          info->cCRLEntry);
4266         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4267          "Wrong issuer size %d\n", info->Issuer.cbData);
4268         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4269          "Unexpected issuer\n");
4270         LocalFree(buf);
4271     }
4272     /* check decoding with an empty CRL entry */
4273     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4274      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4275      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4276     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4277      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4278     /* with a real CRL entry */
4279     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4280      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4281      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4282     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4283     if (buf)
4284     {
4285         CRL_INFO *info = (CRL_INFO *)buf;
4286         CRL_ENTRY *entry;
4287
4288         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4289         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4290          info->cCRLEntry);
4291         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4292         entry = info->rgCRLEntry;
4293         ok(entry->SerialNumber.cbData == 1,
4294          "Expected serial number size 1, got %d\n",
4295          entry->SerialNumber.cbData);
4296         ok(*entry->SerialNumber.pbData == *serialNum,
4297          "Expected serial number %d, got %d\n", *serialNum,
4298          *entry->SerialNumber.pbData);
4299         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4300          "Wrong issuer size %d\n", info->Issuer.cbData);
4301         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4302          "Unexpected issuer\n");
4303         LocalFree(buf);
4304     }
4305     /* a real CRL from verisign that has extensions */
4306     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4307      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4308      NULL, (BYTE *)&buf, &size);
4309     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4310     if (buf)
4311     {
4312         CRL_INFO *info = (CRL_INFO *)buf;
4313         CRL_ENTRY *entry;
4314
4315         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4316         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4317          info->cCRLEntry);
4318         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4319         entry = info->rgCRLEntry;
4320         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4321          info->cExtension);
4322         LocalFree(buf);
4323     }
4324     /* another real CRL from verisign that has lots of entries */
4325     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4326      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4327      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4328     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4329     if (buf)
4330     {
4331         CRL_INFO *info = (CRL_INFO *)buf;
4332
4333         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4334         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4335          info->cCRLEntry);
4336         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4337          info->cExtension);
4338         LocalFree(buf);
4339     }
4340     /* and finally, with an extension */
4341     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4342      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4343      NULL, (BYTE *)&buf, &size);
4344     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4345     if (buf)
4346     {
4347         CRL_INFO *info = (CRL_INFO *)buf;
4348         CRL_ENTRY *entry;
4349
4350         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4351         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4352          info->cCRLEntry);
4353         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4354         entry = info->rgCRLEntry;
4355         ok(entry->SerialNumber.cbData == 1,
4356          "Expected serial number size 1, got %d\n",
4357          entry->SerialNumber.cbData);
4358         ok(*entry->SerialNumber.pbData == *serialNum,
4359          "Expected serial number %d, got %d\n", *serialNum,
4360          *entry->SerialNumber.pbData);
4361         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4362          "Wrong issuer size %d\n", info->Issuer.cbData);
4363         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4364          "Unexpected issuer\n");
4365         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4366          info->cExtension);
4367         LocalFree(buf);
4368     }
4369     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4370      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4371      NULL, (BYTE *)&buf, &size);
4372     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4373     if (buf)
4374     {
4375         CRL_INFO *info = (CRL_INFO *)buf;
4376
4377         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4378          info->cExtension);
4379         LocalFree(buf);
4380     }
4381     /* And again, with an issuing dist point */
4382     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4383      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4384      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4385     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4386     if (buf)
4387     {
4388         CRL_INFO *info = (CRL_INFO *)buf;
4389
4390         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4391          info->cExtension);
4392         LocalFree(buf);
4393     }
4394 }
4395
4396 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4397  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4398 static const BYTE encodedUsage[] = {
4399  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4400  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4401  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4402
4403 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4404 {
4405     BOOL ret;
4406     BYTE *buf = NULL;
4407     DWORD size = 0;
4408     CERT_ENHKEY_USAGE usage;
4409
4410     /* Test with empty usage */
4411     usage.cUsageIdentifier = 0;
4412     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4413      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4414     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4415     if (buf)
4416     {
4417         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4418         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4419         LocalFree(buf);
4420     }
4421     /* Test with a few usages */
4422     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4423     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4424     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4425      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4426     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4427     if (buf)
4428     {
4429         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4430         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4431         LocalFree(buf);
4432     }
4433 }
4434
4435 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4436 {
4437     BOOL ret;
4438     LPBYTE buf = NULL;
4439     DWORD size = 0;
4440
4441     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4442      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4443      (BYTE *)&buf, &size);
4444     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4445     if (buf)
4446     {
4447         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4448
4449         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4450          "Wrong size %d\n", size);
4451         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4452          usage->cUsageIdentifier);
4453         LocalFree(buf);
4454     }
4455     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4456      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4457      (BYTE *)&buf, &size);
4458     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4459     if (buf)
4460     {
4461         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4462         DWORD i;
4463
4464         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4465          "Wrong size %d\n", size);
4466         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4467          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4468         for (i = 0; i < usage->cUsageIdentifier; i++)
4469             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4470              "Expected OID %s, got %s\n", keyUsages[i],
4471              usage->rgpszUsageIdentifier[i]);
4472         LocalFree(buf);
4473     }
4474 }
4475
4476 static BYTE keyId[] = { 1,2,3,4 };
4477 static const BYTE authorityKeyIdWithId[] = {
4478  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4479 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4480  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4481  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4482 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4483
4484 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4485 {
4486     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4487     BOOL ret;
4488     BYTE *buf = NULL;
4489     DWORD size = 0;
4490
4491     /* Test with empty id */
4492     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4493      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4494     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4495     if (buf)
4496     {
4497         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4498         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4499         LocalFree(buf);
4500     }
4501     /* With just a key id */
4502     info.KeyId.cbData = sizeof(keyId);
4503     info.KeyId.pbData = keyId;
4504     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4505      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4506     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4507     if (buf)
4508     {
4509         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4510         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4511         LocalFree(buf);
4512     }
4513     /* With just an issuer */
4514     info.KeyId.cbData = 0;
4515     info.CertIssuer.cbData = sizeof(encodedCommonName);
4516     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4517     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4518      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4519     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4520     if (buf)
4521     {
4522         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4523          size);
4524         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4525         LocalFree(buf);
4526     }
4527     /* With just a serial number */
4528     info.CertIssuer.cbData = 0;
4529     info.CertSerialNumber.cbData = sizeof(serialNum);
4530     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4531     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4532      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4533     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4534     if (buf)
4535     {
4536         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4537          size);
4538         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4539         LocalFree(buf);
4540     }
4541 }
4542
4543 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4544 {
4545     BOOL ret;
4546     LPBYTE buf = NULL;
4547     DWORD size = 0;
4548
4549     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4550      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4551      (BYTE *)&buf, &size);
4552     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4553     if (buf)
4554     {
4555         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4556
4557         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4558          size);
4559         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4560         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4561         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4562         LocalFree(buf);
4563     }
4564     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4565      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4566      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4567     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4568     if (buf)
4569     {
4570         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4571
4572         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4573          size);
4574         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4575         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4576          "Unexpected key id\n");
4577         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4578         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4579         LocalFree(buf);
4580     }
4581     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4582      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4583      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4584     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4585     if (buf)
4586     {
4587         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4588
4589         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4590          size);
4591         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4592         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4593          "Unexpected issuer len\n");
4594         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4595          sizeof(encodedCommonName)), "Unexpected issuer\n");
4596         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4597         LocalFree(buf);
4598     }
4599     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4600      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4601      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4602     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4603     if (buf)
4604     {
4605         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4606
4607         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4608          size);
4609         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4610         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4611         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4612          "Unexpected serial number len\n");
4613         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4614          "Unexpected serial number\n");
4615         LocalFree(buf);
4616     }
4617 }
4618
4619 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4620  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4621  0x6f,0x72,0x67 };
4622
4623 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4624 {
4625     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4626     CERT_ALT_NAME_ENTRY entry = { 0 };
4627     BOOL ret;
4628     BYTE *buf = NULL;
4629     DWORD size = 0;
4630
4631     /* Test with empty id */
4632     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4633      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4634     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4635     if (buf)
4636     {
4637         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4638         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4639         LocalFree(buf);
4640     }
4641     /* With just a key id */
4642     info.KeyId.cbData = sizeof(keyId);
4643     info.KeyId.pbData = keyId;
4644     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4645      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4646     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4647     if (buf)
4648     {
4649         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4650          size);
4651         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4652         LocalFree(buf);
4653     }
4654     /* With a bogus issuer name */
4655     info.KeyId.cbData = 0;
4656     info.AuthorityCertIssuer.cAltEntry = 1;
4657     info.AuthorityCertIssuer.rgAltEntry = &entry;
4658     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4659      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4660     ok(!ret && GetLastError() == E_INVALIDARG,
4661      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4662     /* With an issuer name */
4663     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4664     U(entry).pwszURL = (LPWSTR)url;
4665     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4666      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4667     ok(ret, "pCryptEncodeObjectEx failed: %08x\n", GetLastError());
4668     if (buf)
4669     {
4670         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4671          size);
4672         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4673          "Unexpected value\n");
4674         LocalFree(buf);
4675     }
4676     /* With just a serial number */
4677     info.AuthorityCertIssuer.cAltEntry = 0;
4678     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4679     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4680     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4681      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4682     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4683     if (buf)
4684     {
4685         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4686          size);
4687         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4688         LocalFree(buf);
4689     }
4690 }
4691
4692 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4693 {
4694     BOOL ret;
4695     LPBYTE buf = NULL;
4696     DWORD size = 0;
4697
4698     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4699      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4700      (BYTE *)&buf, &size);
4701     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4702     if (buf)
4703     {
4704         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4705
4706         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4707          size);
4708         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4709         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4710          "Expected no issuer name entries\n");
4711         ok(info->AuthorityCertSerialNumber.cbData == 0,
4712          "Expected no serial number\n");
4713         LocalFree(buf);
4714     }
4715     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4716      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4717      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4718     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4719     if (buf)
4720     {
4721         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4722
4723         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4724          size);
4725         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4726         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4727          "Unexpected key id\n");
4728         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4729          "Expected no issuer name entries\n");
4730         ok(info->AuthorityCertSerialNumber.cbData == 0,
4731          "Expected no serial number\n");
4732         LocalFree(buf);
4733     }
4734     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4735      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4736      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4737     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4738     if (buf)
4739     {
4740         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4741
4742         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4743          size);
4744         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4745         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4746          "Expected 1 issuer entry, got %d\n",
4747          info->AuthorityCertIssuer.cAltEntry);
4748         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4749          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4750          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4751         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4752          url), "Unexpected URL\n");
4753         ok(info->AuthorityCertSerialNumber.cbData == 0,
4754          "Expected no serial number\n");
4755         LocalFree(buf);
4756     }
4757     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4758      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4759      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4760     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4761     if (buf)
4762     {
4763         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4764
4765         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4766          size);
4767         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4768         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4769          "Expected no issuer name entries\n");
4770         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4771          "Unexpected serial number len\n");
4772         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4773          sizeof(serialNum)), "Unexpected serial number\n");
4774         LocalFree(buf);
4775     }
4776 }
4777
4778 static const BYTE authorityInfoAccessWithUrl[] = {
4779 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4780 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4781 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4782 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4783 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4784 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4785
4786 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4787 {
4788     static char oid1[] = "1.2.3";
4789     static char oid2[] = "1.5.6";
4790     BOOL ret;
4791     BYTE *buf = NULL;
4792     DWORD size = 0;
4793     CERT_ACCESS_DESCRIPTION accessDescription[2];
4794     CERT_AUTHORITY_INFO_ACCESS aia;
4795
4796     memset(accessDescription, 0, sizeof(accessDescription));
4797     aia.cAccDescr = 0;
4798     aia.rgAccDescr = NULL;
4799     /* Having no access descriptions is allowed */
4800     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4801      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4802     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4803     if (buf)
4804     {
4805         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4806         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4807         LocalFree(buf);
4808         buf = NULL;
4809     }
4810     /* It can't have an empty access method */
4811     aia.cAccDescr = 1;
4812     aia.rgAccDescr = accessDescription;
4813     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4814      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4815     ok(!ret && GetLastError() == E_INVALIDARG,
4816      "expected E_INVALIDARG, got %08x\n", GetLastError());
4817     /* It can't have an empty location */
4818     accessDescription[0].pszAccessMethod = oid1;
4819     SetLastError(0xdeadbeef);
4820     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4821      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4822     ok(!ret && GetLastError() == E_INVALIDARG,
4823      "expected E_INVALIDARG, got %08x\n", GetLastError());
4824     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4825     accessDescription[0].AccessLocation.pwszURL = (LPWSTR)url;
4826     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4827      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4828     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4829     if (buf)
4830     {
4831         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4832          size);
4833         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4834          "unexpected value\n");
4835         LocalFree(buf);
4836         buf = NULL;
4837     }
4838     accessDescription[1].pszAccessMethod = oid2;
4839     accessDescription[1].AccessLocation.dwAltNameChoice =
4840      CERT_ALT_NAME_IP_ADDRESS;
4841     accessDescription[1].AccessLocation.IPAddress.cbData =
4842      sizeof(encodedIPAddr);
4843     accessDescription[1].AccessLocation.IPAddress.pbData =
4844      (LPBYTE)encodedIPAddr;
4845     aia.cAccDescr = 2;
4846     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4847      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4848     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4849     if (buf)
4850     {
4851         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4852          "unexpected size %d\n", size);
4853         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4854          "unexpected value\n");
4855         LocalFree(buf);
4856         buf = NULL;
4857     }
4858 }
4859
4860 static void compareAuthorityInfoAccess(LPCSTR header,
4861  const CERT_AUTHORITY_INFO_ACCESS *expected,
4862  const CERT_AUTHORITY_INFO_ACCESS *got)
4863 {
4864     DWORD i;
4865
4866     ok(expected->cAccDescr == got->cAccDescr,
4867      "%s: expected %d access descriptions, got %d\n", header,
4868      expected->cAccDescr, got->cAccDescr);
4869     for (i = 0; i < expected->cAccDescr; i++)
4870     {
4871         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4872          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4873          header, i, expected->rgAccDescr[i].pszAccessMethod,
4874          got->rgAccDescr[i].pszAccessMethod);
4875         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4876          &got->rgAccDescr[i].AccessLocation);
4877     }
4878 }
4879
4880 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4881 {
4882     static char oid1[] = "1.2.3";
4883     static char oid2[] = "1.5.6";
4884     BOOL ret;
4885     LPBYTE buf = NULL;
4886     DWORD size = 0;
4887
4888     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4889      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4890      (BYTE *)&buf, &size);
4891     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4892     if (buf)
4893     {
4894         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4895
4896         compareAuthorityInfoAccess("empty AIA", &aia,
4897          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4898         LocalFree(buf);
4899         buf = NULL;
4900     }
4901     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4902      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4903      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4904     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4905     if (buf)
4906     {
4907         CERT_ACCESS_DESCRIPTION accessDescription;
4908         CERT_AUTHORITY_INFO_ACCESS aia;
4909
4910         accessDescription.pszAccessMethod = oid1;
4911         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4912         accessDescription.AccessLocation.pwszURL = (LPWSTR)url;
4913         aia.cAccDescr = 1;
4914         aia.rgAccDescr = &accessDescription;
4915         compareAuthorityInfoAccess("AIA with URL", &aia,
4916          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4917         LocalFree(buf);
4918         buf = NULL;
4919     }
4920     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4921      authorityInfoAccessWithUrlAndIPAddr,
4922      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
4923      NULL, (BYTE *)&buf, &size);
4924     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4925     if (buf)
4926     {
4927         CERT_ACCESS_DESCRIPTION accessDescription[2];
4928         CERT_AUTHORITY_INFO_ACCESS aia;
4929
4930         accessDescription[0].pszAccessMethod = oid1;
4931         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4932         accessDescription[0].AccessLocation.pwszURL = (LPWSTR)url;
4933         accessDescription[1].pszAccessMethod = oid2;
4934         accessDescription[1].AccessLocation.dwAltNameChoice =
4935          CERT_ALT_NAME_IP_ADDRESS;
4936         accessDescription[1].AccessLocation.IPAddress.cbData =
4937          sizeof(encodedIPAddr);
4938         accessDescription[1].AccessLocation.IPAddress.pbData =
4939          (LPBYTE)encodedIPAddr;
4940         aia.cAccDescr = 2;
4941         aia.rgAccDescr = accessDescription;
4942         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
4943          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4944         LocalFree(buf);
4945         buf = NULL;
4946     }
4947 }
4948
4949 static const BYTE emptyCTL[] = {
4950 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4951 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4952 static const BYTE emptyCTLWithVersion1[] = {
4953 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
4954 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4955 static const BYTE ctlWithUsageIdentifier[] = {
4956 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
4957 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4958 static const BYTE ctlWithListIdentifier[] = {
4959 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
4960 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4961 static const BYTE ctlWithSequenceNumber[] = {
4962 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
4963 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4964 static const BYTE ctlWithThisUpdate[] = {
4965 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
4966 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4967 static const BYTE ctlWithThisAndNextUpdate[] = {
4968 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
4969 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
4970 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4971 static const BYTE ctlWithAlgId[] = {
4972 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4973 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
4974 static const BYTE ctlWithBogusEntry[] = {
4975 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4976 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
4977 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
4978 static const BYTE ctlWithOneEntry[] = {
4979 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4980 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
4981 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
4982 static const BYTE ctlWithTwoEntries[] = {
4983 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4984 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
4985 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
4986 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
4987 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4988
4989 static void test_encodeCTL(DWORD dwEncoding)
4990 {
4991     static char oid1[] = "1.2.3";
4992     static char oid2[] = "1.5.6";
4993     char *pOid1 = oid1;
4994     BOOL ret;
4995     BYTE *buf = NULL;
4996     DWORD size = 0;
4997     CTL_INFO info;
4998     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
4999     CTL_ENTRY ctlEntry[2];
5000     CRYPT_ATTRIBUTE attr1, attr2;
5001     CRYPT_ATTR_BLOB value1, value2;
5002
5003     memset(&info, 0, sizeof(info));
5004     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5005      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5006     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5007     if (buf)
5008     {
5009         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5010         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5011         LocalFree(buf);
5012         buf = NULL;
5013     }
5014     info.dwVersion = 1;
5015     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5016      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5017     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5018     if (buf)
5019     {
5020         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5021         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5022         LocalFree(buf);
5023         buf = NULL;
5024     }
5025     info.dwVersion = 0;
5026     info.SubjectUsage.cUsageIdentifier = 1;
5027     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5028     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5029      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5030     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5031     if (buf)
5032     {
5033         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5034          size);
5035         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5036         LocalFree(buf);
5037         buf = NULL;
5038     }
5039     info.SubjectUsage.cUsageIdentifier = 0;
5040     info.ListIdentifier.cbData = sizeof(serialNum);
5041     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5042     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5043      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5044     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5045     if (buf)
5046     {
5047         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5048         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5049         LocalFree(buf);
5050         buf = NULL;
5051     }
5052     info.ListIdentifier.cbData = 0;
5053     info.SequenceNumber.cbData = sizeof(serialNum);
5054     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5055     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5056      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5057     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5058     if (buf)
5059     {
5060         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5061          size);
5062         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5063         LocalFree(buf);
5064         buf = NULL;
5065     }
5066     info.SequenceNumber.cbData = 0;
5067     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5068     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5069      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5070     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5071     if (buf)
5072     {
5073         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5074         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5075         LocalFree(buf);
5076         buf = NULL;
5077     }
5078     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5079     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5080      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5081     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5082     if (buf)
5083     {
5084         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5085          size);
5086         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5087         LocalFree(buf);
5088         buf = NULL;
5089     }
5090     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5091     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5092     info.SubjectAlgorithm.pszObjId = oid2;
5093     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5094      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5095     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5096     if (buf)
5097     {
5098         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5099         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5100         LocalFree(buf);
5101         buf = NULL;
5102     }
5103     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5104      * (see tests below) but it'll encode fine.
5105      */
5106     info.SubjectAlgorithm.pszObjId = NULL;
5107     value1.cbData = sizeof(serialNum);
5108     value1.pbData = (LPBYTE)serialNum;
5109     attr1.pszObjId = oid1;
5110     attr1.cValue = 1;
5111     attr1.rgValue = &value1;
5112     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5113     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5114     ctlEntry[0].cAttribute = 1;
5115     ctlEntry[0].rgAttribute = &attr1;
5116     info.cCTLEntry = 1;
5117     info.rgCTLEntry = ctlEntry;
5118     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5119      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5120     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5121     if (buf)
5122     {
5123         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5124         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5125         LocalFree(buf);
5126         buf = NULL;
5127     }
5128     value1.cbData = sizeof(emptySequence);
5129     value1.pbData = (LPBYTE)emptySequence;
5130     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5131      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5132     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5133     if (buf)
5134     {
5135         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5136         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5137         LocalFree(buf);
5138         buf = NULL;
5139     }
5140     value2.cbData = sizeof(encodedIPAddr);
5141     value2.pbData = (LPBYTE)encodedIPAddr;
5142     attr2.pszObjId = oid2;
5143     attr2.cValue = 1;
5144     attr2.rgValue = &value2;
5145     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5146     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5147     ctlEntry[1].cAttribute = 1;
5148     ctlEntry[1].rgAttribute = &attr2;
5149     info.cCTLEntry = 2;
5150     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5151      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5152     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5153     if (buf)
5154     {
5155         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5156         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5157         LocalFree(buf);
5158         buf = NULL;
5159     }
5160 }
5161
5162 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5163  const CTL_INFO *got)
5164 {
5165     DWORD i, j, k;
5166
5167     ok(expected->dwVersion == got->dwVersion,
5168      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5169      got->dwVersion);
5170     ok(expected->SubjectUsage.cUsageIdentifier ==
5171      got->SubjectUsage.cUsageIdentifier,
5172      "%s: expected %d usage identifiers, got %d\n", header,
5173      expected->SubjectUsage.cUsageIdentifier,
5174      got->SubjectUsage.cUsageIdentifier);
5175     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5176         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5177          got->SubjectUsage.rgpszUsageIdentifier[i]),
5178          "%s[%d]: expected %s, got %s\n", header, i,
5179          expected->SubjectUsage.rgpszUsageIdentifier[i],
5180          got->SubjectUsage.rgpszUsageIdentifier[i]);
5181     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5182      "%s: expected list identifier of %d bytes, got %d\n", header,
5183      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5184     if (expected->ListIdentifier.cbData)
5185         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5186          expected->ListIdentifier.cbData),
5187          "%s: unexpected list identifier value\n", header);
5188     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5189      "%s: expected sequence number of %d bytes, got %d\n", header,
5190      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5191     if (expected->SequenceNumber.cbData)
5192         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5193          expected->SequenceNumber.cbData),
5194          "%s: unexpected sequence number value\n", header);
5195     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5196      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5197      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5198      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5199     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5200      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5201      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5202      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5203     if (expected->SubjectAlgorithm.pszObjId &&
5204      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5205         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5206          expected->SubjectAlgorithm.pszObjId);
5207     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5208         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5209          got->SubjectAlgorithm.pszObjId),
5210          "%s: expected subject algorithm %s, got %s\n", header,
5211          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5212     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5213      got->SubjectAlgorithm.Parameters.cbData,
5214      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5215      expected->SubjectAlgorithm.Parameters.cbData,
5216      got->SubjectAlgorithm.Parameters.cbData);
5217     if (expected->SubjectAlgorithm.Parameters.cbData)
5218         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5219          got->SubjectAlgorithm.Parameters.pbData,
5220          expected->SubjectAlgorithm.Parameters.cbData),
5221          "%s: unexpected subject algorithm parameter value\n", header);
5222     ok(expected->cCTLEntry == got->cCTLEntry,
5223      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5224      got->cCTLEntry);
5225     for (i = 0; i < expected->cCTLEntry; i++)
5226     {
5227         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5228          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5229          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5230          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5231          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5232         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5233             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5234              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5235              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5236              "%s[%d]: unexpected subject identifier value\n",
5237              header, i);
5238         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5239         {
5240             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5241              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5242              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5243              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5244              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5245             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5246             {
5247                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5248                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5249                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5250                  header, i, j, k,
5251                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5252                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5253                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5254                     ok(!memcmp(
5255                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5256                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5257                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5258                      "%s[%d][%d][%d]: unexpected value\n",
5259                      header, i, j, k);
5260             }
5261         }
5262     }
5263     ok(expected->cExtension == got->cExtension,
5264      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5265      got->cExtension);
5266     for (i = 0; i < expected->cExtension; i++)
5267     {
5268         ok(!strcmp(expected->rgExtension[i].pszObjId,
5269          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5270          header, i, expected->rgExtension[i].pszObjId,
5271          got->rgExtension[i].pszObjId);
5272         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5273          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5274          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5275         ok(expected->rgExtension[i].Value.cbData ==
5276          got->rgExtension[i].Value.cbData,
5277          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5278          header, i, expected->rgExtension[i].Value.cbData,
5279          got->rgExtension[i].Value.cbData);
5280         if (expected->rgExtension[i].Value.cbData)
5281             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5282              got->rgExtension[i].Value.pbData,
5283              expected->rgExtension[i].Value.cbData),
5284              "%s[%d]: unexpected extension value\n", header, i);
5285     }
5286 }
5287
5288 static const BYTE signedCTL[] = {
5289 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5290 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5291 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5292 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5293 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5294 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5295 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5296 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5297 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5298 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5299 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5300 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5301 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5302 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5303 static const BYTE signedCTLWithCTLInnerContent[] = {
5304 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5305 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5306 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5307 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5308 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5309 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5310 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5311 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5312 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5313 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5314 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5315 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5316 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5317 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5318 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5319 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5320 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5321 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5322 0x57,0x6c,0x0b,0x47,0xb8 };
5323
5324 static void test_decodeCTL(DWORD dwEncoding)
5325 {
5326     static char oid1[] = "1.2.3";
5327     static char oid2[] = "1.5.6";
5328     static BYTE nullData[] = { 5,0 };
5329     char *pOid1 = oid1;
5330     BOOL ret;
5331     BYTE *buf = NULL;
5332     DWORD size = 0;
5333     CTL_INFO info;
5334     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5335     CTL_ENTRY ctlEntry[2];
5336     CRYPT_ATTRIBUTE attr1, attr2;
5337     CRYPT_ATTR_BLOB value1, value2;
5338
5339     memset(&info, 0, sizeof(info));
5340     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5341      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5342     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5343     if (buf)
5344     {
5345         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5346         LocalFree(buf);
5347         buf = NULL;
5348     }
5349     info.dwVersion = 1;
5350     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5351      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
5352      &size);
5353     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5354     if (buf)
5355     {
5356         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5357         LocalFree(buf);
5358         buf = NULL;
5359     }
5360     info.dwVersion = 0;
5361     info.SubjectUsage.cUsageIdentifier = 1;
5362     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5363     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5364      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5365      (BYTE *)&buf, &size);
5366     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5367     if (buf)
5368     {
5369         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5370         LocalFree(buf);
5371         buf = NULL;
5372     }
5373     info.SubjectUsage.cUsageIdentifier = 0;
5374     info.ListIdentifier.cbData = sizeof(serialNum);
5375     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5376     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5377      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5378      (BYTE *)&buf, &size);
5379     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5380     if (buf)
5381     {
5382         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5383         LocalFree(buf);
5384         buf = NULL;
5385     }
5386     info.ListIdentifier.cbData = 0;
5387     info.SequenceNumber.cbData = sizeof(serialNum);
5388     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5389     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5390      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL,
5391      (BYTE *)&buf, &size);
5392     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5393     if (buf)
5394     {
5395         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5396         LocalFree(buf);
5397         buf = NULL;
5398     }
5399     info.SequenceNumber.cbData = 0;
5400     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5401     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5402      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5403      (BYTE *)&buf, &size);
5404     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5405     if (buf)
5406     {
5407         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5408         LocalFree(buf);
5409         buf = NULL;
5410     }
5411     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5412     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5413      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5414      (BYTE *)&buf, &size);
5415     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5416     if (buf)
5417     {
5418         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5419         LocalFree(buf);
5420         buf = NULL;
5421     }
5422     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5423     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5424     info.SubjectAlgorithm.pszObjId = oid2;
5425     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5426     info.SubjectAlgorithm.Parameters.pbData = nullData;
5427     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5428      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL,
5429      (BYTE *)&buf, &size);
5430     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5431     if (buf)
5432     {
5433         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5434         LocalFree(buf);
5435         buf = NULL;
5436     }
5437     SetLastError(0xdeadbeef);
5438     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5439      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5440      (BYTE *)&buf, &size);
5441     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT),
5442      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5443      GetLastError());
5444     info.SubjectAlgorithm.Parameters.cbData = 0;
5445     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5446     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5447     info.SubjectAlgorithm.pszObjId = oid2;
5448     info.SubjectAlgorithm.pszObjId = NULL;
5449     value1.cbData = sizeof(emptySequence);
5450     value1.pbData = (LPBYTE)emptySequence;
5451     attr1.pszObjId = oid1;
5452     attr1.cValue = 1;
5453     attr1.rgValue = &value1;
5454     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5455     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5456     ctlEntry[0].cAttribute = 1;
5457     ctlEntry[0].rgAttribute = &attr1;
5458     info.cCTLEntry = 1;
5459     info.rgCTLEntry = ctlEntry;
5460     SetLastError(0xdeadbeef);
5461     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5462      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5463      (BYTE *)&buf, &size);
5464     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5465     if (buf)
5466     {
5467         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5468         LocalFree(buf);
5469         buf = NULL;
5470     }
5471     value2.cbData = sizeof(encodedIPAddr);
5472     value2.pbData = (LPBYTE)encodedIPAddr;
5473     attr2.pszObjId = oid2;
5474     attr2.cValue = 1;
5475     attr2.rgValue = &value2;
5476     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5477     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5478     ctlEntry[1].cAttribute = 1;
5479     ctlEntry[1].rgAttribute = &attr2;
5480     info.cCTLEntry = 2;
5481     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5482      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL,
5483      (BYTE *)&buf, &size);
5484     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5485     if (buf)
5486     {
5487         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5488         LocalFree(buf);
5489         buf = NULL;
5490     }
5491     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5492     SetLastError(0xdeadbeef);
5493     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5494      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5495     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
5496      "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
5497     SetLastError(0xdeadbeef);
5498     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5499      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5500      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5501     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
5502      "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
5503 }
5504
5505 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5506 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5507  0x03,0,0,0,0,0,0 };
5508 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5509  0xa0,0x01,0x01 };
5510 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5511  0x03,0x02,0x01,0x01 };
5512 static BYTE bogusDER[] = { 1 };
5513
5514 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5515 {
5516     BOOL ret;
5517     BYTE *buf = NULL;
5518     DWORD size = 0;
5519     CRYPT_CONTENT_INFO info = { 0 };
5520     char oid1[] = "1.2.3";
5521
5522     SetLastError(0xdeadbeef);
5523     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5524      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5525     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5526      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5527     SetLastError(0xdeadbeef);
5528     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5529      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5530     ok(!ret && GetLastError() == E_INVALIDARG,
5531      "Expected E_INVALIDARG, got %x\n", GetLastError());
5532     info.pszObjId = oid1;
5533     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5534      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5535     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5536     if (buf)
5537     {
5538         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5539         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5540         LocalFree(buf);
5541     }
5542     info.Content.pbData = bogusDER;
5543     info.Content.cbData = sizeof(bogusDER);
5544     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5545      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5546     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5547     if (buf)
5548     {
5549         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5550         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5551         LocalFree(buf);
5552     }
5553     info.Content.pbData = (BYTE *)ints[0].encoded;
5554     info.Content.cbData = ints[0].encoded[1] + 2;
5555     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5556      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5557     if (buf)
5558     {
5559         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5560         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5561         LocalFree(buf);
5562     }
5563 }
5564
5565 static const BYTE indefiniteSignedPKCSContent[] = {
5566 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5567 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5568 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5569 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5570 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5571 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5572 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5573 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5574 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5575 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5576 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5577 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5578 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5579 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5580 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5581 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5582 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5583 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5584 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5585 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5586 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5587 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5588 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5589 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5590 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5591 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5592 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5593 0x00,0x00,0x00,0x00,0x00,0x00 };
5594
5595 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5596 {
5597     BOOL ret;
5598     LPBYTE buf = NULL;
5599     DWORD size = 0;
5600     CRYPT_CONTENT_INFO *info;
5601
5602     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5603      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5604      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5605     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5606     if (buf)
5607     {
5608         info = (CRYPT_CONTENT_INFO *)buf;
5609
5610         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5611          info->pszObjId);
5612         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5613          info->Content.cbData);
5614         LocalFree(buf);
5615     }
5616     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5617      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5618      0, NULL, NULL, &size);
5619     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5620     SetLastError(0xdeadbeef);
5621     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5622      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5623      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5624     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5625      * I doubt an app depends on that.
5626      */
5627     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5628      GetLastError() == CRYPT_E_ASN1_CORRUPT),
5629      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5630      GetLastError());
5631     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5632      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5633      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5634     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5635     if (buf)
5636     {
5637         info = (CRYPT_CONTENT_INFO *)buf;
5638
5639         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5640          info->pszObjId);
5641         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5642          "Unexpected size %d\n", info->Content.cbData);
5643         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5644          info->Content.cbData), "Unexpected value\n");
5645         LocalFree(buf);
5646     }
5647     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5648      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5649      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5650     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5651     if (buf)
5652     {
5653         info = (CRYPT_CONTENT_INFO *)buf;
5654
5655         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5656          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5657         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5658          info->Content.cbData);
5659         LocalFree(buf);
5660     }
5661 }
5662
5663 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5664  0x00 };
5665 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5666  0x01 };
5667 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5668  0x02,0x01,0x01 };
5669
5670 static void test_encodePKCSAttribute(DWORD dwEncoding)
5671 {
5672     CRYPT_ATTRIBUTE attr = { 0 };
5673     BOOL ret;
5674     LPBYTE buf = NULL;
5675     DWORD size = 0;
5676     CRYPT_ATTR_BLOB blob;
5677     char oid[] = "1.2.3";
5678
5679     SetLastError(0xdeadbeef);
5680     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5681      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5682     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5683      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5684     SetLastError(0xdeadbeef);
5685     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5686      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5687     ok(!ret && GetLastError() == E_INVALIDARG,
5688      "Expected E_INVALIDARG, got %x\n", GetLastError());
5689     attr.pszObjId = oid;
5690     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5691      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5692     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5693     if (buf)
5694     {
5695         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5696         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5697         LocalFree(buf);
5698     }
5699     blob.cbData = sizeof(bogusDER);
5700     blob.pbData = bogusDER;
5701     attr.cValue = 1;
5702     attr.rgValue = &blob;
5703     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5704      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5705     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5706     if (buf)
5707     {
5708         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5709         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5710         LocalFree(buf);
5711     }
5712     blob.pbData = (BYTE *)ints[0].encoded;
5713     blob.cbData = ints[0].encoded[1] + 2;
5714     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5715      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5716     if (buf)
5717     {
5718         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5719         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5720         LocalFree(buf);
5721     }
5722 }
5723
5724 static void test_decodePKCSAttribute(DWORD dwEncoding)
5725 {
5726     BOOL ret;
5727     LPBYTE buf = NULL;
5728     DWORD size = 0;
5729     CRYPT_ATTRIBUTE *attr;
5730
5731     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5732      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5733      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5734     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5735     if (buf)
5736     {
5737         attr = (CRYPT_ATTRIBUTE *)buf;
5738
5739         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5740          attr->pszObjId);
5741         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5742         LocalFree(buf);
5743     }
5744     SetLastError(0xdeadbeef);
5745     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5746      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5747      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5748     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5749      * I doubt an app depends on that.
5750      */
5751     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5752      GetLastError() == CRYPT_E_ASN1_CORRUPT),
5753      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5754      GetLastError());
5755     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5756      intPKCSAttr, sizeof(intPKCSAttr),
5757      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5758     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5759     if (buf)
5760     {
5761         attr = (CRYPT_ATTRIBUTE *)buf;
5762
5763         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5764          attr->pszObjId);
5765         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5766         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5767          "Unexpected size %d\n", attr->rgValue[0].cbData);
5768         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5769          attr->rgValue[0].cbData), "Unexpected value\n");
5770         LocalFree(buf);
5771     }
5772 }
5773
5774 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5775 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5776  0x2a,0x03,0x31,0x00 };
5777 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5778  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5779
5780 static void test_encodePKCSAttributes(DWORD dwEncoding)
5781 {
5782     CRYPT_ATTRIBUTES attributes = { 0 };
5783     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5784     CRYPT_ATTR_BLOB blob;
5785     BOOL ret;
5786     LPBYTE buf = NULL;
5787     DWORD size = 0;
5788     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5789
5790     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5791      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5792     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5793     if (buf)
5794     {
5795         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5796         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5797         LocalFree(buf);
5798     }
5799     attributes.cAttr = 1;
5800     attributes.rgAttr = attr;
5801     SetLastError(0xdeadbeef);
5802     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5803      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5804     ok(!ret && GetLastError() == E_INVALIDARG,
5805      "Expected E_INVALIDARG, got %x\n", GetLastError());
5806     attr[0].pszObjId = oid1;
5807     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5808      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5809     if (buf)
5810     {
5811         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5812         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5813         LocalFree(buf);
5814     }
5815     attr[1].pszObjId = oid2;
5816     attr[1].cValue = 1;
5817     attr[1].rgValue = &blob;
5818     blob.pbData = (BYTE *)ints[0].encoded;
5819     blob.cbData = ints[0].encoded[1] + 2;
5820     attributes.cAttr = 2;
5821     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5822      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5823     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5824     if (buf)
5825     {
5826         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5827         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5828         LocalFree(buf);
5829     }
5830 }
5831
5832 static void test_decodePKCSAttributes(DWORD dwEncoding)
5833 {
5834     BOOL ret;
5835     LPBYTE buf = NULL;
5836     DWORD size = 0;
5837     CRYPT_ATTRIBUTES *attributes;
5838
5839     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5840      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5841      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5842     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5843     if (buf)
5844     {
5845         attributes = (CRYPT_ATTRIBUTES *)buf;
5846         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5847          attributes->cAttr);
5848         LocalFree(buf);
5849     }
5850     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5851      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5852      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5853     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5854     if (buf)
5855     {
5856         attributes = (CRYPT_ATTRIBUTES *)buf;
5857         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5858          attributes->cAttr);
5859         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5860          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5861         ok(attributes->rgAttr[0].cValue == 0,
5862          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5863         LocalFree(buf);
5864     }
5865     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5866      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5867      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5868     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5869     if (buf)
5870     {
5871         attributes = (CRYPT_ATTRIBUTES *)buf;
5872         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5873          attributes->cAttr);
5874         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5875          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5876         ok(attributes->rgAttr[0].cValue == 0,
5877          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5878         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5879          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5880         ok(attributes->rgAttr[1].cValue == 1,
5881          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5882         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5883          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5884         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5885          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5886         LocalFree(buf);
5887     }
5888 }
5889
5890 static const BYTE singleCapability[] = {
5891 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5892 static const BYTE twoCapabilities[] = {
5893 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5894 static const BYTE singleCapabilitywithNULL[] = {
5895 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5896
5897 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
5898 {
5899     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5900     BOOL ret;
5901     LPBYTE buf = NULL;
5902     DWORD size = 0;
5903     CRYPT_SMIME_CAPABILITY capability[2];
5904     CRYPT_SMIME_CAPABILITIES capabilities;
5905
5906     /* An empty capabilities is allowed */
5907     capabilities.cCapability = 0;
5908     ret = CryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5909      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5910     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5911     if (buf)
5912     {
5913         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5914         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5915         LocalFree(buf);
5916     }
5917     /* A non-empty capabilities with an empty capability (lacking an OID) is
5918      * not allowed
5919      */
5920     capability[0].pszObjId = NULL;
5921     capability[0].Parameters.cbData = 0;
5922     capabilities.cCapability = 1;
5923     capabilities.rgCapability = capability;
5924     SetLastError(0xdeadbeef);
5925     ret = CryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5926      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5927     ok(!ret && GetLastError() == E_INVALIDARG,
5928      "expected E_INVALIDARG, got %08x\n", GetLastError());
5929     capability[0].pszObjId = oid1;
5930     ret = CryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5931      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5932     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5933     if (buf)
5934     {
5935         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
5936         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
5937         LocalFree(buf);
5938     }
5939     capability[1].pszObjId = oid2;
5940     capability[1].Parameters.cbData = 0;
5941     capabilities.cCapability = 2;
5942     ret = CryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5943      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5944     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5945     if (buf)
5946     {
5947         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
5948         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
5949         LocalFree(buf);
5950     }
5951 }
5952
5953 static void compareSMimeCapabilities(LPCSTR header,
5954  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
5955 {
5956     DWORD i;
5957
5958     ok(got->cCapability == expected->cCapability,
5959      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
5960      got->cCapability);
5961     for (i = 0; i < expected->cCapability; i++)
5962     {
5963         ok(!strcmp(expected->rgCapability[i].pszObjId,
5964          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5965          header, i, expected->rgCapability[i].pszObjId,
5966          got->rgCapability[i].pszObjId);
5967         ok(expected->rgCapability[i].Parameters.cbData ==
5968          got->rgCapability[i].Parameters.cbData,
5969          "%s[%d]: expected %d bytes, got %d\n", header, i,
5970          expected->rgCapability[i].Parameters.cbData,
5971          got->rgCapability[i].Parameters.cbData);
5972         if (expected->rgCapability[i].Parameters.cbData)
5973             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
5974              got->rgCapability[i].Parameters.pbData,
5975              expected->rgCapability[i].Parameters.cbData),
5976              "%s[%d]: unexpected value\n", header, i);
5977     }
5978 }
5979
5980 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
5981 {
5982     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5983     BOOL ret;
5984     DWORD size = 0;
5985     CRYPT_SMIME_CAPABILITY capability[2];
5986     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
5987
5988     SetLastError(0xdeadbeef);
5989     ret = CryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5990      emptySequence, sizeof(emptySequence),
5991      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
5992     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5993     if (ret)
5994     {
5995         capabilities.cCapability = 0;
5996         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
5997         LocalFree(ptr);
5998     }
5999     SetLastError(0xdeadbeef);
6000     ret = CryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6001      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6002      (BYTE *)&ptr, &size);
6003     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6004     if (ret)
6005     {
6006         capability[0].pszObjId = oid1;
6007         capability[0].Parameters.cbData = 0;
6008         capabilities.cCapability = 1;
6009         capabilities.rgCapability = capability;
6010         compareSMimeCapabilities("single capability", &capabilities, ptr);
6011         LocalFree(ptr);
6012     }
6013     SetLastError(0xdeadbeef);
6014     ret = CryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6015      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6016      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6017     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6018     if (ret)
6019     {
6020         BYTE NULLparam[] = {0x05, 0x00};
6021         capability[0].pszObjId = oid1;
6022         capability[0].Parameters.cbData = 2;
6023         capability[0].Parameters.pbData = NULLparam;
6024         capabilities.cCapability = 1;
6025         capabilities.rgCapability = capability;
6026         compareSMimeCapabilities("single capability with NULL", &capabilities,
6027          ptr);
6028         LocalFree(ptr);
6029     }
6030     SetLastError(0xdeadbeef);
6031     ret = CryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6032     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6033     (BYTE *)&ptr, &size);
6034     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6035     if (ret)
6036     {
6037         capability[0].Parameters.cbData = 0;
6038         capability[1].pszObjId = oid2;
6039         capability[1].Parameters.cbData = 0;
6040         capabilities.cCapability = 2;
6041         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6042         LocalFree(ptr);
6043     }
6044 }
6045
6046 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6047  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6048  0x67 };
6049 static const BYTE minimalPKCSSigner[] = {
6050  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6051  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6052  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6053 static const BYTE PKCSSignerWithSerial[] = {
6054  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6055  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6056  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6057  0x00 };
6058 static const BYTE PKCSSignerWithHashAlgo[] = {
6059  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6060  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6061  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6062  0x00,0x04,0x00 };
6063 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6064  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6065  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6066  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6067  0x06,0x05,0x00,0x04,0x00 };
6068 static const BYTE PKCSSignerWithHash[] = {
6069  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6070  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6071  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6072  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6073  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6074 static const BYTE PKCSSignerWithAuthAttr[] = {
6075 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6076 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6077 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6078 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6079 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6080 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6081 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6082
6083 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6084 {
6085     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6086     BOOL ret;
6087     LPBYTE buf = NULL;
6088     DWORD size = 0;
6089     CMSG_SIGNER_INFO info = { 0 };
6090     char oid_common_name[] = szOID_COMMON_NAME;
6091     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6092      (LPBYTE)encodedCommonName };
6093     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6094
6095     SetLastError(0xdeadbeef);
6096     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6097      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6098     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6099     {
6100         skip("no PKCS7_SIGNER_INFO encode support\n");
6101         return;
6102     }
6103     ok(!ret && GetLastError() == E_INVALIDARG,
6104      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6105     /* To be encoded, a signer must have an issuer at least, and the encoding
6106      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6107      * see decoding tests.)
6108      */
6109     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6110     info.Issuer.pbData = encodedCommonNameNoNull;
6111     SetLastError(0xdeadbeef);
6112     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6113      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6114     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6115         ok(!ret && GetLastError() == E_INVALIDARG,
6116          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6117     else
6118     {
6119         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6120         if (buf)
6121         {
6122             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6123             if (size == sizeof(minimalPKCSSigner))
6124                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6125             else
6126                 ok(0, "Unexpected value\n");
6127             LocalFree(buf);
6128         }
6129     }
6130     info.SerialNumber.cbData = sizeof(serialNum);
6131     info.SerialNumber.pbData = (BYTE *)serialNum;
6132     SetLastError(0xdeadbeef);
6133     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6134      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6135     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6136         ok(!ret && GetLastError() == E_INVALIDARG,
6137          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6138     else
6139     {
6140         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6141         if (buf)
6142         {
6143             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6144              size);
6145             if (size == sizeof(PKCSSignerWithSerial))
6146                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6147                  "Unexpected value\n");
6148             else
6149                 ok(0, "Unexpected value\n");
6150             LocalFree(buf);
6151         }
6152     }
6153     info.HashAlgorithm.pszObjId = oid1;
6154     SetLastError(0xdeadbeef);
6155     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6156      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6157     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6158         ok(!ret && GetLastError() == E_INVALIDARG,
6159          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6160     else
6161     {
6162         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6163         if (buf)
6164         {
6165             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6166              size);
6167             if (size == sizeof(PKCSSignerWithHashAlgo))
6168                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6169                  "Unexpected value\n");
6170             else
6171                 ok(0, "Unexpected value\n");
6172             LocalFree(buf);
6173         }
6174     }
6175     info.HashEncryptionAlgorithm.pszObjId = oid2;
6176     SetLastError(0xdeadbeef);
6177     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6178      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6179     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6180         ok(!ret && GetLastError() == E_INVALIDARG,
6181          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6182     else
6183     {
6184         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6185         if (buf)
6186         {
6187             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6188              "Unexpected size %d\n", size);
6189             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6190                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6191                  "Unexpected value\n");
6192             else
6193                 ok(0, "Unexpected value\n");
6194             LocalFree(buf);
6195         }
6196     }
6197     info.EncryptedHash.cbData = sizeof(hash);
6198     info.EncryptedHash.pbData = (BYTE *)hash;
6199     SetLastError(0xdeadbeef);
6200     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6201      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6202     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6203         ok(!ret && GetLastError() == E_INVALIDARG,
6204          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6205     else
6206     {
6207         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6208         if (buf)
6209         {
6210             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6211              size);
6212             if (size == sizeof(PKCSSignerWithHash))
6213                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6214                  "Unexpected value\n");
6215             else
6216                 ok(0, "Unexpected value\n");
6217             LocalFree(buf);
6218         }
6219     }
6220     info.AuthAttrs.cAttr = 1;
6221     info.AuthAttrs.rgAttr = &attr;
6222     SetLastError(0xdeadbeef);
6223     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6224      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6225     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6226         ok(!ret && GetLastError() == E_INVALIDARG,
6227          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6228     else
6229     {
6230         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6231         if (buf)
6232         {
6233             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6234              size);
6235             if (size == sizeof(PKCSSignerWithAuthAttr))
6236                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6237                  "Unexpected value\n");
6238             else
6239                 ok(0, "Unexpected value\n");
6240             LocalFree(buf);
6241         }
6242     }
6243 }
6244
6245 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6246 {
6247     BOOL ret;
6248     LPBYTE buf = NULL;
6249     DWORD size = 0;
6250     CMSG_SIGNER_INFO *info;
6251
6252     /* A PKCS signer can't be decoded without a serial number. */
6253     SetLastError(0xdeadbeef);
6254     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6255      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6256      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6257     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
6258      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6259     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6260      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6261      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6262     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6263     if (buf)
6264     {
6265         info = (CMSG_SIGNER_INFO *)buf;
6266         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6267          info->dwVersion);
6268         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6269          "Unexpected size %d\n", info->Issuer.cbData);
6270         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6271          info->Issuer.cbData), "Unexpected value\n");
6272         ok(info->SerialNumber.cbData == sizeof(serialNum),
6273          "Unexpected size %d\n", info->SerialNumber.cbData);
6274         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6275          "Unexpected value\n");
6276         LocalFree(buf);
6277     }
6278     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6279      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6280      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6281     if (buf)
6282     {
6283         info = (CMSG_SIGNER_INFO *)buf;
6284         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6285          info->dwVersion);
6286         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6287          "Unexpected size %d\n", info->Issuer.cbData);
6288         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6289          info->Issuer.cbData), "Unexpected value\n");
6290         ok(info->SerialNumber.cbData == sizeof(serialNum),
6291          "Unexpected size %d\n", info->SerialNumber.cbData);
6292         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6293          "Unexpected value\n");
6294         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6295          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6296         LocalFree(buf);
6297     }
6298     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6299      PKCSSignerWithHashAndEncryptionAlgo,
6300      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6301      NULL, (BYTE *)&buf, &size);
6302     if (buf)
6303     {
6304         info = (CMSG_SIGNER_INFO *)buf;
6305         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6306          info->dwVersion);
6307         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6308          "Unexpected size %d\n", info->Issuer.cbData);
6309         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6310          info->Issuer.cbData), "Unexpected value\n");
6311         ok(info->SerialNumber.cbData == sizeof(serialNum),
6312          "Unexpected size %d\n", info->SerialNumber.cbData);
6313         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6314          "Unexpected value\n");
6315         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6316          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6317         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6318          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6319         LocalFree(buf);
6320     }
6321     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6322      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6323      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6324     if (buf)
6325     {
6326         info = (CMSG_SIGNER_INFO *)buf;
6327         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6328          info->dwVersion);
6329         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6330          "Unexpected size %d\n", info->Issuer.cbData);
6331         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6332          info->Issuer.cbData), "Unexpected value\n");
6333         ok(info->SerialNumber.cbData == sizeof(serialNum),
6334          "Unexpected size %d\n", info->SerialNumber.cbData);
6335         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6336          "Unexpected value\n");
6337         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6338          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6339         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6340          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6341         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6342          info->EncryptedHash.cbData);
6343         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6344          "Unexpected value\n");
6345         LocalFree(buf);
6346     }
6347     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6348      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6349      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6350     if (buf)
6351     {
6352         info = (CMSG_SIGNER_INFO *)buf;
6353         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6354          info->AuthAttrs.cAttr);
6355         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6356          "Expected %s, got %s\n", szOID_COMMON_NAME,
6357          info->AuthAttrs.rgAttr[0].pszObjId);
6358         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6359          info->AuthAttrs.rgAttr[0].cValue);
6360         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6361          sizeof(encodedCommonName), "Unexpected size %d\n",
6362          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6363         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6364          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6365         LocalFree(buf);
6366     }
6367 }
6368
6369 static const BYTE CMSSignerWithKeyId[] = {
6370 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6371 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6372
6373 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6374 {
6375     BOOL ret;
6376     LPBYTE buf = NULL;
6377     DWORD size = 0;
6378     CMSG_CMS_SIGNER_INFO info = { 0 };
6379     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6380
6381     SetLastError(0xdeadbeef);
6382     ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6383      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6384     ok(!ret && GetLastError() == E_INVALIDARG,
6385      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6386     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6387     SetLastError(0xdeadbeef);
6388     ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6389      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6390     ok(!ret, "Expected failure, got %d\n", ret);
6391     ok(GetLastError() == E_INVALIDARG,
6392        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6393     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6394      * be a key id or a issuer serial number with at least the issuer set, and
6395      * the encoding must include PKCS_7_ASN_ENCODING.
6396      * (That isn't enough to be decoded, see decoding tests.)
6397      */
6398     info.SignerId.IssuerSerialNumber.Issuer.cbData =
6399      sizeof(encodedCommonNameNoNull);
6400     info.SignerId.IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6401     SetLastError(0xdeadbeef);
6402     ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6403      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6404     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6405         ok(!ret && GetLastError() == E_INVALIDARG,
6406          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6407     else
6408     {
6409         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6410         if (buf)
6411         {
6412             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6413             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6414             LocalFree(buf);
6415         }
6416     }
6417     info.SignerId.IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6418     info.SignerId.IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6419     SetLastError(0xdeadbeef);
6420     ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6421      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6422     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6423         ok(!ret && GetLastError() == E_INVALIDARG,
6424          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6425     else
6426     {
6427         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6428         if (buf)
6429         {
6430             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6431              size);
6432             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6433             LocalFree(buf);
6434         }
6435     }
6436     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6437     info.SignerId.KeyId.cbData = sizeof(serialNum);
6438     info.SignerId.KeyId.pbData = (BYTE *)serialNum;
6439     SetLastError(0xdeadbeef);
6440     ret = CryptEncodeObjectEx(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(CMSSignerWithKeyId), "Unexpected size %d\n",
6451              size);
6452             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6453             LocalFree(buf);
6454         }
6455     }
6456     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6457      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6458      * (see RFC 3852, section 5.3.)
6459      */
6460     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6461     info.SignerId.HashId.cbData = sizeof(hash);
6462     info.SignerId.HashId.pbData = (BYTE *)hash;
6463     SetLastError(0xdeadbeef);
6464     ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6465      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6466     ok(!ret && GetLastError() == E_INVALIDARG,
6467      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6468     /* Now with a hash algo */
6469     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6470     info.SignerId.IssuerSerialNumber.Issuer.cbData =
6471      sizeof(encodedCommonNameNoNull);
6472     info.SignerId.IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6473     info.HashAlgorithm.pszObjId = oid1;
6474     SetLastError(0xdeadbeef);
6475     ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6476      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6477     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6478         ok(!ret && GetLastError() == E_INVALIDARG,
6479          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6480     else
6481     {
6482         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6483         if (buf)
6484         {
6485             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6486              size);
6487             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6488              "Unexpected value\n");
6489             LocalFree(buf);
6490         }
6491     }
6492     info.HashEncryptionAlgorithm.pszObjId = oid2;
6493     SetLastError(0xdeadbeef);
6494     ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6495      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6496     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6497         ok(!ret && GetLastError() == E_INVALIDARG,
6498          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6499     else
6500     {
6501         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6502         if (buf)
6503         {
6504             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6505              "Unexpected size %d\n", size);
6506             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6507              "Unexpected value\n");
6508             LocalFree(buf);
6509         }
6510     }
6511     info.EncryptedHash.cbData = sizeof(hash);
6512     info.EncryptedHash.pbData = (BYTE *)hash;
6513     SetLastError(0xdeadbeef);
6514     ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6515      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6516     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6517         ok(!ret && GetLastError() == E_INVALIDARG,
6518          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6519     else
6520     {
6521         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6522         if (buf)
6523         {
6524             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6525              size);
6526             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6527             LocalFree(buf);
6528         }
6529     }
6530 }
6531
6532 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6533 {
6534     BOOL ret;
6535     LPBYTE buf = NULL;
6536     DWORD size = 0;
6537     CMSG_CMS_SIGNER_INFO *info;
6538     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6539
6540     /* A CMS signer can't be decoded without a serial number. */
6541     SetLastError(0xdeadbeef);
6542     ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6543      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6544      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6545     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
6546      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6547     ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6548      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6549      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6550     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6551     if (buf)
6552     {
6553         info = (CMSG_CMS_SIGNER_INFO *)buf;
6554         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6555          info->dwVersion);
6556         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6557          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6558          info->SignerId.dwIdChoice);
6559         ok(info->SignerId.IssuerSerialNumber.Issuer.cbData ==
6560          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6561          info->SignerId.IssuerSerialNumber.Issuer.cbData);
6562         ok(!memcmp(info->SignerId.IssuerSerialNumber.Issuer.pbData,
6563          encodedCommonNameNoNull,
6564          info->SignerId.IssuerSerialNumber.Issuer.cbData),
6565          "Unexpected value\n");
6566         ok(info->SignerId.IssuerSerialNumber.SerialNumber.cbData ==
6567          sizeof(serialNum), "Unexpected size %d\n",
6568          info->SignerId.IssuerSerialNumber.SerialNumber.cbData);
6569         ok(!memcmp(info->SignerId.IssuerSerialNumber.SerialNumber.pbData,
6570          serialNum, sizeof(serialNum)), "Unexpected value\n");
6571         LocalFree(buf);
6572     }
6573     ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6574      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6575      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6576     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6577     if (buf)
6578     {
6579         info = (CMSG_CMS_SIGNER_INFO *)buf;
6580         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6581          info->dwVersion);
6582         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6583          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6584          info->SignerId.dwIdChoice);
6585         ok(info->SignerId.IssuerSerialNumber.Issuer.cbData ==
6586          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6587          info->SignerId.IssuerSerialNumber.Issuer.cbData);
6588         ok(!memcmp(info->SignerId.IssuerSerialNumber.Issuer.pbData,
6589          encodedCommonNameNoNull,
6590          info->SignerId.IssuerSerialNumber.Issuer.cbData),
6591          "Unexpected value\n");
6592         ok(info->SignerId.IssuerSerialNumber.SerialNumber.cbData ==
6593          sizeof(serialNum), "Unexpected size %d\n",
6594          info->SignerId.IssuerSerialNumber.SerialNumber.cbData);
6595         ok(!memcmp(info->SignerId.IssuerSerialNumber.SerialNumber.pbData,
6596          serialNum, sizeof(serialNum)), "Unexpected value\n");
6597         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6598          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6599         LocalFree(buf);
6600     }
6601     ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6602      PKCSSignerWithHashAndEncryptionAlgo,
6603      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6604      NULL, (BYTE *)&buf, &size);
6605     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6606     if (buf)
6607     {
6608         info = (CMSG_CMS_SIGNER_INFO *)buf;
6609         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6610          info->dwVersion);
6611         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6612          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6613          info->SignerId.dwIdChoice);
6614         ok(info->SignerId.IssuerSerialNumber.Issuer.cbData ==
6615          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6616          info->SignerId.IssuerSerialNumber.Issuer.cbData);
6617         ok(!memcmp(info->SignerId.IssuerSerialNumber.Issuer.pbData,
6618          encodedCommonNameNoNull,
6619          info->SignerId.IssuerSerialNumber.Issuer.cbData),
6620          "Unexpected value\n");
6621         ok(info->SignerId.IssuerSerialNumber.SerialNumber.cbData ==
6622          sizeof(serialNum), "Unexpected size %d\n",
6623          info->SignerId.IssuerSerialNumber.SerialNumber.cbData);
6624         ok(!memcmp(info->SignerId.IssuerSerialNumber.SerialNumber.pbData,
6625          serialNum, sizeof(serialNum)), "Unexpected value\n");
6626         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6627          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6628         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6629          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6630         LocalFree(buf);
6631     }
6632     ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6633      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6634      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6635     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6636     if (buf)
6637     {
6638         info = (CMSG_CMS_SIGNER_INFO *)buf;
6639         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6640          info->dwVersion);
6641         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6642          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6643          info->SignerId.dwIdChoice);
6644         ok(info->SignerId.IssuerSerialNumber.Issuer.cbData ==
6645          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6646          info->SignerId.IssuerSerialNumber.Issuer.cbData);
6647         ok(!memcmp(info->SignerId.IssuerSerialNumber.Issuer.pbData,
6648          encodedCommonNameNoNull,
6649          info->SignerId.IssuerSerialNumber.Issuer.cbData),
6650          "Unexpected value\n");
6651         ok(info->SignerId.IssuerSerialNumber.SerialNumber.cbData ==
6652          sizeof(serialNum), "Unexpected size %d\n",
6653          info->SignerId.IssuerSerialNumber.SerialNumber.cbData);
6654         ok(!memcmp(info->SignerId.IssuerSerialNumber.SerialNumber.pbData,
6655          serialNum, sizeof(serialNum)), "Unexpected value\n");
6656         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6657          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6658         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6659          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6660         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6661          info->EncryptedHash.cbData);
6662         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6663          "Unexpected value\n");
6664         LocalFree(buf);
6665     }
6666     ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6667      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6668      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6669     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6670     if (buf)
6671     {
6672         info = (CMSG_CMS_SIGNER_INFO *)buf;
6673         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6674          info->dwVersion);
6675         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6676          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6677          info->SignerId.dwIdChoice);
6678         ok(info->SignerId.KeyId.cbData == sizeof(serialNum),
6679          "Unexpected size %d\n", info->SignerId.KeyId.cbData);
6680         ok(!memcmp(info->SignerId.KeyId.pbData, serialNum, sizeof(serialNum)),
6681          "Unexpected value\n");
6682         LocalFree(buf);
6683     }
6684 }
6685
6686 static BYTE emptyDNSPermittedConstraints[] = {
6687 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6688 static BYTE emptyDNSExcludedConstraints[] = {
6689 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6690 static BYTE DNSExcludedConstraints[] = {
6691 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6692 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6693 static BYTE permittedAndExcludedConstraints[] = {
6694 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6695 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6696 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6697 static BYTE permittedAndExcludedWithMinConstraints[] = {
6698 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6699 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6700 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6701 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6702 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6703 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6704 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6705
6706 static void test_encodeNameConstraints(DWORD dwEncoding)
6707 {
6708     BOOL ret;
6709     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6710     CERT_GENERAL_SUBTREE permitted = { { 0 } };
6711     CERT_GENERAL_SUBTREE excluded = { { 0 } };
6712     LPBYTE buf;
6713     DWORD size;
6714
6715     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6716      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6717     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6718     {
6719         skip("no X509_NAME_CONSTRAINTS encode support\n");
6720         return;
6721     }
6722     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6723     if (ret)
6724     {
6725         ok(size == sizeof(emptySequence), "Unexpected size\n");
6726         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6727         LocalFree(buf);
6728     }
6729     constraints.cPermittedSubtree = 1;
6730     constraints.rgPermittedSubtree = &permitted;
6731     SetLastError(0xdeadbeef);
6732     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6733      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6734     ok(!ret && GetLastError() == E_INVALIDARG,
6735      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6736     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6737     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6738      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6739     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6740     if (ret)
6741     {
6742         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6743         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6744          "Unexpected value\n");
6745         LocalFree(buf);
6746     }
6747     constraints.cPermittedSubtree = 0;
6748     constraints.cExcludedSubtree = 1;
6749     constraints.rgExcludedSubtree = &excluded;
6750     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6751     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6752      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6753     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6754     if (ret)
6755     {
6756         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6757         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6758          "Unexpected value\n");
6759         LocalFree(buf);
6760     }
6761     U(excluded.Base).pwszURL = (LPWSTR)url;
6762     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6763      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6764     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6765     if (ret)
6766     {
6767         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6768         ok(!memcmp(buf, DNSExcludedConstraints, size),
6769          "Unexpected value\n");
6770         LocalFree(buf);
6771     }
6772     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6773     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6774     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6775     constraints.cPermittedSubtree = 1;
6776     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6777      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6778     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6779     if (ret)
6780     {
6781         ok(size == sizeof(permittedAndExcludedConstraints),
6782          "Unexpected size\n");
6783         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6784          "Unexpected value\n");
6785         LocalFree(buf);
6786     }
6787     permitted.dwMinimum = 5;
6788     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6789      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6790     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6791     if (ret)
6792     {
6793         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6794          "Unexpected size\n");
6795         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6796          "Unexpected value\n");
6797         LocalFree(buf);
6798     }
6799     permitted.fMaximum = TRUE;
6800     permitted.dwMaximum = 3;
6801     SetLastError(0xdeadbeef);
6802     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6803      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6804     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6805     if (ret)
6806     {
6807         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6808          "Unexpected size\n");
6809         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6810          "Unexpected value\n");
6811         LocalFree(buf);
6812     }
6813 }
6814
6815 struct EncodedNameConstraints
6816 {
6817     CRYPT_DATA_BLOB            encoded;
6818     CERT_NAME_CONSTRAINTS_INFO constraints;
6819 };
6820
6821 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6822  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6823 static CERT_GENERAL_SUBTREE DNSSubtree = {
6824  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6825 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6826  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6827 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6828  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6829 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6830  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6831
6832 struct EncodedNameConstraints encodedNameConstraints[] = {
6833  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6834  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6835    { 1, &emptyDNSSubtree, 0, NULL } },
6836  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6837    { 0, NULL, 1, &emptyDNSSubtree } },
6838  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6839    { 0, NULL, 1, &DNSSubtree } },
6840  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6841    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6842  { { sizeof(permittedAndExcludedWithMinConstraints),
6843      permittedAndExcludedWithMinConstraints },
6844    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6845  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6846      permittedAndExcludedWithMinMaxConstraints },
6847    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6848 };
6849
6850 static void test_decodeNameConstraints(DWORD dwEncoding)
6851 {
6852     BOOL ret;
6853     DWORD i;
6854     CERT_NAME_CONSTRAINTS_INFO *constraints;
6855
6856     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6857     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6858     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6859     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6860     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6861     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6862     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6863     for (i = 0;
6864      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6865      i++)
6866     {
6867         DWORD size;
6868
6869         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6870          encodedNameConstraints[i].encoded.pbData,
6871          encodedNameConstraints[i].encoded.cbData,
6872          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
6873         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6874         {
6875             skip("no X509_NAME_CONSTRAINTS decode support\n");
6876             return;
6877         }
6878         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
6879         if (ret)
6880         {
6881             DWORD j;
6882
6883             if (constraints->cPermittedSubtree !=
6884              encodedNameConstraints[i].constraints.cPermittedSubtree)
6885                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
6886                  encodedNameConstraints[i].constraints.cPermittedSubtree,
6887                  constraints->cPermittedSubtree);
6888             if (constraints->cPermittedSubtree ==
6889              encodedNameConstraints[i].constraints.cPermittedSubtree)
6890             {
6891                 for (j = 0; j < constraints->cPermittedSubtree; j++)
6892                 {
6893                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
6894                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
6895                 }
6896             }
6897             if (constraints->cExcludedSubtree !=
6898              encodedNameConstraints[i].constraints.cExcludedSubtree)
6899                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
6900                  encodedNameConstraints[i].constraints.cExcludedSubtree,
6901                  constraints->cExcludedSubtree);
6902             if (constraints->cExcludedSubtree ==
6903              encodedNameConstraints[i].constraints.cExcludedSubtree)
6904             {
6905                 for (j = 0; j < constraints->cExcludedSubtree; j++)
6906                 {
6907                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
6908                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
6909                 }
6910             }
6911             LocalFree(constraints);
6912         }
6913     }
6914 }
6915
6916 /* Free *pInfo with HeapFree */
6917 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
6918 {
6919     BOOL ret;
6920     DWORD size = 0;
6921     HCRYPTKEY key;
6922
6923     /* This crashes
6924     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
6925      */
6926     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
6927     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6928      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6929     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
6930      &size);
6931     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6932      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6933     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
6934      NULL, &size);
6935     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6936      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6937     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
6938      0, NULL, NULL, &size);
6939     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6940      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6941     /* Test with no key */
6942     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
6943      0, NULL, NULL, &size);
6944     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
6945      GetLastError());
6946     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
6947     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
6948     if (ret)
6949     {
6950         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
6951          NULL, 0, NULL, NULL, &size);
6952         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
6953         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
6954         if (*pInfo)
6955         {
6956             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
6957              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
6958             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
6959              GetLastError());
6960             if (ret)
6961             {
6962                 /* By default (we passed NULL as the OID) the OID is
6963                  * szOID_RSA_RSA.
6964                  */
6965                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
6966                  "Expected %s, got %s\n", szOID_RSA_RSA,
6967                  (*pInfo)->Algorithm.pszObjId);
6968             }
6969         }
6970     }
6971     CryptDestroyKey(key);
6972 }
6973
6974 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
6975  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
6976  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
6977  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
6978  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
6979  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
6980  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
6981  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
6982  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
6983  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
6984  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
6985  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
6986  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
6987  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
6988  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
6989  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
6990  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
6991  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
6992  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
6993  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
6994  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
6995  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
6996  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
6997  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
6998  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
6999
7000 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7001 {
7002     BOOL ret;
7003     HCRYPTKEY key;
7004     PCCERT_CONTEXT context;
7005     DWORD dwSize;
7006     ALG_ID ai;
7007
7008     /* These crash
7009     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7010     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7011     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7012     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7013      NULL);
7014      */
7015     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7016     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7017      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7018     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7019     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7020      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7021     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7022      &key);
7023     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7024      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7025
7026     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7027     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7028      &key);
7029     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7030
7031     dwSize = sizeof(ai);
7032     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7033     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7034     if(ret)
7035     {
7036       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7037       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7038     }
7039
7040     CryptDestroyKey(key);
7041
7042     /* Repeat with forced algorithm */
7043     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7044      &key);
7045     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7046
7047     dwSize = sizeof(ai);
7048     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7049     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7050     if(ret)
7051     {
7052       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7053       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7054     }
7055
7056     CryptDestroyKey(key);
7057
7058     /* Test importing a public key from a certificate context */
7059     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7060      sizeof(expiredCert));
7061     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7062      GetLastError());
7063     if (context)
7064     {
7065         ok(!strcmp(szOID_RSA_RSA,
7066          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7067          "Expected %s, got %s\n", szOID_RSA_RSA,
7068          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7069         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7070          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7071         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7072         CryptDestroyKey(key);
7073         CertFreeCertificateContext(context);
7074     }
7075 }
7076
7077 static const char cspName[] = "WineCryptTemp";
7078
7079 static void testPortPublicKeyInfo(void)
7080 {
7081     HCRYPTPROV csp;
7082     BOOL ret;
7083     PCERT_PUBLIC_KEY_INFO info = NULL;
7084
7085     /* Just in case a previous run failed, delete this thing */
7086     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7087      CRYPT_DELETEKEYSET);
7088     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7089      CRYPT_NEWKEYSET);
7090
7091     testExportPublicKey(csp, &info);
7092     testImportPublicKey(csp, info);
7093
7094     HeapFree(GetProcessHeap(), 0, info);
7095     CryptReleaseContext(csp, 0);
7096     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7097      CRYPT_DELETEKEYSET);
7098 }
7099
7100 START_TEST(encode)
7101 {
7102     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7103      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7104     HMODULE hCrypt32;
7105     DWORD i;
7106
7107     hCrypt32 = GetModuleHandleA("crypt32.dll");
7108     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7109     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7110     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7111     {
7112         skip("CryptDecodeObjectEx() is not available\n");
7113         return;
7114     }
7115
7116     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7117     {
7118         test_encodeInt(encodings[i]);
7119         test_decodeInt(encodings[i]);
7120         test_encodeEnumerated(encodings[i]);
7121         test_decodeEnumerated(encodings[i]);
7122         test_encodeFiletime(encodings[i]);
7123         test_decodeFiletime(encodings[i]);
7124         test_encodeName(encodings[i]);
7125         test_decodeName(encodings[i]);
7126         test_encodeUnicodeName(encodings[i]);
7127         test_decodeUnicodeName(encodings[i]);
7128         test_encodeNameValue(encodings[i]);
7129         test_decodeNameValue(encodings[i]);
7130         test_encodeUnicodeNameValue(encodings[i]);
7131         test_decodeUnicodeNameValue(encodings[i]);
7132         test_encodeAltName(encodings[i]);
7133         test_decodeAltName(encodings[i]);
7134         test_encodeOctets(encodings[i]);
7135         test_decodeOctets(encodings[i]);
7136         test_encodeBits(encodings[i]);
7137         test_decodeBits(encodings[i]);
7138         test_encodeBasicConstraints(encodings[i]);
7139         test_decodeBasicConstraints(encodings[i]);
7140         test_encodeRsaPublicKey(encodings[i]);
7141         test_decodeRsaPublicKey(encodings[i]);
7142         test_encodeSequenceOfAny(encodings[i]);
7143         test_decodeSequenceOfAny(encodings[i]);
7144         test_encodeExtensions(encodings[i]);
7145         test_decodeExtensions(encodings[i]);
7146         test_encodePublicKeyInfo(encodings[i]);
7147         test_decodePublicKeyInfo(encodings[i]);
7148         test_encodeCertToBeSigned(encodings[i]);
7149         test_decodeCertToBeSigned(encodings[i]);
7150         test_encodeCert(encodings[i]);
7151         test_decodeCert(encodings[i]);
7152         test_encodeCRLDistPoints(encodings[i]);
7153         test_decodeCRLDistPoints(encodings[i]);
7154         test_encodeCRLIssuingDistPoint(encodings[i]);
7155         test_decodeCRLIssuingDistPoint(encodings[i]);
7156         test_encodeCRLToBeSigned(encodings[i]);
7157         test_decodeCRLToBeSigned(encodings[i]);
7158         test_encodeEnhancedKeyUsage(encodings[i]);
7159         test_decodeEnhancedKeyUsage(encodings[i]);
7160         test_encodeAuthorityKeyId(encodings[i]);
7161         test_decodeAuthorityKeyId(encodings[i]);
7162         test_encodeAuthorityKeyId2(encodings[i]);
7163         test_decodeAuthorityKeyId2(encodings[i]);
7164         test_encodeAuthorityInfoAccess(encodings[i]);
7165         test_decodeAuthorityInfoAccess(encodings[i]);
7166         test_encodeCTL(encodings[i]);
7167         test_decodeCTL(encodings[i]);
7168         test_encodePKCSContentInfo(encodings[i]);
7169         test_decodePKCSContentInfo(encodings[i]);
7170         test_encodePKCSAttribute(encodings[i]);
7171         test_decodePKCSAttribute(encodings[i]);
7172         test_encodePKCSAttributes(encodings[i]);
7173         test_decodePKCSAttributes(encodings[i]);
7174         test_encodePKCSSMimeCapabilities(encodings[i]);
7175         test_decodePKCSSMimeCapabilities(encodings[i]);
7176         test_encodePKCSSignerInfo(encodings[i]);
7177         test_decodePKCSSignerInfo(encodings[i]);
7178         test_encodeCMSSignerInfo(encodings[i]);
7179         test_decodeCMSSignerInfo(encodings[i]);
7180         test_encodeNameConstraints(encodings[i]);
7181         test_decodeNameConstraints(encodings[i]);
7182     }
7183     testPortPublicKeyInfo();
7184 }