Assorted spelling fixes.
[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 emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
4779 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
4780  0x03,0,0,0,0,0,0 };
4781 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
4782  0xa0,0x01,0x01 };
4783 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
4784  0x03,0x02,0x01,0x01 };
4785 static BYTE bogusDER[] = { 1 };
4786
4787 static void test_encodePKCSContentInfo(DWORD dwEncoding)
4788 {
4789     BOOL ret;
4790     BYTE *buf = NULL;
4791     DWORD size = 0;
4792     CRYPT_CONTENT_INFO info = { 0 };
4793     char oid1[] = "1.2.3";
4794
4795     SetLastError(0xdeadbeef);
4796     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
4797      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4798     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4799      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4800     SetLastError(0xdeadbeef);
4801     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4802      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4803     ok(!ret && GetLastError() == E_INVALIDARG,
4804      "Expected E_INVALIDARG, got %x\n", GetLastError());
4805     info.pszObjId = oid1;
4806     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4807      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4808     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4809     if (buf)
4810     {
4811         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
4812         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
4813         LocalFree(buf);
4814     }
4815     info.Content.pbData = bogusDER;
4816     info.Content.cbData = sizeof(bogusDER);
4817     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4818      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4819     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
4820     if (buf)
4821     {
4822         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
4823         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
4824         LocalFree(buf);
4825     }
4826     info.Content.pbData = (BYTE *)ints[0].encoded;
4827     info.Content.cbData = ints[0].encoded[1] + 2;
4828     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4829      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4830     if (buf)
4831     {
4832         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
4833         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
4834         LocalFree(buf);
4835     }
4836 }
4837
4838 static const BYTE indefiniteSignedPKCSContent[] = {
4839 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
4840 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
4841 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
4842 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
4843 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
4844 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
4845 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
4846 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4847 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
4848 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
4849 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
4850 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
4851 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
4852 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
4853 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
4854 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
4855 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
4856 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
4857 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
4858 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
4859 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
4860 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
4861 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
4862 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
4863 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
4864 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
4865 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
4866 0x00,0x00,0x00,0x00,0x00,0x00 };
4867
4868 static void test_decodePKCSContentInfo(DWORD dwEncoding)
4869 {
4870     BOOL ret;
4871     LPBYTE buf = NULL;
4872     DWORD size = 0;
4873     CRYPT_CONTENT_INFO *info;
4874
4875     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4876      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
4877      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4878     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4879     if (buf)
4880     {
4881         info = (CRYPT_CONTENT_INFO *)buf;
4882
4883         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4884          info->pszObjId);
4885         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
4886          info->Content.cbData);
4887         LocalFree(buf);
4888     }
4889     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4890      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
4891      0, NULL, NULL, &size);
4892     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4893     SetLastError(0xdeadbeef);
4894     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4895      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
4896      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4897     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
4898      * I doubt an app depends on that.
4899      */
4900     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
4901      GetLastError() == CRYPT_E_ASN1_CORRUPT),
4902      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
4903      GetLastError());
4904     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4905      intPKCSContentInfo, sizeof(intPKCSContentInfo),
4906      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4907     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4908     if (buf)
4909     {
4910         info = (CRYPT_CONTENT_INFO *)buf;
4911
4912         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4913          info->pszObjId);
4914         ok(info->Content.cbData == ints[0].encoded[1] + 2,
4915          "Unexpected size %d\n", info->Content.cbData);
4916         ok(!memcmp(info->Content.pbData, ints[0].encoded,
4917          info->Content.cbData), "Unexpected value\n");
4918         LocalFree(buf);
4919     }
4920     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4921      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
4922      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4923     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4924     if (buf)
4925     {
4926         info = (CRYPT_CONTENT_INFO *)buf;
4927
4928         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
4929          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
4930         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
4931          info->Content.cbData);
4932         LocalFree(buf);
4933     }
4934 }
4935
4936 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
4937  0x00 };
4938 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
4939  0x01 };
4940 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
4941  0x02,0x01,0x01 };
4942
4943 static void test_encodePKCSAttribute(DWORD dwEncoding)
4944 {
4945     CRYPT_ATTRIBUTE attr = { 0 };
4946     BOOL ret;
4947     LPBYTE buf = NULL;
4948     DWORD size = 0;
4949     CRYPT_ATTR_BLOB blob;
4950     char oid[] = "1.2.3";
4951
4952     SetLastError(0xdeadbeef);
4953     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
4954      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4955     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4956      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4957     SetLastError(0xdeadbeef);
4958     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4959      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4960     ok(!ret && GetLastError() == E_INVALIDARG,
4961      "Expected E_INVALIDARG, got %x\n", GetLastError());
4962     attr.pszObjId = oid;
4963     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4964      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4965     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4966     if (buf)
4967     {
4968         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
4969         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
4970         LocalFree(buf);
4971     }
4972     blob.cbData = sizeof(bogusDER);
4973     blob.pbData = bogusDER;
4974     attr.cValue = 1;
4975     attr.rgValue = &blob;
4976     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4977      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4978     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4979     if (buf)
4980     {
4981         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
4982         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
4983         LocalFree(buf);
4984     }
4985     blob.pbData = (BYTE *)ints[0].encoded;
4986     blob.cbData = ints[0].encoded[1] + 2;
4987     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4988      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4989     if (buf)
4990     {
4991         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
4992         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
4993         LocalFree(buf);
4994     }
4995 }
4996
4997 static void test_decodePKCSAttribute(DWORD dwEncoding)
4998 {
4999     BOOL ret;
5000     LPBYTE buf = NULL;
5001     DWORD size = 0;
5002     CRYPT_ATTRIBUTE *attr;
5003
5004     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5005      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5006      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5007     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5008     if (buf)
5009     {
5010         attr = (CRYPT_ATTRIBUTE *)buf;
5011
5012         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5013          attr->pszObjId);
5014         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5015         LocalFree(buf);
5016     }
5017     SetLastError(0xdeadbeef);
5018     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5019      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5020      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5021     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5022      * I doubt an app depends on that.
5023      */
5024     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5025      GetLastError() == CRYPT_E_ASN1_CORRUPT),
5026      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5027      GetLastError());
5028     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5029      intPKCSAttr, sizeof(intPKCSAttr),
5030      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5031     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5032     if (buf)
5033     {
5034         attr = (CRYPT_ATTRIBUTE *)buf;
5035
5036         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5037          attr->pszObjId);
5038         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5039         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5040          "Unexpected size %d\n", attr->rgValue[0].cbData);
5041         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5042          attr->rgValue[0].cbData), "Unexpected value\n");
5043         LocalFree(buf);
5044     }
5045 }
5046
5047 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5048 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5049  0x2a,0x03,0x31,0x00 };
5050 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5051  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5052
5053 static void test_encodePKCSAttributes(DWORD dwEncoding)
5054 {
5055     CRYPT_ATTRIBUTES attributes = { 0 };
5056     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5057     CRYPT_ATTR_BLOB blob;
5058     BOOL ret;
5059     LPBYTE buf = NULL;
5060     DWORD size = 0;
5061     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5062
5063     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5064      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5065     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5066     if (buf)
5067     {
5068         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5069         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5070         LocalFree(buf);
5071     }
5072     attributes.cAttr = 1;
5073     attributes.rgAttr = attr;
5074     SetLastError(0xdeadbeef);
5075     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5076      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5077     ok(!ret && GetLastError() == E_INVALIDARG,
5078      "Expected E_INVALIDARG, got %x\n", GetLastError());
5079     attr[0].pszObjId = oid1;
5080     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5081      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5082     if (buf)
5083     {
5084         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5085         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5086         LocalFree(buf);
5087     }
5088     attr[1].pszObjId = oid2;
5089     attr[1].cValue = 1;
5090     attr[1].rgValue = &blob;
5091     blob.pbData = (BYTE *)ints[0].encoded;
5092     blob.cbData = ints[0].encoded[1] + 2;
5093     attributes.cAttr = 2;
5094     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5095      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5096     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5097     if (buf)
5098     {
5099         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5100         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5101         LocalFree(buf);
5102     }
5103 }
5104
5105 static void test_decodePKCSAttributes(DWORD dwEncoding)
5106 {
5107     BOOL ret;
5108     LPBYTE buf = NULL;
5109     DWORD size = 0;
5110     CRYPT_ATTRIBUTES *attributes;
5111
5112     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5113      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5114      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5115     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5116     if (buf)
5117     {
5118         attributes = (CRYPT_ATTRIBUTES *)buf;
5119         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5120          attributes->cAttr);
5121         LocalFree(buf);
5122     }
5123     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5124      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5125      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5126     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5127     if (buf)
5128     {
5129         attributes = (CRYPT_ATTRIBUTES *)buf;
5130         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5131          attributes->cAttr);
5132         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5133          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5134         ok(attributes->rgAttr[0].cValue == 0,
5135          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5136         LocalFree(buf);
5137     }
5138     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5139      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5140      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5141     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5142     if (buf)
5143     {
5144         attributes = (CRYPT_ATTRIBUTES *)buf;
5145         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5146          attributes->cAttr);
5147         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5148          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5149         ok(attributes->rgAttr[0].cValue == 0,
5150          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5151         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5152          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5153         ok(attributes->rgAttr[1].cValue == 1,
5154          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5155         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5156          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5157         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5158          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5159         LocalFree(buf);
5160     }
5161 }
5162
5163 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
5164  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5165  0x67 };
5166 static const BYTE minimalPKCSSigner[] = {
5167  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5168  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5169  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
5170 static const BYTE PKCSSignerWithSerial[] = {
5171  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5172  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5173  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5174  0x00 };
5175 static const BYTE PKCSSignerWithHashAlgo[] = {
5176  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5177  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5178  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5179  0x00,0x04,0x00 };
5180 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
5181  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5182  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5183  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
5184  0x06,0x05,0x00,0x04,0x00 };
5185 static const BYTE PKCSSignerWithHash[] = {
5186  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5187  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5188  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
5189  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
5190  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
5191 static const BYTE PKCSSignerWithAuthAttr[] = {
5192 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
5193 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
5194 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
5195 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
5196 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
5197 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
5198 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
5199
5200 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
5201 {
5202     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
5203     BOOL ret;
5204     LPBYTE buf = NULL;
5205     DWORD size = 0;
5206     CMSG_SIGNER_INFO info = { 0 };
5207     char oid_common_name[] = szOID_COMMON_NAME;
5208     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
5209      (LPBYTE)encodedCommonName };
5210     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
5211
5212     SetLastError(0xdeadbeef);
5213     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5214      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5215     ok(!ret && GetLastError() == E_INVALIDARG,
5216      "Expected E_INVALIDARG, got %08x\n", GetLastError());
5217     /* To be encoded, a signer must have an issuer at least, and the encoding
5218      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
5219      * see decoding tests.)
5220      */
5221     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
5222     info.Issuer.pbData = encodedCommonNameNoNull;
5223     SetLastError(0xdeadbeef);
5224     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5225      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5226     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5227         ok(!ret && GetLastError() == E_INVALIDARG,
5228          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5229     else
5230     {
5231         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5232         if (buf)
5233         {
5234             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
5235             if (size == sizeof(minimalPKCSSigner))
5236                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
5237             else
5238                 ok(0, "Unexpected value\n");
5239             LocalFree(buf);
5240         }
5241     }
5242     info.SerialNumber.cbData = sizeof(serialNum);
5243     info.SerialNumber.pbData = (BYTE *)serialNum;
5244     SetLastError(0xdeadbeef);
5245     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5246      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5247     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5248         ok(!ret && GetLastError() == E_INVALIDARG,
5249          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5250     else
5251     {
5252         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5253         if (buf)
5254         {
5255             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
5256              size);
5257             if (size == sizeof(PKCSSignerWithSerial))
5258                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
5259                  "Unexpected value\n");
5260             else
5261                 ok(0, "Unexpected value\n");
5262             LocalFree(buf);
5263         }
5264     }
5265     info.HashAlgorithm.pszObjId = oid1;
5266     SetLastError(0xdeadbeef);
5267     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5268      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5269     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5270         ok(!ret && GetLastError() == E_INVALIDARG,
5271          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5272     else
5273     {
5274         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5275         if (buf)
5276         {
5277             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
5278              size);
5279             if (size == sizeof(PKCSSignerWithHashAlgo))
5280                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
5281                  "Unexpected value\n");
5282             else
5283                 ok(0, "Unexpected value\n");
5284             LocalFree(buf);
5285         }
5286     }
5287     info.HashEncryptionAlgorithm.pszObjId = oid2;
5288     SetLastError(0xdeadbeef);
5289     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5290      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5291     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5292         ok(!ret && GetLastError() == E_INVALIDARG,
5293          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5294     else
5295     {
5296         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5297         if (buf)
5298         {
5299             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
5300              "Unexpected size %d\n", size);
5301             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
5302                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
5303                  "Unexpected value\n");
5304             else
5305                 ok(0, "Unexpected value\n");
5306             LocalFree(buf);
5307         }
5308     }
5309     info.EncryptedHash.cbData = sizeof(hash);
5310     info.EncryptedHash.pbData = (BYTE *)hash;
5311     SetLastError(0xdeadbeef);
5312     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5313      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5314     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5315         ok(!ret && GetLastError() == E_INVALIDARG,
5316          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5317     else
5318     {
5319         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5320         if (buf)
5321         {
5322             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
5323              size);
5324             if (size == sizeof(PKCSSignerWithHash))
5325                 ok(!memcmp(buf, PKCSSignerWithHash, size),
5326                  "Unexpected value\n");
5327             else
5328                 ok(0, "Unexpected value\n");
5329             LocalFree(buf);
5330         }
5331     }
5332     info.AuthAttrs.cAttr = 1;
5333     info.AuthAttrs.rgAttr = &attr;
5334     SetLastError(0xdeadbeef);
5335     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5336      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5337     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5338         ok(!ret && GetLastError() == E_INVALIDARG,
5339          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5340     else
5341     {
5342         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5343         if (buf)
5344         {
5345             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
5346              size);
5347             if (size == sizeof(PKCSSignerWithAuthAttr))
5348                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
5349                  "Unexpected value\n");
5350             else
5351                 ok(0, "Unexpected value\n");
5352             LocalFree(buf);
5353         }
5354     }
5355 }
5356
5357 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
5358 {
5359     BOOL ret;
5360     LPBYTE buf = NULL;
5361     DWORD size = 0;
5362     CMSG_SIGNER_INFO *info;
5363
5364     /* A PKCS signer can't be decoded without a serial number. */
5365     SetLastError(0xdeadbeef);
5366     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5367      minimalPKCSSigner, sizeof(minimalPKCSSigner),
5368      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5369     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
5370      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
5371     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5372      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
5373      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5374     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5375     if (buf)
5376     {
5377         info = (CMSG_SIGNER_INFO *)buf;
5378         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5379          info->dwVersion);
5380         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5381          "Unexpected size %d\n", info->Issuer.cbData);
5382         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5383          info->Issuer.cbData), "Unexpected value\n");
5384         ok(info->SerialNumber.cbData == sizeof(serialNum),
5385          "Unexpected size %d\n", info->SerialNumber.cbData);
5386         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5387          "Unexpected value\n");
5388         LocalFree(buf);
5389     }
5390     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5391      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
5392      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5393     if (buf)
5394     {
5395         info = (CMSG_SIGNER_INFO *)buf;
5396         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5397          info->dwVersion);
5398         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5399          "Unexpected size %d\n", info->Issuer.cbData);
5400         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5401          info->Issuer.cbData), "Unexpected value\n");
5402         ok(info->SerialNumber.cbData == sizeof(serialNum),
5403          "Unexpected size %d\n", info->SerialNumber.cbData);
5404         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5405          "Unexpected value\n");
5406         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5407          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5408         LocalFree(buf);
5409     }
5410     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5411      PKCSSignerWithHashAndEncryptionAlgo,
5412      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
5413      NULL, (BYTE *)&buf, &size);
5414     if (buf)
5415     {
5416         info = (CMSG_SIGNER_INFO *)buf;
5417         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5418          info->dwVersion);
5419         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5420          "Unexpected size %d\n", info->Issuer.cbData);
5421         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5422          info->Issuer.cbData), "Unexpected value\n");
5423         ok(info->SerialNumber.cbData == sizeof(serialNum),
5424          "Unexpected size %d\n", info->SerialNumber.cbData);
5425         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5426          "Unexpected value\n");
5427         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5428          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5429         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5430          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5431         LocalFree(buf);
5432     }
5433     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5434      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
5435      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5436     if (buf)
5437     {
5438         info = (CMSG_SIGNER_INFO *)buf;
5439         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5440          info->dwVersion);
5441         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5442          "Unexpected size %d\n", info->Issuer.cbData);
5443         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5444          info->Issuer.cbData), "Unexpected value\n");
5445         ok(info->SerialNumber.cbData == sizeof(serialNum),
5446          "Unexpected size %d\n", info->SerialNumber.cbData);
5447         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5448          "Unexpected value\n");
5449         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5450          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5451         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5452          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5453         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
5454          info->EncryptedHash.cbData);
5455         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
5456          "Unexpected value\n");
5457         LocalFree(buf);
5458     }
5459     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5460      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
5461      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5462     if (buf)
5463     {
5464         info = (CMSG_SIGNER_INFO *)buf;
5465         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
5466          info->AuthAttrs.cAttr);
5467         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
5468          "Expected %s, got %s\n", szOID_COMMON_NAME,
5469          info->AuthAttrs.rgAttr[0].pszObjId);
5470         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
5471          info->AuthAttrs.rgAttr[0].cValue);
5472         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
5473          sizeof(encodedCommonName), "Unexpected size %d\n",
5474          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
5475         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
5476          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
5477         LocalFree(buf);
5478     }
5479 }
5480
5481 static BYTE emptyDNSPermittedConstraints[] = {
5482 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
5483 static BYTE emptyDNSExcludedConstraints[] = {
5484 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
5485 static BYTE DNSExcludedConstraints[] = {
5486 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
5487 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5488 static BYTE permittedAndExcludedConstraints[] = {
5489 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
5490 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
5491 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5492 static BYTE permittedAndExcludedWithMinConstraints[] = {
5493 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
5494 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
5495 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5496 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
5497 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
5498 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
5499 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5500
5501 static void test_encodeNameConstraints(DWORD dwEncoding)
5502 {
5503     BOOL ret;
5504     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
5505     CERT_GENERAL_SUBTREE permitted = { { 0 } };
5506     CERT_GENERAL_SUBTREE excluded = { { 0 } };
5507     LPBYTE buf;
5508     DWORD size;
5509
5510     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5511      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5512     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5513     if (ret)
5514     {
5515         ok(size == sizeof(emptySequence), "Unexpected size\n");
5516         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
5517         LocalFree(buf);
5518     }
5519     constraints.cPermittedSubtree = 1;
5520     constraints.rgPermittedSubtree = &permitted;
5521     SetLastError(0xdeadbeef);
5522     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5523      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5524     ok(!ret && GetLastError() == E_INVALIDARG,
5525      "Expected E_INVALIDARG, got %08x\n", GetLastError());
5526     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
5527     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5528      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5529     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5530     if (ret)
5531     {
5532         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
5533         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
5534          "Unexpected value\n");
5535         LocalFree(buf);
5536     }
5537     constraints.cPermittedSubtree = 0;
5538     constraints.cExcludedSubtree = 1;
5539     constraints.rgExcludedSubtree = &excluded;
5540     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
5541     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5542      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5543     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5544     if (ret)
5545     {
5546         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
5547         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
5548          "Unexpected value\n");
5549         LocalFree(buf);
5550     }
5551     U(excluded.Base).pwszURL = (LPWSTR)url;
5552     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5553      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5554     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5555     if (ret)
5556     {
5557         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
5558         ok(!memcmp(buf, DNSExcludedConstraints, size),
5559          "Unexpected value\n");
5560         LocalFree(buf);
5561     }
5562     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
5563     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
5564     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
5565     constraints.cPermittedSubtree = 1;
5566     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5567      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5568     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5569     if (ret)
5570     {
5571         ok(size == sizeof(permittedAndExcludedConstraints),
5572          "Unexpected size\n");
5573         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
5574          "Unexpected value\n");
5575         LocalFree(buf);
5576     }
5577     permitted.dwMinimum = 5;
5578     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5579      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5580     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5581     if (ret)
5582     {
5583         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
5584          "Unexpected size\n");
5585         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
5586          "Unexpected value\n");
5587         LocalFree(buf);
5588     }
5589     permitted.fMaximum = TRUE;
5590     permitted.dwMaximum = 3;
5591     SetLastError(0xdeadbeef);
5592     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
5593      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5594     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5595     if (ret)
5596     {
5597         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
5598          "Unexpected size\n");
5599         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
5600          "Unexpected value\n");
5601         LocalFree(buf);
5602     }
5603 }
5604
5605 struct EncodedNameConstraints
5606 {
5607     CRYPT_DATA_BLOB            encoded;
5608     CERT_NAME_CONSTRAINTS_INFO constraints;
5609 };
5610
5611 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
5612  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
5613 static CERT_GENERAL_SUBTREE DNSSubtree = {
5614  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
5615 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
5616  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
5617 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
5618  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
5619 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
5620  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
5621
5622 struct EncodedNameConstraints encodedNameConstraints[] = {
5623  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
5624  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
5625    { 1, &emptyDNSSubtree, 0, NULL } },
5626  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
5627    { 0, NULL, 1, &emptyDNSSubtree } },
5628  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
5629    { 0, NULL, 1, &DNSSubtree } },
5630  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
5631    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
5632  { { sizeof(permittedAndExcludedWithMinConstraints),
5633      permittedAndExcludedWithMinConstraints },
5634    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
5635  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
5636      permittedAndExcludedWithMinMaxConstraints },
5637    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
5638 };
5639
5640 static void test_decodeNameConstraints(DWORD dwEncoding)
5641 {
5642     BOOL ret;
5643     DWORD i;
5644     CERT_NAME_CONSTRAINTS_INFO *constraints;
5645
5646     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
5647     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
5648     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
5649     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
5650     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
5651     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
5652     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
5653     for (i = 0;
5654      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
5655      i++)
5656     {
5657         DWORD size;
5658
5659         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
5660          encodedNameConstraints[i].encoded.pbData,
5661          encodedNameConstraints[i].encoded.cbData,
5662          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
5663         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
5664         if (ret)
5665         {
5666             DWORD j;
5667
5668             if (constraints->cPermittedSubtree !=
5669              encodedNameConstraints[i].constraints.cPermittedSubtree)
5670                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
5671                  encodedNameConstraints[i].constraints.cPermittedSubtree,
5672                  constraints->cPermittedSubtree);
5673             if (constraints->cPermittedSubtree ==
5674              encodedNameConstraints[i].constraints.cPermittedSubtree)
5675             {
5676                 for (j = 0; j < constraints->cPermittedSubtree; j++)
5677                 {
5678                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
5679                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
5680                 }
5681             }
5682             if (constraints->cExcludedSubtree !=
5683              encodedNameConstraints[i].constraints.cExcludedSubtree)
5684                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
5685                  encodedNameConstraints[i].constraints.cExcludedSubtree,
5686                  constraints->cExcludedSubtree);
5687             if (constraints->cExcludedSubtree ==
5688              encodedNameConstraints[i].constraints.cExcludedSubtree)
5689             {
5690                 for (j = 0; j < constraints->cExcludedSubtree; j++)
5691                 {
5692                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
5693                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
5694                 }
5695             }
5696             LocalFree(constraints);
5697         }
5698     }
5699 }
5700
5701 /* Free *pInfo with HeapFree */
5702 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
5703 {
5704     BOOL ret;
5705     DWORD size = 0;
5706     HCRYPTKEY key;
5707
5708     /* This crashes
5709     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
5710      */
5711     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
5712     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5713      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5714     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
5715      &size);
5716     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5717      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5718     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
5719      NULL, &size);
5720     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5721      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5722     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5723      0, NULL, NULL, &size);
5724     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5725      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5726     /* Test with no key */
5727     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5728      0, NULL, NULL, &size);
5729     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
5730      GetLastError());
5731     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
5732     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
5733     if (ret)
5734     {
5735         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
5736          NULL, 0, NULL, NULL, &size);
5737         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
5738         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
5739         if (*pInfo)
5740         {
5741             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
5742              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
5743             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
5744              GetLastError());
5745             if (ret)
5746             {
5747                 /* By default (we passed NULL as the OID) the OID is
5748                  * szOID_RSA_RSA.
5749                  */
5750                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
5751                  "Expected %s, got %s\n", szOID_RSA_RSA,
5752                  (*pInfo)->Algorithm.pszObjId);
5753             }
5754         }
5755     }
5756     CryptDestroyKey(key);
5757 }
5758
5759 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
5760  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
5761  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
5762  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5763  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5764  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5765  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
5766  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
5767  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5768  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5769  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5770  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5771  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
5772  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
5773  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
5774  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
5775  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
5776  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
5777  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
5778  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
5779  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
5780  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
5781  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
5782  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
5783  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
5784
5785 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
5786 {
5787     BOOL ret;
5788     HCRYPTKEY key;
5789     PCCERT_CONTEXT context;
5790
5791     /* These crash
5792     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
5793     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
5794     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
5795     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5796      NULL);
5797      */
5798     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
5799     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5800      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5801     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
5802     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5803      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5804     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
5805      &key);
5806     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5807      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5808     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5809      &key);
5810     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5811     CryptDestroyKey(key);
5812
5813     /* Test importing a public key from a certificate context */
5814     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
5815      sizeof(expiredCert));
5816     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
5817      GetLastError());
5818     if (context)
5819     {
5820         ok(!strcmp(szOID_RSA_RSA,
5821          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
5822          "Expected %s, got %s\n", szOID_RSA_RSA,
5823          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
5824         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
5825          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
5826         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5827         CryptDestroyKey(key);
5828         CertFreeCertificateContext(context);
5829     }
5830 }
5831
5832 static const char cspName[] = "WineCryptTemp";
5833
5834 static void testPortPublicKeyInfo(void)
5835 {
5836     HCRYPTPROV csp;
5837     BOOL ret;
5838     PCERT_PUBLIC_KEY_INFO info = NULL;
5839
5840     /* Just in case a previous run failed, delete this thing */
5841     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5842      CRYPT_DELETEKEYSET);
5843     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5844      CRYPT_NEWKEYSET);
5845
5846     testExportPublicKey(csp, &info);
5847     testImportPublicKey(csp, info);
5848
5849     HeapFree(GetProcessHeap(), 0, info);
5850     CryptReleaseContext(csp, 0);
5851     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5852      CRYPT_DELETEKEYSET);
5853 }
5854
5855 START_TEST(encode)
5856 {
5857     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
5858      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
5859     HMODULE hCrypt32;
5860     DWORD i;
5861
5862     hCrypt32 = GetModuleHandleA("crypt32.dll");
5863     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
5864     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
5865     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
5866     {
5867         skip("CryptDecodeObjectEx() is not available\n");
5868         return;
5869     }
5870
5871     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
5872     {
5873         test_encodeInt(encodings[i]);
5874         test_decodeInt(encodings[i]);
5875         test_encodeEnumerated(encodings[i]);
5876         test_decodeEnumerated(encodings[i]);
5877         test_encodeFiletime(encodings[i]);
5878         test_decodeFiletime(encodings[i]);
5879         test_encodeName(encodings[i]);
5880         test_decodeName(encodings[i]);
5881         test_encodeUnicodeName(encodings[i]);
5882         test_decodeUnicodeName(encodings[i]);
5883         test_encodeNameValue(encodings[i]);
5884         test_decodeNameValue(encodings[i]);
5885         test_encodeUnicodeNameValue(encodings[i]);
5886         test_decodeUnicodeNameValue(encodings[i]);
5887         test_encodeAltName(encodings[i]);
5888         test_decodeAltName(encodings[i]);
5889         test_encodeOctets(encodings[i]);
5890         test_decodeOctets(encodings[i]);
5891         test_encodeBits(encodings[i]);
5892         test_decodeBits(encodings[i]);
5893         test_encodeBasicConstraints(encodings[i]);
5894         test_decodeBasicConstraints(encodings[i]);
5895         test_encodeRsaPublicKey(encodings[i]);
5896         test_decodeRsaPublicKey(encodings[i]);
5897         test_encodeSequenceOfAny(encodings[i]);
5898         test_decodeSequenceOfAny(encodings[i]);
5899         test_encodeExtensions(encodings[i]);
5900         test_decodeExtensions(encodings[i]);
5901         test_encodePublicKeyInfo(encodings[i]);
5902         test_decodePublicKeyInfo(encodings[i]);
5903         test_encodeCertToBeSigned(encodings[i]);
5904         test_decodeCertToBeSigned(encodings[i]);
5905         test_encodeCert(encodings[i]);
5906         test_decodeCert(encodings[i]);
5907         test_encodeCRLDistPoints(encodings[i]);
5908         test_decodeCRLDistPoints(encodings[i]);
5909         test_encodeCRLIssuingDistPoint(encodings[i]);
5910         test_decodeCRLIssuingDistPoint(encodings[i]);
5911         test_encodeCRLToBeSigned(encodings[i]);
5912         test_decodeCRLToBeSigned(encodings[i]);
5913         test_encodeEnhancedKeyUsage(encodings[i]);
5914         test_decodeEnhancedKeyUsage(encodings[i]);
5915         test_encodeAuthorityKeyId(encodings[i]);
5916         test_decodeAuthorityKeyId(encodings[i]);
5917         test_encodeAuthorityKeyId2(encodings[i]);
5918         test_decodeAuthorityKeyId2(encodings[i]);
5919         test_encodePKCSContentInfo(encodings[i]);
5920         test_decodePKCSContentInfo(encodings[i]);
5921         test_encodePKCSAttribute(encodings[i]);
5922         test_decodePKCSAttribute(encodings[i]);
5923         test_encodePKCSAttributes(encodings[i]);
5924         test_decodePKCSAttributes(encodings[i]);
5925         test_encodePKCSSignerInfo(encodings[i]);
5926         test_decodePKCSSignerInfo(encodings[i]);
5927         test_encodeNameConstraints(encodings[i]);
5928         test_decodeNameConstraints(encodings[i]);
5929     }
5930     testPortPublicKeyInfo();
5931 }