comctl32/listview: Free ID array when removing all items.
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
32
33 struct encodedInt
34 {
35     int val;
36     const BYTE *encoded;
37 };
38
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
46
47 static const struct encodedInt ints[] = {
48  { 1,          bin1 },
49  { 127,        bin2 },
50  { 128,        bin3 },
51  { 256,        bin4 },
52  { -128,       bin5 },
53  { -129,       bin6 },
54  { 0xbaddf00d, bin7 },
55 };
56
57 struct encodedBigInt
58 {
59     const BYTE *val;
60     const BYTE *encoded;
61     const BYTE *decoded;
62 };
63
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
67
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
71
72 static const struct encodedBigInt bigInts[] = {
73  { bin8, bin9, bin10 },
74  { bin11, bin12, bin13 },
75 };
76
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
81
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84  { bin14, bin15, NULL },
85  { bin16, bin17, NULL },
86 };
87
88 static void test_encodeInt(DWORD dwEncoding)
89 {
90     DWORD bufSize = 0;
91     int i;
92     BOOL ret;
93     CRYPT_INTEGER_BLOB blob;
94     BYTE *buf = NULL;
95
96     /* CryptEncodeObjectEx with NULL bufSize crashes..
97     ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98      NULL);
99      */
100     /* check bogus encoding */
101     ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102      &bufSize);
103     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105     if (0)
106     {
107         /* check with NULL integer buffer.  Windows XP incorrectly returns an
108          * NTSTATUS (crashes on win9x).
109          */
110         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111          &bufSize);
112         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
114     }
115     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
116     {
117         /* encode as normal integer */
118         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119          NULL, NULL, &bufSize);
120         ok(ret, "Expected success, got %d\n", GetLastError());
121         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124         if (buf)
125         {
126             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127              buf[0]);
128             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129              buf[1], ints[i].encoded[1]);
130             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132             LocalFree(buf);
133         }
134         /* encode as multibyte integer */
135         blob.cbData = sizeof(ints[i].val);
136         blob.pbData = (BYTE *)&ints[i].val;
137         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138          0, NULL, NULL, &bufSize);
139         ok(ret, "Expected success, got %d\n", GetLastError());
140         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143         if (buf)
144         {
145             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146              buf[0]);
147             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148              buf[1], ints[i].encoded[1]);
149             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151             LocalFree(buf);
152         }
153     }
154     /* encode a couple bigger ints, just to show it's little-endian and leading
155      * sign bytes are dropped
156      */
157     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158     {
159         blob.cbData = strlen((const char*)bigInts[i].val);
160         blob.pbData = (BYTE *)bigInts[i].val;
161         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162          0, NULL, NULL, &bufSize);
163         ok(ret, "Expected success, got %d\n", GetLastError());
164         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167         if (buf)
168         {
169             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170              buf[0]);
171             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172              buf[1], bigInts[i].encoded[1]);
173             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174              bigInts[i].encoded[1] + 1),
175              "Encoded value didn't match expected\n");
176             LocalFree(buf);
177         }
178     }
179     /* and, encode some uints */
180     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181     {
182         blob.cbData = strlen((const char*)bigUInts[i].val);
183         blob.pbData = (BYTE*)bigUInts[i].val;
184         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185          0, NULL, NULL, &bufSize);
186         ok(ret, "Expected success, got %d\n", GetLastError());
187         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190         if (buf)
191         {
192             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193              buf[0]);
194             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195              buf[1], bigUInts[i].encoded[1]);
196             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197              bigUInts[i].encoded[1] + 1),
198              "Encoded value didn't match expected\n");
199             LocalFree(buf);
200         }
201     }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211     BYTE *buf = NULL;
212     DWORD bufSize = 0;
213     int i;
214     BOOL ret;
215
216     /* CryptDecodeObjectEx with NULL bufSize crashes..
217     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219      */
220     /* check bogus encoding */
221     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225     /* check with NULL integer buffer */
226     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227      &bufSize);
228     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229      GetLastError() == OSS_BAD_ARG /* Win9x */),
230      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231     /* check with a valid, but too large, integer */
232     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
234     ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
235      broken(ret) /* Win9x */,
236      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
237     /* check with a DER-encoded string */
238     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
239      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
240     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
241      GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
242      "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
243      GetLastError());
244     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
245     {
246         /* When the output buffer is NULL, this always succeeds */
247         SetLastError(0xdeadbeef);
248         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250          &bufSize);
251         ok(ret && GetLastError() == NOERROR,
252          "Expected success and NOERROR, got %d\n", GetLastError());
253         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254          ints[i].encoded, ints[i].encoded[1] + 2,
255          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
256         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
257         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
258         ok(buf != NULL, "Expected allocated buffer\n");
259         if (buf)
260         {
261             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262              ints[i].val, *(int *)buf);
263             LocalFree(buf);
264         }
265     }
266     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
267     {
268         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270          &bufSize);
271         ok(ret && GetLastError() == NOERROR,
272          "Expected success and NOERROR, got %d\n", GetLastError());
273         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
276         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278         ok(buf != NULL, "Expected allocated buffer\n");
279         if (buf)
280         {
281             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
282
283             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285              blob->cbData);
286             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287              "Unexpected value\n");
288             LocalFree(buf);
289         }
290     }
291     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
292     {
293         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295          &bufSize);
296         ok(ret && GetLastError() == NOERROR,
297          "Expected success and NOERROR, got %d\n", GetLastError());
298         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
301         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303         ok(buf != NULL, "Expected allocated buffer\n");
304         if (buf)
305         {
306             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
307
308             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310              blob->cbData);
311             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312              "Unexpected value\n");
313             LocalFree(buf);
314         }
315     }
316     /* Decode the value 1 with long-form length */
317     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
319     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320     if (buf)
321     {
322         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323         LocalFree(buf);
324     }
325     /* check with extra bytes at the end */
326     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
328     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329     if (buf)
330     {
331         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332         LocalFree(buf);
333     }
334     /* Try to decode some bogus large items */
335     /* The buffer size is smaller than the encoded length, so this should fail
336      * with CRYPT_E_ASN1_EOD if it's being decoded.
337      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339      * So this test unfortunately isn't useful.
340     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
342     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
344      */
345     /* This will try to decode the buffer and overflow it, check that it's
346      * caught.
347      */
348     if (0)
349     {
350     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
353     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
355     }
356 }
357
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
360
361 /* These are always encoded unsigned, and aren't constrained to be any
362  * particular value
363  */
364 static const struct encodedInt enums[] = {
365  { 1,    bin18 },
366  { -128, bin19 },
367 };
368
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370  * X509_ENUMERATED.
371  */
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373  szOID_CRL_REASON_CODE };
374
375 static void test_encodeEnumerated(DWORD dwEncoding)
376 {
377     DWORD i, j;
378
379     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
380     {
381         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
382         {
383             BOOL ret;
384             BYTE *buf = NULL;
385             DWORD bufSize = 0;
386
387             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
389              &bufSize);
390             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391             if (buf)
392             {
393                 ok(buf[0] == 0xa,
394                  "Got unexpected type %d for enumerated (expected 0xa)\n",
395                  buf[0]);
396                 ok(buf[1] == enums[j].encoded[1],
397                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399                  enums[j].encoded[1] + 1),
400                  "Encoded value of 0x%08x didn't match expected\n",
401                  enums[j].val);
402                 LocalFree(buf);
403             }
404         }
405     }
406 }
407
408 static void test_decodeEnumerated(DWORD dwEncoding)
409 {
410     DWORD i, j;
411
412     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
413     {
414         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
415         {
416             BOOL ret;
417             DWORD bufSize = sizeof(int);
418             int val;
419
420             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422              &val, &bufSize);
423             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424             ok(bufSize == sizeof(int),
425              "Got unexpected size %d for enumerated\n", bufSize);
426             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427              val, enums[j].val);
428         }
429     }
430 }
431
432 struct encodedFiletime
433 {
434     SYSTEMTIME sysTime;
435     const BYTE *encodedTime;
436 };
437
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439  const struct encodedFiletime *time)
440 {
441     FILETIME ft = { 0 };
442     BYTE *buf = NULL;
443     DWORD bufSize = 0;
444     BOOL ret;
445
446     ret = SystemTimeToFileTime(&time->sysTime, &ft);
447     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
450     /* years other than 1950-2050 are not allowed for encodings other than
451      * X509_CHOICE_OF_TIME.
452      */
453     if (structType == X509_CHOICE_OF_TIME ||
454      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
455     {
456         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457          GetLastError());
458         ok(buf != NULL, "Expected an allocated buffer\n");
459         if (buf)
460         {
461             ok(buf[0] == time->encodedTime[0],
462              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463              buf[0]);
464             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465              time->encodedTime[1], bufSize);
466             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467              "Got unexpected value for time encoding\n");
468             LocalFree(buf);
469         }
470     }
471     else
472         ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473          broken(GetLastError() == ERROR_SUCCESS),
474          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
475 }
476
477 static const char *printSystemTime(const SYSTEMTIME *st)
478 {
479     static char buf[25];
480
481     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483     return buf;
484 }
485
486 static const char *printFileTime(const FILETIME *ft)
487 {
488     static char buf[25];
489     SYSTEMTIME st;
490
491     FileTimeToSystemTime(ft, &st);
492     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494     return buf;
495 }
496
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
498 {
499     SYSTEMTIME st;
500
501     FileTimeToSystemTime(got, &st);
502     ok((expected->wYear == st.wYear &&
503      expected->wMonth == st.wMonth &&
504      expected->wDay == st.wDay &&
505      expected->wHour == st.wHour &&
506      expected->wMinute == st.wMinute &&
507      expected->wSecond == st.wSecond &&
508      abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509      /* Some Windows systems only seem to be accurate in their time decoding to
510       * within about an hour.
511       */
512      broken(expected->wYear == st.wYear &&
513      expected->wMonth == st.wMonth &&
514      expected->wDay == st.wDay &&
515      abs(expected->wHour - st.wHour) <= 1),
516      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517      printSystemTime(expected), printFileTime(got));
518 }
519
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521  const struct encodedFiletime *time)
522 {
523     FILETIME ft = { 0 };
524     DWORD size = sizeof(ft);
525     BOOL ret;
526
527     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529     /* years other than 1950-2050 are not allowed for encodings other than
530      * X509_CHOICE_OF_TIME.
531      */
532     if (structType == X509_CHOICE_OF_TIME ||
533      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
534     {
535         ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536          "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537          GetLastError());
538         if (ret)
539             compareTime(&time->sysTime, &ft);
540     }
541     else
542         ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543          GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544          "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545          GetLastError());
546 }
547
548 static const BYTE bin20[] = {
549     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
554
555 static const struct encodedFiletime times[] = {
556  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
559 };
560
561 static void test_encodeFiletime(DWORD dwEncoding)
562 {
563     DWORD i;
564
565     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
566     {
567         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
570     }
571 }
572
573 static const BYTE bin23[] = {
574     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598     0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602     0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604     0x18,0x08, '2','1','4','5','0','6','0','6'};
605
606 static void test_decodeFiletime(DWORD dwEncoding)
607 {
608     static const struct encodedFiletime otherTimes[] = {
609      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
610      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
612      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
613      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
614      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
615      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
616      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
617      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
618      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
619      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
620      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
621     };
622     /* An oddball case that succeeds in Windows, but doesn't seem correct
623      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
624      */
625     static const unsigned char *bogusTimes[] = {
626      /* oddly, this succeeds on Windows, with year 2765
627      "\x18" "\x0f" "21r50606161000Z",
628       */
629      bin35,
630      bin36,
631      bin37,
632      bin38,
633     };
634     DWORD i, size;
635     FILETIME ft1 = { 0 }, ft2 = { 0 };
636     BOOL ret;
637
638     /* Check bogus length with non-NULL buffer */
639     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641     size = 1;
642     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644     ok(!ret && GetLastError() == ERROR_MORE_DATA,
645      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646     /* Normal tests */
647     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
648     {
649         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
652     }
653     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
654     {
655         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
658     }
659     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
660     {
661         size = sizeof(ft1);
662         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664         ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665                      GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666            broken(ret), /* Win9x and NT4 for bin38 */
667          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668          GetLastError());
669     }
670 }
671
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
674
675 static const BYTE emptySequence[] = { 0x30, 0 };
676 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
677 static const BYTE twoRDNs[] = {
678     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
679     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
680     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
681 static const BYTE encodedTwoRDNs[] = {
682 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
683 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
684 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
685 0x6e,0x67,0x00,
686 };
687
688 static const BYTE us[] = { 0x55, 0x53 };
689 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
690  0x74, 0x61 };
691 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
692  0x6f, 0x6c, 0x69, 0x73 };
693 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
694  0x76, 0x65, 0x72, 0x73 };
695 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
696  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
697 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
698  0x73, 0x74 };
699 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
700  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
701
702 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
703 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
704
705 static CHAR oid_us[]            = "2.5.4.6",
706             oid_minnesota[]     = "2.5.4.8",
707             oid_minneapolis[]   = "2.5.4.7",
708             oid_codeweavers[]   = "2.5.4.10",
709             oid_wine[]          = "2.5.4.11",
710             oid_localhostAttr[] = "2.5.4.3",
711             oid_aric[]          = "1.2.840.113549.1.9.1";
712 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
713                                     { RDNA(minnesota) },
714                                     { RDNA(minneapolis) },
715                                     { RDNA(codeweavers) },
716                                     { RDNA(wine) },
717                                     { RDNA(localhostAttr) },
718                                     { RDNIA5(aric) } };
719 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
720                                            { RDNA(localhostAttr) },
721                                            { RDNA(minnesota) },
722                                            { RDNA(minneapolis) },
723                                            { RDNA(codeweavers) },
724                                            { RDNA(wine) },
725                                            { RDNIA5(aric) } };
726
727 #undef RDNIA5
728 #undef RDNA
729
730 static const BYTE encodedRDNAttrs[] = {
731 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
732 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
733 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
734 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
735 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
736 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
737 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
738 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
739 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
740 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
741 };
742
743 static void test_encodeName(DWORD dwEncoding)
744 {
745     CERT_RDN_ATTR attrs[2];
746     CERT_RDN rdn;
747     CERT_NAME_INFO info;
748     static CHAR oid_common_name[] = szOID_COMMON_NAME,
749                 oid_sur_name[]    = szOID_SUR_NAME;
750     BYTE *buf = NULL;
751     DWORD size = 0;
752     BOOL ret;
753
754     if (0)
755     {
756         /* Test with NULL pvStructInfo (crashes on win9x) */
757         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
758          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
759         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
760          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
761     }
762     /* Test with empty CERT_NAME_INFO */
763     info.cRDN = 0;
764     info.rgRDN = NULL;
765     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
767     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
768     if (buf)
769     {
770         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771          "Got unexpected encoding for empty name\n");
772         LocalFree(buf);
773     }
774     if (0)
775     {
776         /* Test with bogus CERT_RDN (crashes on win9x) */
777         info.cRDN = 1;
778         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
780         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
781          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
782     }
783     /* Test with empty CERT_RDN */
784     rdn.cRDNAttr = 0;
785     rdn.rgRDNAttr = NULL;
786     info.cRDN = 1;
787     info.rgRDN = &rdn;
788     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
789      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
790     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
791     if (buf)
792     {
793         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794          "Got unexpected encoding for empty RDN array\n");
795         LocalFree(buf);
796     }
797     if (0)
798     {
799         /* Test with bogus attr array (crashes on win9x) */
800         rdn.cRDNAttr = 1;
801         rdn.rgRDNAttr = NULL;
802         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
803          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
804         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
805          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
806     }
807     /* oddly, a bogus OID is accepted by Windows XP; not testing.
808     attrs[0].pszObjId = "bogus";
809     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
810     attrs[0].Value.cbData = sizeof(commonName);
811     attrs[0].Value.pbData = commonName;
812     rdn.cRDNAttr = 1;
813     rdn.rgRDNAttr = attrs;
814     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
815      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
816     ok(!ret, "Expected failure, got success\n");
817      */
818     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
819      * the encoded attributes to be swapped.
820      */
821     attrs[0].pszObjId = oid_common_name;
822     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
823     attrs[0].Value.cbData = sizeof(commonName);
824     attrs[0].Value.pbData = (BYTE *)commonName;
825     attrs[1].pszObjId = oid_sur_name;
826     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
827     attrs[1].Value.cbData = sizeof(surName);
828     attrs[1].Value.pbData = (BYTE *)surName;
829     rdn.cRDNAttr = 2;
830     rdn.rgRDNAttr = attrs;
831     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
832      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
833     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
834     if (buf)
835     {
836         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837          "Got unexpected encoding for two RDN array\n");
838         LocalFree(buf);
839     }
840     /* A name can be "encoded" with previously encoded RDN attrs. */
841     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
842     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
843     attrs[0].Value.cbData = sizeof(twoRDNs);
844     rdn.cRDNAttr = 1;
845     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
846      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
847     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
848     if (buf)
849     {
850         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851         ok(!memcmp(buf, encodedTwoRDNs, size),
852          "Unexpected value for re-endoded two RDN array\n");
853         LocalFree(buf);
854     }
855     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
856     rdn.cRDNAttr = 1;
857     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
858     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
859      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
860     ok(!ret && GetLastError() == E_INVALIDARG,
861      "Expected E_INVALIDARG, got %08x\n", GetLastError());
862     /* Test a more complex name */
863     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
864     rdn.rgRDNAttr = rdnAttrs;
865     info.cRDN = 1;
866     info.rgRDN = &rdn;
867     buf = NULL;
868     size = 0;
869     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
870      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
871     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
872     if (ret)
873     {
874         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
875         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
876         LocalFree(buf);
877     }
878 }
879
880 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
881 static WCHAR surNameW[] = { 'L','a','n','g',0 };
882
883 static const BYTE twoRDNsNoNull[] = {
884  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
885  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
886  0x20,0x4c,0x61,0x6e,0x67 };
887 static const BYTE anyType[] = {
888  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
889  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
890  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
891  0x61,0x4c,0x67,0x6e };
892
893 static void test_encodeUnicodeName(DWORD dwEncoding)
894 {
895     CERT_RDN_ATTR attrs[2];
896     CERT_RDN rdn;
897     CERT_NAME_INFO info;
898     static CHAR oid_common_name[] = szOID_COMMON_NAME,
899                 oid_sur_name[]    = szOID_SUR_NAME;
900     BYTE *buf = NULL;
901     DWORD size = 0;
902     BOOL ret;
903
904     if (0)
905     {
906         /* Test with NULL pvStructInfo (crashes on win9x) */
907         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
908          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
909         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
910          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
911     }
912     /* Test with empty CERT_NAME_INFO */
913     info.cRDN = 0;
914     info.rgRDN = NULL;
915     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
916      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
917     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
918     if (buf)
919     {
920         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921          "Got unexpected encoding for empty name\n");
922         LocalFree(buf);
923     }
924     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925      * encoding (the NULL).
926      */
927     attrs[0].pszObjId = oid_common_name;
928     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
929     attrs[0].Value.cbData = sizeof(commonNameW);
930     attrs[0].Value.pbData = (BYTE *)commonNameW;
931     rdn.cRDNAttr = 1;
932     rdn.rgRDNAttr = attrs;
933     info.cRDN = 1;
934     info.rgRDN = &rdn;
935     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
937     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
938      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
939     ok(size == 9, "Unexpected error index %08x\n", size);
940     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
941      * forces the order of the encoded attributes to be swapped.
942      */
943     attrs[0].pszObjId = oid_common_name;
944     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
945     attrs[0].Value.cbData = 0;
946     attrs[0].Value.pbData = (BYTE *)commonNameW;
947     attrs[1].pszObjId = oid_sur_name;
948     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
949     attrs[1].Value.cbData = 0;
950     attrs[1].Value.pbData = (BYTE *)surNameW;
951     rdn.cRDNAttr = 2;
952     rdn.rgRDNAttr = attrs;
953     info.cRDN = 1;
954     info.rgRDN = &rdn;
955     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
956      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
957     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
958     if (buf)
959     {
960         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961          "Got unexpected encoding for two RDN array\n");
962         LocalFree(buf);
963     }
964     /* A name can be "encoded" with previously encoded RDN attrs. */
965     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
966     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
967     attrs[0].Value.cbData = sizeof(twoRDNs);
968     rdn.cRDNAttr = 1;
969     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
970      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
971     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
972     if (buf)
973     {
974         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975         ok(!memcmp(buf, encodedTwoRDNs, size),
976          "Unexpected value for re-endoded two RDN array\n");
977         LocalFree(buf);
978     }
979     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980     rdn.cRDNAttr = 1;
981     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
984     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985     if (buf)
986     {
987         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989         LocalFree(buf);
990     }
991 }
992
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994  const CERT_NAME_VALUE *got)
995 {
996     if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
997         got->dwValueType == CERT_RDN_ENCODED_BLOB)
998     {
999         win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
1000         return;
1001     }
1002
1003     ok(got->dwValueType == expected->dwValueType,
1004      "Expected string type %d, got %d\n", expected->dwValueType,
1005      got->dwValueType);
1006     ok(got->Value.cbData == expected->Value.cbData,
1007      "String type %d: unexpected data size, got %d, expected %d\n",
1008      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1009     if (got->Value.cbData && got->Value.pbData)
1010         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1011          min(got->Value.cbData, expected->Value.cbData)),
1012          "String type %d: unexpected value\n", expected->dwValueType);
1013 }
1014
1015 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1016  const CERT_RDN_ATTR *got)
1017 {
1018     if (expected->pszObjId && strlen(expected->pszObjId))
1019     {
1020         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1021          expected->pszObjId);
1022         if (got->pszObjId)
1023         {
1024             ok(!strcmp(got->pszObjId, expected->pszObjId),
1025              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1026              expected->pszObjId);
1027         }
1028     }
1029     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1030      (const CERT_NAME_VALUE *)&got->dwValueType);
1031 }
1032
1033 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1034 {
1035     ok(got->cRDNAttr == expected->cRDNAttr,
1036      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1037     if (got->cRDNAttr)
1038     {
1039         DWORD i;
1040
1041         for (i = 0; i < got->cRDNAttr; i++)
1042             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1043     }
1044 }
1045
1046 static void compareNames(const CERT_NAME_INFO *expected,
1047  const CERT_NAME_INFO *got)
1048 {
1049     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1050      expected->cRDN, got->cRDN);
1051     if (got->cRDN)
1052     {
1053         DWORD i;
1054
1055         for (i = 0; i < got->cRDN; i++)
1056             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1057     }
1058 }
1059
1060 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1061 static const BYTE twoRDNsExtraBytes[] = {
1062     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1063     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1064     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1065
1066 static void test_decodeName(DWORD dwEncoding)
1067 {
1068     BYTE *buf = NULL;
1069     DWORD bufSize = 0;
1070     BOOL ret;
1071     CERT_RDN rdn;
1072     CERT_NAME_INFO info = { 1, &rdn };
1073
1074     /* test empty name */
1075     bufSize = 0;
1076     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1077      emptySequence[1] + 2,
1078      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1079      &buf, &bufSize);
1080     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1081     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1082      * decoder works the same way, so only test the count.
1083      */
1084     if (buf)
1085     {
1086         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1087         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1088          "Expected 0 RDNs in empty info, got %d\n",
1089          ((CERT_NAME_INFO *)buf)->cRDN);
1090         LocalFree(buf);
1091     }
1092     /* test empty name with indefinite-length encoding */
1093     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1094      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1095      &buf, &bufSize);
1096     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1097     if (ret)
1098     {
1099         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1100         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1101          "Expected 0 RDNs in empty info, got %d\n",
1102          ((CERT_NAME_INFO *)buf)->cRDN);
1103         LocalFree(buf);
1104     }
1105     /* test empty RDN */
1106     bufSize = 0;
1107     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1108      emptyRDNs[1] + 2,
1109      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1110      &buf, &bufSize);
1111     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1112     if (buf)
1113     {
1114         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1115
1116         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1117          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1118          "Got unexpected value for empty RDN\n");
1119         LocalFree(buf);
1120     }
1121     /* test two RDN attrs */
1122     bufSize = 0;
1123     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1124      twoRDNs[1] + 2,
1125      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1126      &buf, &bufSize);
1127     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1128     if (buf)
1129     {
1130         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1131                     oid_common_name[] = szOID_COMMON_NAME;
1132
1133         CERT_RDN_ATTR attrs[] = {
1134          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1135           (BYTE *)surName } },
1136          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1137           (BYTE *)commonName } },
1138         };
1139
1140         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1141         rdn.rgRDNAttr = attrs;
1142         compareNames(&info, (CERT_NAME_INFO *)buf);
1143         LocalFree(buf);
1144     }
1145     /* test that two RDN attrs with extra bytes succeeds */
1146     bufSize = 0;
1147     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1148      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1149     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1150     /* And, a slightly more complicated name */
1151     buf = NULL;
1152     bufSize = 0;
1153     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1154      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1155     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1156     if (ret)
1157     {
1158         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1159         rdn.rgRDNAttr = decodedRdnAttrs;
1160         compareNames(&info, (CERT_NAME_INFO *)buf);
1161         LocalFree(buf);
1162     }
1163 }
1164
1165 static void test_decodeUnicodeName(DWORD dwEncoding)
1166 {
1167     BYTE *buf = NULL;
1168     DWORD bufSize = 0;
1169     BOOL ret;
1170     CERT_RDN rdn;
1171     CERT_NAME_INFO info = { 1, &rdn };
1172
1173     /* test empty name */
1174     bufSize = 0;
1175     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1176      emptySequence[1] + 2,
1177      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1178      &buf, &bufSize);
1179     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1180     if (buf)
1181     {
1182         ok(bufSize == sizeof(CERT_NAME_INFO),
1183          "Got wrong bufSize %d\n", bufSize);
1184         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1185          "Expected 0 RDNs in empty info, got %d\n",
1186          ((CERT_NAME_INFO *)buf)->cRDN);
1187         LocalFree(buf);
1188     }
1189     /* test empty RDN */
1190     bufSize = 0;
1191     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1192      emptyRDNs[1] + 2,
1193      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1194      &buf, &bufSize);
1195     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1196     if (buf)
1197     {
1198         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1199
1200         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1201          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1202          "Got unexpected value for empty RDN\n");
1203         LocalFree(buf);
1204     }
1205     /* test two RDN attrs */
1206     bufSize = 0;
1207     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1208      sizeof(twoRDNsNoNull),
1209      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1210      &buf, &bufSize);
1211     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1212     if (buf)
1213     {
1214         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1215                     oid_common_name[] = szOID_COMMON_NAME;
1216
1217         CERT_RDN_ATTR attrs[] = {
1218          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1219          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1220          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1221          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1222         };
1223
1224         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1225         rdn.rgRDNAttr = attrs;
1226         compareNames(&info, (CERT_NAME_INFO *)buf);
1227         LocalFree(buf);
1228     }
1229 }
1230
1231 struct EncodedNameValue
1232 {
1233     CERT_NAME_VALUE value;
1234     const BYTE *encoded;
1235     DWORD encodedSize;
1236 };
1237
1238 static const char bogusIA5[] = "\x80";
1239 static const char bogusPrintable[] = "~";
1240 static const char bogusNumeric[] = "A";
1241 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1242 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1243 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1244 static BYTE octetCommonNameValue[] = {
1245  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1246 static BYTE numericCommonNameValue[] = {
1247  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1248 static BYTE printableCommonNameValue[] = {
1249  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250 static BYTE t61CommonNameValue[] = {
1251  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1252 static BYTE videotexCommonNameValue[] = {
1253  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1254 static BYTE ia5CommonNameValue[] = {
1255  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1256 static BYTE graphicCommonNameValue[] = {
1257  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1258 static BYTE visibleCommonNameValue[] = {
1259  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1260 static BYTE generalCommonNameValue[] = {
1261  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1262 static BYTE bmpCommonNameValue[] = {
1263  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1264  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1265 static BYTE utf8CommonNameValue[] = {
1266  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1267
1268 static struct EncodedNameValue nameValues[] = {
1269  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1270      octetCommonNameValue, sizeof(octetCommonNameValue) },
1271  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1272      numericCommonNameValue, sizeof(numericCommonNameValue) },
1273  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1274      printableCommonNameValue, sizeof(printableCommonNameValue) },
1275  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1276      t61CommonNameValue, sizeof(t61CommonNameValue) },
1277  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1278      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1279  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1280      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1281  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1282      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1283  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1284      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1285  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1286      generalCommonNameValue, sizeof(generalCommonNameValue) },
1287  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1288      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1289  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1290      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1291  /* The following tests succeed under Windows, but really should fail,
1292   * they contain characters that are illegal for the encoding.  I'm
1293   * including them to justify my lazy encoding.
1294   */
1295  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1296      sizeof(bin42) },
1297  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1298      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1299  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1300      bin44, sizeof(bin44) },
1301 };
1302
1303 static void test_encodeNameValue(DWORD dwEncoding)
1304 {
1305     BYTE *buf = NULL;
1306     DWORD size = 0, i;
1307     BOOL ret;
1308     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1309
1310     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1311     value.Value.pbData = printableCommonNameValue;
1312     value.Value.cbData = sizeof(printableCommonNameValue);
1313     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1314      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1315     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1316     if (buf)
1317     {
1318         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1319          size);
1320         ok(!memcmp(buf, printableCommonNameValue, size),
1321          "Unexpected encoding\n");
1322         LocalFree(buf);
1323     }
1324     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1325     {
1326         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1327          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1328         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1329          "Type %d: CryptEncodeObjectEx failed: %08x\n",
1330          nameValues[i].value.dwValueType, GetLastError());
1331         if (ret)
1332         {
1333             ok(size == nameValues[i].encodedSize,
1334              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1335             ok(!memcmp(buf, nameValues[i].encoded, size),
1336              "Got unexpected encoding\n");
1337             LocalFree(buf);
1338         }
1339     }
1340 }
1341
1342 static void test_decodeNameValue(DWORD dwEncoding)
1343 {
1344     int i;
1345     BYTE *buf = NULL;
1346     DWORD bufSize = 0;
1347     BOOL ret;
1348
1349     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1350     {
1351         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1352          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1353          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1354          &buf, &bufSize);
1355         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1356          nameValues[i].value.dwValueType, GetLastError());
1357         if (ret)
1358         {
1359             compareNameValues(&nameValues[i].value,
1360              (const CERT_NAME_VALUE *)buf);
1361             LocalFree(buf);
1362         }
1363     }
1364 }
1365
1366 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1367 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1368 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1369  'h','q','.','o','r','g',0 };
1370 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1371  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1372  0x6f, 0x72, 0x67 };
1373 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1374  0x575b, 0 };
1375 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1376 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1377  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1378 static const BYTE localhost[] = { 127, 0, 0, 1 };
1379 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1380  0x01 };
1381 static const unsigned char encodedCommonName[] = {
1382     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1383 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1384 static const BYTE encodedDirectoryName[] = {
1385 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1386 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1387
1388 static void test_encodeAltName(DWORD dwEncoding)
1389 {
1390     CERT_ALT_NAME_INFO info = { 0 };
1391     CERT_ALT_NAME_ENTRY entry = { 0 };
1392     BYTE *buf = NULL;
1393     DWORD size = 0;
1394     BOOL ret;
1395     char oid[] = "1.2.3";
1396
1397     /* Test with empty info */
1398     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1399      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1400     if (buf)
1401     {
1402         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1403         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1404         LocalFree(buf);
1405     }
1406     /* Test with an empty entry */
1407     info.cAltEntry = 1;
1408     info.rgAltEntry = &entry;
1409     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1410      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1411     ok(!ret && GetLastError() == E_INVALIDARG,
1412      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1413     /* Test with an empty pointer */
1414     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1415     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1416      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1417     if (buf)
1418     {
1419         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1420         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1421         LocalFree(buf);
1422     }
1423     /* Test with a real URL */
1424     U(entry).pwszURL = (LPWSTR)url;
1425     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1426      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1427     if (buf)
1428     {
1429         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1430         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1431         LocalFree(buf);
1432     }
1433     /* Now with the URL containing an invalid IA5 char */
1434     U(entry).pwszURL = (LPWSTR)nihongoURL;
1435     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1436      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1437     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1438      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1439     /* The first invalid character is at index 7 */
1440     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1441      "Expected invalid char at index 7, got %d\n",
1442      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1443     /* Now with the URL missing a scheme */
1444     U(entry).pwszURL = (LPWSTR)dnsName;
1445     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1446      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1447     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1448     if (buf)
1449     {
1450         /* This succeeds, but it shouldn't, so don't worry about conforming */
1451         LocalFree(buf);
1452     }
1453     /* Now with a DNS name */
1454     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1455     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1456      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1457     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1458     if (buf)
1459     {
1460         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1461         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1462         LocalFree(buf);
1463     }
1464     /* Test with an IP address */
1465     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1466     U(entry).IPAddress.cbData = sizeof(localhost);
1467     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1468     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1469      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1470     if (buf)
1471     {
1472         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1473         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1474         LocalFree(buf);
1475     }
1476     /* Test with OID */
1477     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1478     U(entry).pszRegisteredID = oid;
1479     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1480      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1481     if (buf)
1482     {
1483         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1484         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1485         LocalFree(buf);
1486     }
1487     /* Test with directory name */
1488     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1489     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1490     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1491     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1492      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1493     if (buf)
1494     {
1495         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1496         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1497         LocalFree(buf);
1498     }
1499 }
1500
1501 static void test_decodeAltName(DWORD dwEncoding)
1502 {
1503     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1504      0x00, 0x00, 0x01 };
1505     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1506      0x01 };
1507     BOOL ret;
1508     BYTE *buf = NULL;
1509     DWORD bufSize = 0;
1510     CERT_ALT_NAME_INFO *info;
1511
1512     /* Test some bogus ones first */
1513     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1514      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1515      NULL, &buf, &bufSize);
1516     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1517      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1518      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1519      GetLastError());
1520     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1521      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1522      &bufSize);
1523     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1524      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1525      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1526      GetLastError());
1527     /* Now expected cases */
1528     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1529      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1530     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1531     if (buf)
1532     {
1533         info = (CERT_ALT_NAME_INFO *)buf;
1534
1535         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1536          info->cAltEntry);
1537         LocalFree(buf);
1538     }
1539     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1540      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1541     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1542     if (buf)
1543     {
1544         info = (CERT_ALT_NAME_INFO *)buf;
1545
1546         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1547          info->cAltEntry);
1548         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1549          "Expected CERT_ALT_NAME_URL, got %d\n",
1550          info->rgAltEntry[0].dwAltNameChoice);
1551         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1552          "Expected empty URL\n");
1553         LocalFree(buf);
1554     }
1555     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1556      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1557     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1558     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1559      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1560     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1561     if (buf)
1562     {
1563         info = (CERT_ALT_NAME_INFO *)buf;
1564
1565         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1566          info->cAltEntry);
1567         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1568          "Expected CERT_ALT_NAME_URL, got %d\n",
1569          info->rgAltEntry[0].dwAltNameChoice);
1570         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1571         LocalFree(buf);
1572     }
1573     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1574      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1575     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1576     if (buf)
1577     {
1578         info = (CERT_ALT_NAME_INFO *)buf;
1579
1580         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1581          info->cAltEntry);
1582         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1583          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1584          info->rgAltEntry[0].dwAltNameChoice);
1585         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1586          "Unexpected DNS name\n");
1587         LocalFree(buf);
1588     }
1589     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1590      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1591     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1592     if (buf)
1593     {
1594         info = (CERT_ALT_NAME_INFO *)buf;
1595
1596         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1597          info->cAltEntry);
1598         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1599          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1600          info->rgAltEntry[0].dwAltNameChoice);
1601         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1602          "Unexpected IP address length %d\n",
1603           U(info->rgAltEntry[0]).IPAddress.cbData);
1604         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1605          sizeof(localhost)), "Unexpected IP address value\n");
1606         LocalFree(buf);
1607     }
1608     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1609      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1610     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1611     if (buf)
1612     {
1613         info = (CERT_ALT_NAME_INFO *)buf;
1614
1615         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1616          info->cAltEntry);
1617         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1618          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1619          info->rgAltEntry[0].dwAltNameChoice);
1620         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1621            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1622         LocalFree(buf);
1623     }
1624     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1625      encodedDirectoryName, sizeof(encodedDirectoryName),
1626      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1627     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1628     if (buf)
1629     {
1630         info = (CERT_ALT_NAME_INFO *)buf;
1631
1632         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1633          info->cAltEntry);
1634         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1635          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1636          info->rgAltEntry[0].dwAltNameChoice);
1637         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1638          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1639           U(info->rgAltEntry[0]).DirectoryName.cbData);
1640         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1641          encodedCommonName, sizeof(encodedCommonName)),
1642          "Unexpected directory name value\n");
1643         LocalFree(buf);
1644     }
1645 }
1646
1647 struct UnicodeExpectedError
1648 {
1649     DWORD   valueType;
1650     LPCWSTR str;
1651     DWORD   errorIndex;
1652     DWORD   error;
1653 };
1654
1655 static const WCHAR oneW[] = { '1',0 };
1656 static const WCHAR aW[] = { 'a',0 };
1657 static const WCHAR quoteW[] = { '"', 0 };
1658
1659 static struct UnicodeExpectedError unicodeErrors[] = {
1660  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1661  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1662  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1663  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1664  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1665  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1666 };
1667
1668 struct UnicodeExpectedResult
1669 {
1670     DWORD           valueType;
1671     LPCWSTR         str;
1672     CRYPT_DATA_BLOB encoded;
1673 };
1674
1675 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1676 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1677 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1678 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1679 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1680 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1681 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1682 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1683 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1684 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1685 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1686 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1687  0x5b };
1688 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1689  0x6f,0x5b };
1690 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1691  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1692 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1693  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1694
1695 static struct UnicodeExpectedResult unicodeResults[] = {
1696  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1697  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1698  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1699  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1700  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1701  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1702  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1703  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1704  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1705  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1706  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1707  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1708  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1709 };
1710
1711 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1712  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1713  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1714 };
1715
1716 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1717 {
1718     BYTE *buf = NULL;
1719     DWORD size = 0, i;
1720     BOOL ret;
1721     CERT_NAME_VALUE value;
1722
1723     if (0)
1724     {
1725         /* Crashes on win9x */
1726         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1727          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1728         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1729          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1730     }
1731     /* Have to have a string of some sort */
1732     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1733     value.Value.pbData = NULL;
1734     value.Value.cbData = 0;
1735     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1736      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1737     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1738      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1739     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1740     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1741      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1742     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1743      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1744     value.dwValueType = CERT_RDN_ANY_TYPE;
1745     value.Value.pbData = (LPBYTE)oneW;
1746     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1747      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1748     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1749      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1750     value.Value.cbData = sizeof(oneW);
1751     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1752      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1753     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1754      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1755     /* An encoded string with specified length isn't good enough either */
1756     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1757     value.Value.pbData = oneUniversal;
1758     value.Value.cbData = sizeof(oneUniversal);
1759     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1760      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1761     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1762      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1763     /* More failure checking */
1764     value.Value.cbData = 0;
1765     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1766     {
1767         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1768         value.dwValueType = unicodeErrors[i].valueType;
1769         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1770          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1771         ok(!ret && GetLastError() == unicodeErrors[i].error,
1772          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1773          unicodeErrors[i].error, GetLastError());
1774         ok(size == unicodeErrors[i].errorIndex,
1775          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1776          size);
1777     }
1778     /* cbData can be zero if the string is NULL-terminated */
1779     value.Value.cbData = 0;
1780     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1781     {
1782         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1783         value.dwValueType = unicodeResults[i].valueType;
1784         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1785          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1786         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1787          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1788         if (buf)
1789         {
1790             ok(size == unicodeResults[i].encoded.cbData,
1791              "Value type %d: expected size %d, got %d\n",
1792              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1793             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1794              "Value type %d: unexpected value\n", value.dwValueType);
1795             LocalFree(buf);
1796         }
1797     }
1798     /* These "encode," but they do so by truncating each unicode character
1799      * rather than properly encoding it.  Kept separate from the proper results,
1800      * because the encoded forms won't decode to their original strings.
1801      */
1802     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1803     {
1804         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1805         value.dwValueType = unicodeWeirdness[i].valueType;
1806         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1807          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1808         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1809         if (buf)
1810         {
1811             ok(size == unicodeWeirdness[i].encoded.cbData,
1812              "Value type %d: expected size %d, got %d\n",
1813              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1814             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1815              "Value type %d: unexpected value\n", value.dwValueType);
1816             LocalFree(buf);
1817         }
1818     }
1819 }
1820
1821 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1822 {
1823     if (n <= 0) return 0;
1824     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1825     return *str1 - *str2;
1826 }
1827
1828 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1829 {
1830     DWORD i;
1831
1832     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1833     {
1834         BYTE *buf = NULL;
1835         BOOL ret;
1836         DWORD size = 0;
1837
1838         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1839          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1840          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1841         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1842          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1843         if (ret && buf)
1844         {
1845             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1846
1847             ok(value->dwValueType == unicodeResults[i].valueType,
1848              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1849              value->dwValueType);
1850             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1851              value->Value.cbData / sizeof(WCHAR)),
1852              "Unexpected decoded value for index %d (value type %d)\n", i,
1853              unicodeResults[i].valueType);
1854             LocalFree(buf);
1855         }
1856     }
1857 }
1858
1859 struct encodedOctets
1860 {
1861     const BYTE *val;
1862     const BYTE *encoded;
1863 };
1864
1865 static const unsigned char bin46[] = { 'h','i',0 };
1866 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1867 static const unsigned char bin48[] = {
1868      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1869 static const unsigned char bin49[] = {
1870      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1871 static const unsigned char bin50[] = { 0 };
1872 static const unsigned char bin51[] = { 0x04,0x00,0 };
1873
1874 static const struct encodedOctets octets[] = {
1875     { bin46, bin47 },
1876     { bin48, bin49 },
1877     { bin50, bin51 },
1878 };
1879
1880 static void test_encodeOctets(DWORD dwEncoding)
1881 {
1882     CRYPT_DATA_BLOB blob;
1883     DWORD i;
1884
1885     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1886     {
1887         BYTE *buf = NULL;
1888         BOOL ret;
1889         DWORD bufSize = 0;
1890
1891         blob.cbData = strlen((const char*)octets[i].val);
1892         blob.pbData = (BYTE*)octets[i].val;
1893         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1894          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1895         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1896         if (buf)
1897         {
1898             ok(buf[0] == 4,
1899              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1900             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1901              buf[1], octets[i].encoded[1]);
1902             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1903              octets[i].encoded[1] + 1), "Got unexpected value\n");
1904             LocalFree(buf);
1905         }
1906     }
1907 }
1908
1909 static void test_decodeOctets(DWORD dwEncoding)
1910 {
1911     DWORD i;
1912
1913     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1914     {
1915         BYTE *buf = NULL;
1916         BOOL ret;
1917         DWORD bufSize = 0;
1918
1919         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1920          octets[i].encoded, octets[i].encoded[1] + 2,
1921          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1922         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1923         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1924          "Expected size >= %d, got %d\n",
1925            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1926         ok(buf != NULL, "Expected allocated buffer\n");
1927         if (buf)
1928         {
1929             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1930
1931             if (blob->cbData)
1932                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1933                  "Unexpected value\n");
1934             LocalFree(buf);
1935         }
1936     }
1937 }
1938
1939 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1940
1941 struct encodedBits
1942 {
1943     DWORD cUnusedBits;
1944     const BYTE *encoded;
1945     DWORD cbDecoded;
1946     const BYTE *decoded;
1947 };
1948
1949 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1950 static const unsigned char bin53[] = { 0xff,0xff };
1951 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1952 static const unsigned char bin55[] = { 0xff,0xfe };
1953 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1954 static const unsigned char bin57[] = { 0xfe };
1955 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1956
1957 static const struct encodedBits bits[] = {
1958     /* normal test cases */
1959     { 0, bin52, 2, bin53 },
1960     { 1, bin54, 2, bin55 },
1961     /* strange test case, showing cUnusedBits >= 8 is allowed */
1962     { 9, bin56, 1, bin57 },
1963 };
1964
1965 static void test_encodeBits(DWORD dwEncoding)
1966 {
1967     DWORD i;
1968
1969     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1970     {
1971         CRYPT_BIT_BLOB blob;
1972         BOOL ret;
1973         BYTE *buf = NULL;
1974         DWORD bufSize = 0;
1975
1976         blob.cbData = sizeof(bytesToEncode);
1977         blob.pbData = (BYTE *)bytesToEncode;
1978         blob.cUnusedBits = bits[i].cUnusedBits;
1979         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1980          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1981         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1982         if (buf)
1983         {
1984             ok(bufSize == bits[i].encoded[1] + 2,
1985              "%d: Got unexpected size %d, expected %d\n", i, bufSize,
1986              bits[i].encoded[1] + 2);
1987             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1988              "%d: Unexpected value\n", i);
1989             LocalFree(buf);
1990         }
1991     }
1992 }
1993
1994 static void test_decodeBits(DWORD dwEncoding)
1995 {
1996     static const BYTE ber[] = "\x03\x02\x01\xff";
1997     static const BYTE berDecoded = 0xfe;
1998     DWORD i;
1999     BOOL ret;
2000     BYTE *buf = NULL;
2001     DWORD bufSize = 0;
2002
2003     /* normal cases */
2004     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2005     {
2006         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2007          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2008          &bufSize);
2009         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2010         if (buf)
2011         {
2012             CRYPT_BIT_BLOB *blob;
2013
2014             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2015                "Got unexpected size %d\n", bufSize);
2016             blob = (CRYPT_BIT_BLOB *)buf;
2017             ok(blob->cbData == bits[i].cbDecoded,
2018              "Got unexpected length %d, expected %d\n", blob->cbData,
2019              bits[i].cbDecoded);
2020             if (blob->cbData && bits[i].cbDecoded)
2021                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2022                  "Unexpected value\n");
2023             LocalFree(buf);
2024         }
2025     }
2026     /* special case: check that something that's valid in BER but not in DER
2027      * decodes successfully
2028      */
2029     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2030      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2031     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2032     if (buf)
2033     {
2034         CRYPT_BIT_BLOB *blob;
2035
2036         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2037            "Got unexpected size %d\n", bufSize);
2038         blob = (CRYPT_BIT_BLOB *)buf;
2039         ok(blob->cbData == sizeof(berDecoded),
2040            "Got unexpected length %d\n", blob->cbData);
2041         if (blob->cbData)
2042             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2043         LocalFree(buf);
2044     }
2045 }
2046
2047 struct Constraints2
2048 {
2049     CERT_BASIC_CONSTRAINTS2_INFO info;
2050     const BYTE *encoded;
2051 };
2052
2053 static const unsigned char bin59[] = { 0x30,0x00 };
2054 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2055 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2056 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2057 static const struct Constraints2 constraints2[] = {
2058  /* empty constraints */
2059  { { FALSE, FALSE, 0}, bin59 },
2060  /* can be a CA */
2061  { { TRUE,  FALSE, 0}, bin60 },
2062  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2063   * but that's not the case
2064   */
2065  { { FALSE, TRUE,  0}, bin61 },
2066  /* can be a CA and has path length constraints set */
2067  { { TRUE,  TRUE,  1}, bin62 },
2068 };
2069
2070 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2071 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2072  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2073  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2074  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2075 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2076  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2077  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2078  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2079  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2080
2081 static void test_encodeBasicConstraints(DWORD dwEncoding)
2082 {
2083     DWORD i, bufSize = 0;
2084     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2085     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2086      (LPBYTE)encodedDomainName };
2087     BOOL ret;
2088     BYTE *buf = NULL;
2089
2090     /* First test with the simpler info2 */
2091     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2092     {
2093         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2094          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2095          &bufSize);
2096         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2097         if (buf)
2098         {
2099             ok(bufSize == constraints2[i].encoded[1] + 2,
2100              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2101              bufSize);
2102             ok(!memcmp(buf, constraints2[i].encoded,
2103              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2104             LocalFree(buf);
2105         }
2106     }
2107     /* Now test with more complex basic constraints */
2108     info.SubjectType.cbData = 0;
2109     info.fPathLenConstraint = FALSE;
2110     info.cSubtreesConstraint = 0;
2111     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2112      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2113     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2114      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2115     if (buf)
2116     {
2117         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2118         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2119          "Unexpected value\n");
2120         LocalFree(buf);
2121     }
2122     /* None of the certs I examined had any subtree constraint, but I test one
2123      * anyway just in case.
2124      */
2125     info.cSubtreesConstraint = 1;
2126     info.rgSubtreesConstraint = &nameBlob;
2127     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2128      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2129     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2130      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2131     if (buf)
2132     {
2133         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2134         ok(!memcmp(buf, constraintWithDomainName,
2135          sizeof(constraintWithDomainName)), "Unexpected value\n");
2136         LocalFree(buf);
2137     }
2138     /* FIXME: test encoding with subject type. */
2139 }
2140
2141 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2142
2143 static void test_decodeBasicConstraints(DWORD dwEncoding)
2144 {
2145     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2146      0xff };
2147     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2148     DWORD i;
2149     BOOL ret;
2150     BYTE *buf = NULL;
2151     DWORD bufSize = 0;
2152
2153     /* First test with simpler info2 */
2154     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2155     {
2156         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2157          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2158          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2159         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2160          GetLastError());
2161         if (buf)
2162         {
2163             CERT_BASIC_CONSTRAINTS2_INFO *info =
2164              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2165
2166             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2167              "Unexpected value for item %d\n", i);
2168             LocalFree(buf);
2169         }
2170     }
2171     /* Check with the order of encoded elements inverted */
2172     buf = (PBYTE)1;
2173     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2174      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2175      &bufSize);
2176     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2177      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2178      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2179      GetLastError());
2180     ok(!buf, "Expected buf to be set to NULL\n");
2181     /* Check with a non-DER bool */
2182     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2183      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2184      &buf, &bufSize);
2185     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2186     if (buf)
2187     {
2188         CERT_BASIC_CONSTRAINTS2_INFO *info =
2189          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2190
2191         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2192         LocalFree(buf);
2193     }
2194     /* Check with a non-basic constraints value */
2195     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2196      encodedCommonName, encodedCommonName[1] + 2,
2197      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2198     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2199      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2200      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2201      GetLastError());
2202     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2203     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2204      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2205      &buf, &bufSize);
2206     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2207     if (buf)
2208     {
2209         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2210
2211         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2212         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2213         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2214         LocalFree(buf);
2215     }
2216     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2217      constraintWithDomainName, sizeof(constraintWithDomainName),
2218      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2219     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2220     if (buf)
2221     {
2222         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2223
2224         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2225         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2226         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2227         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2228         {
2229             ok(info->rgSubtreesConstraint[0].cbData ==
2230              sizeof(encodedDomainName), "Wrong size %d\n",
2231              info->rgSubtreesConstraint[0].cbData);
2232             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2233              sizeof(encodedDomainName)), "Unexpected value\n");
2234         }
2235         LocalFree(buf);
2236     }
2237 }
2238
2239 /* These are terrible public keys of course, I'm just testing encoding */
2240 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2241 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2242 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2243 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2244 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2245 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2246 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2247 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2248
2249 struct EncodedRSAPubKey
2250 {
2251     const BYTE *modulus;
2252     size_t modulusLen;
2253     const BYTE *encoded;
2254     size_t decodedModulusLen;
2255 };
2256
2257 struct EncodedRSAPubKey rsaPubKeys[] = {
2258     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2259     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2260     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2261     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2262 };
2263
2264 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2265 {
2266     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2267     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2268     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2269     BOOL ret;
2270     BYTE *buf = NULL;
2271     DWORD bufSize = 0, i;
2272
2273     /* Try with a bogus blob type */
2274     hdr->bType = 2;
2275     hdr->bVersion = CUR_BLOB_VERSION;
2276     hdr->reserved = 0;
2277     hdr->aiKeyAlg = CALG_RSA_KEYX;
2278     rsaPubKey->magic = 0x31415352;
2279     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2280     rsaPubKey->pubexp = 65537;
2281     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2282      sizeof(modulus1));
2283
2284     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2285      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2286     ok(!ret && GetLastError() == E_INVALIDARG,
2287      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2288     /* Now with a bogus reserved field */
2289     hdr->bType = PUBLICKEYBLOB;
2290     hdr->reserved = 1;
2291     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2292      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2293     if (buf)
2294     {
2295         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2296          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2297         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2298         LocalFree(buf);
2299     }
2300     /* Now with a bogus blob version */
2301     hdr->reserved = 0;
2302     hdr->bVersion = 0;
2303     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2304      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2305     if (buf)
2306     {
2307         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2308          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2309         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2310         LocalFree(buf);
2311     }
2312     /* And with a bogus alg ID */
2313     hdr->bVersion = CUR_BLOB_VERSION;
2314     hdr->aiKeyAlg = CALG_DES;
2315     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2316      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2317     if (buf)
2318     {
2319         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2320          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2321         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2322         LocalFree(buf);
2323     }
2324     /* Check a couple of RSA-related OIDs */
2325     hdr->aiKeyAlg = CALG_RSA_KEYX;
2326     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2327      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2328     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2329      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2330     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2331      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2332     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2333      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2334     /* Finally, all valid */
2335     hdr->aiKeyAlg = CALG_RSA_KEYX;
2336     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2337     {
2338         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2339          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2340         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2341          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2342         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2343         if (buf)
2344         {
2345             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2346              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2347              bufSize);
2348             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2349              "Unexpected value\n");
2350             LocalFree(buf);
2351         }
2352     }
2353 }
2354
2355 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2356 {
2357     DWORD i;
2358     LPBYTE buf = NULL;
2359     DWORD bufSize = 0;
2360     BOOL ret;
2361
2362     /* Try with a bad length */
2363     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2364      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2365      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2366     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2367      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2368      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2369      GetLastError());
2370     /* Try with a couple of RSA-related OIDs */
2371     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2372      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2373      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2374     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2375      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2376     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2377      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2378      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2379     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2380      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2381     /* Now try success cases */
2382     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2383     {
2384         bufSize = 0;
2385         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2386          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2387          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2388         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2389         if (buf)
2390         {
2391             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2392             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2393
2394             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2395              rsaPubKeys[i].decodedModulusLen,
2396              "Wrong size %d\n", bufSize);
2397             ok(hdr->bType == PUBLICKEYBLOB,
2398              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2399              hdr->bType);
2400             ok(hdr->bVersion == CUR_BLOB_VERSION,
2401              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2402              CUR_BLOB_VERSION, hdr->bVersion);
2403             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2404              hdr->reserved);
2405             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2406              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2407             ok(rsaPubKey->magic == 0x31415352,
2408              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2409             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2410              "Wrong bit len %d\n", rsaPubKey->bitlen);
2411             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2412              rsaPubKey->pubexp);
2413             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2414              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2415              "Unexpected modulus\n");
2416             LocalFree(buf);
2417         }
2418     }
2419 }
2420
2421 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2422  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2423  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2424
2425 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2426  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2427  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2428  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2429
2430 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2431 {
2432     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2433     CRYPT_SEQUENCE_OF_ANY seq;
2434     DWORD i;
2435     BOOL ret;
2436     BYTE *buf = NULL;
2437     DWORD bufSize = 0;
2438
2439     /* Encode a homogeneous sequence */
2440     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2441     {
2442         blobs[i].cbData = ints[i].encoded[1] + 2;
2443         blobs[i].pbData = (BYTE *)ints[i].encoded;
2444     }
2445     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2446     seq.rgValue = blobs;
2447
2448     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2449      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2450     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2451     if (buf)
2452     {
2453         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2454         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2455         LocalFree(buf);
2456     }
2457     /* Change the type of the first element in the sequence, and give it
2458      * another go
2459      */
2460     blobs[0].cbData = times[0].encodedTime[1] + 2;
2461     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2462     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2463      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2464     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2465     if (buf)
2466     {
2467         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2468         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2469          "Unexpected value\n");
2470         LocalFree(buf);
2471     }
2472 }
2473
2474 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2475 {
2476     BOOL ret;
2477     BYTE *buf = NULL;
2478     DWORD bufSize = 0;
2479
2480     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2481      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2482     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2483     if (buf)
2484     {
2485         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2486         DWORD i;
2487
2488         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2489          "Wrong elements %d\n", seq->cValue);
2490         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2491         {
2492             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2493              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2494              seq->rgValue[i].cbData);
2495             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2496              ints[i].encoded[1] + 2), "Unexpected value\n");
2497         }
2498         LocalFree(buf);
2499     }
2500     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2501      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2502      &bufSize);
2503     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2504     if (buf)
2505     {
2506         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2507
2508         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2509          "Wrong elements %d\n", seq->cValue);
2510         /* Just check the first element since it's all that changed */
2511         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2512          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2513          seq->rgValue[0].cbData);
2514         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2515          times[0].encodedTime[1] + 2), "Unexpected value\n");
2516         LocalFree(buf);
2517     }
2518 }
2519
2520 struct encodedExtensions
2521 {
2522     CERT_EXTENSIONS exts;
2523     const BYTE *encoded;
2524 };
2525
2526 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2527 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2528 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2529 static CERT_EXTENSION criticalExt =
2530  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2531 static CERT_EXTENSION nonCriticalExt =
2532  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2533 static CHAR oid_short[] = "1.1";
2534 static CERT_EXTENSION extWithShortOid =
2535  { oid_short, FALSE, { 0, NULL } };
2536
2537 static const BYTE ext0[] = { 0x30,0x00 };
2538 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2539                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2540 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2541                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2542 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2543
2544 static const struct encodedExtensions exts[] = {
2545  { { 0, NULL }, ext0 },
2546  { { 1, &criticalExt }, ext1 },
2547  { { 1, &nonCriticalExt }, ext2 },
2548  { { 1, &extWithShortOid }, ext3 }
2549 };
2550
2551 static void test_encodeExtensions(DWORD dwEncoding)
2552 {
2553     DWORD i;
2554
2555     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2556     {
2557         BOOL ret;
2558         BYTE *buf = NULL;
2559         DWORD bufSize = 0;
2560
2561         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2562          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2563         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2564         if (buf)
2565         {
2566             ok(bufSize == exts[i].encoded[1] + 2,
2567              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2568             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2569              "Unexpected value\n");
2570             LocalFree(buf);
2571         }
2572     }
2573 }
2574
2575 static void test_decodeExtensions(DWORD dwEncoding)
2576 {
2577     DWORD i;
2578
2579     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2580     {
2581         BOOL ret;
2582         BYTE *buf = NULL;
2583         DWORD bufSize = 0;
2584
2585         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2586          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2587          NULL, &buf, &bufSize);
2588         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2589         if (buf)
2590         {
2591             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2592             DWORD j;
2593
2594             ok(ext->cExtension == exts[i].exts.cExtension,
2595              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2596              ext->cExtension);
2597             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2598             {
2599                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2600                  exts[i].exts.rgExtension[j].pszObjId),
2601                  "Expected OID %s, got %s\n",
2602                  exts[i].exts.rgExtension[j].pszObjId,
2603                  ext->rgExtension[j].pszObjId);
2604                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2605                  exts[i].exts.rgExtension[j].Value.pbData,
2606                  exts[i].exts.rgExtension[j].Value.cbData),
2607                  "Unexpected value\n");
2608             }
2609             LocalFree(buf);
2610         }
2611     }
2612 }
2613
2614 /* MS encodes public key info with a NULL if the algorithm identifier's
2615  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2616  * it encodes them by omitting the algorithm parameters.  It accepts either
2617  * form for decoding.
2618  */
2619 struct encodedPublicKey
2620 {
2621     CERT_PUBLIC_KEY_INFO info;
2622     const BYTE *encoded;
2623     const BYTE *encodedNoNull;
2624     CERT_PUBLIC_KEY_INFO decoded;
2625 };
2626
2627 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2628  0xe, 0xf };
2629 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2630
2631 static const unsigned char bin64[] = {
2632     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2633 static const unsigned char bin65[] = {
2634     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2635 static const unsigned char bin66[] = {
2636     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2637 static const unsigned char bin67[] = {
2638     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2639 static const unsigned char bin68[] = {
2640     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2641     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2642 static const unsigned char bin69[] = {
2643     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2644     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2645 static const unsigned char bin70[] = {
2646     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2647     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2648     0x0f};
2649 static const unsigned char bin71[] = {
2650     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2651     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2652     0x0f};
2653 static unsigned char bin72[] = { 0x05,0x00};
2654
2655 static CHAR oid_bogus[] = "1.2.3",
2656             oid_rsa[]   = szOID_RSA;
2657
2658 static const struct encodedPublicKey pubKeys[] = {
2659  /* with a bogus OID */
2660  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2661   bin64, bin65,
2662   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2663  /* some normal keys */
2664  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2665   bin66, bin67,
2666   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2667  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2668   bin68, bin69,
2669   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2670  /* with add'l parameters--note they must be DER-encoded */
2671  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2672   (BYTE *)aKey, 0 } },
2673   bin70, bin71,
2674   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2675   (BYTE *)aKey, 0 } } },
2676 };
2677
2678 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2679 {
2680     DWORD i;
2681
2682     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2683     {
2684         BOOL ret;
2685         BYTE *buf = NULL;
2686         DWORD bufSize = 0;
2687
2688         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2689          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2690          &bufSize);
2691         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2692          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2693         if (buf)
2694         {
2695             ok(bufSize == pubKeys[i].encoded[1] + 2,
2696              "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2697             if (bufSize == pubKeys[i].encoded[1] + 2)
2698                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2699                  "Unexpected value\n");
2700             LocalFree(buf);
2701         }
2702     }
2703 }
2704
2705 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2706  const CERT_PUBLIC_KEY_INFO *got)
2707 {
2708     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2709      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2710      got->Algorithm.pszObjId);
2711     ok(expected->Algorithm.Parameters.cbData ==
2712      got->Algorithm.Parameters.cbData,
2713      "Expected parameters of %d bytes, got %d\n",
2714      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2715     if (expected->Algorithm.Parameters.cbData)
2716         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2717          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2718          "Unexpected algorithm parameters\n");
2719     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2720      "Expected public key of %d bytes, got %d\n",
2721      expected->PublicKey.cbData, got->PublicKey.cbData);
2722     if (expected->PublicKey.cbData)
2723         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2724          got->PublicKey.cbData), "Unexpected public key value\n");
2725 }
2726
2727 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2728 {
2729     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2730      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2731      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2732      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2733     DWORD i;
2734     BOOL ret;
2735     BYTE *buf = NULL;
2736     DWORD bufSize = 0;
2737
2738     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2739     {
2740         /* The NULL form decodes to the decoded member */
2741         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2742          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2743          NULL, &buf, &bufSize);
2744         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2745         if (buf)
2746         {
2747             comparePublicKeyInfo(&pubKeys[i].decoded,
2748              (CERT_PUBLIC_KEY_INFO *)buf);
2749             LocalFree(buf);
2750         }
2751         /* The non-NULL form decodes to the original */
2752         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2753          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2754          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2755         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2756         if (buf)
2757         {
2758             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2759             LocalFree(buf);
2760         }
2761     }
2762     /* Test with bogus (not valid DER) parameters */
2763     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2764      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2765      NULL, &buf, &bufSize);
2766     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2767      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2768      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2769      GetLastError());
2770 }
2771
2772 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2773  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2774  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2775  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2776  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2777 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2778  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2779  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2780  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2781  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2782 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2783  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2784  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2785  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2786  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2787 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2788  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2789  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2790  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2791  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2792  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2793  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2794 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2795  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2796  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2797  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2798  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2799  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2800  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2801 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2802  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2803  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2804  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2805  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2806  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2807  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2808  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2809  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2810  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2811 static const BYTE v1CertWithPubKey[] = {
2812 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2813 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2814 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2815 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2816 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2817 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2818 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2819 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2820 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2821 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2822 0x01,0x01 };
2823 static const BYTE v1CertWithPubKeyNoNull[] = {
2824 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2825 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2826 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2827 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2828 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2829 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2830 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2831 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2832 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2833 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2834 static const BYTE v1CertWithSubjectKeyId[] = {
2835 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2836 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2837 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2838 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2839 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2840 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2841 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2842 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2843 0x4c,0x61,0x6e,0x67,0x00 };
2844
2845 static const BYTE serialNum[] = { 0x01 };
2846
2847 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2848 {
2849     BOOL ret;
2850     BYTE *buf = NULL;
2851     DWORD size = 0;
2852     CERT_INFO info = { 0 };
2853     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2854     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2855     CERT_EXTENSION ext;
2856
2857     if (0)
2858     {
2859         /* Test with NULL pvStructInfo (crashes on win9x) */
2860         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2861          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2862         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2863          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2864     }
2865     /* Test with a V1 cert */
2866     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2867      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2868     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2869      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2870     if (buf)
2871     {
2872         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2873          v1Cert[1] + 2, size);
2874         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2875         LocalFree(buf);
2876     }
2877     /* Test v2 cert */
2878     info.dwVersion = CERT_V2;
2879     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2880      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2881     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2882      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2883     if (buf)
2884     {
2885         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2886         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2887         LocalFree(buf);
2888     }
2889     /* Test v3 cert */
2890     info.dwVersion = CERT_V3;
2891     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2892      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2893     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2894      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2895     if (buf)
2896     {
2897         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2898         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2899         LocalFree(buf);
2900     }
2901     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2902      * API doesn't prevent it)
2903      */
2904     info.dwVersion = CERT_V1;
2905     info.cExtension = 1;
2906     info.rgExtension = &criticalExt;
2907     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2908      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2909     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2910      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2911     if (buf)
2912     {
2913         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2914         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2915         LocalFree(buf);
2916     }
2917     /* test v1 cert with a serial number */
2918     info.SerialNumber.cbData = sizeof(serialNum);
2919     info.SerialNumber.pbData = (BYTE *)serialNum;
2920     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2921      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2922     if (buf)
2923     {
2924         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2925         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2926         LocalFree(buf);
2927     }
2928     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2929     info.Issuer.cbData = sizeof(encodedCommonName);
2930     info.Issuer.pbData = (BYTE *)encodedCommonName;
2931     info.Subject.cbData = sizeof(encodedCommonName);
2932     info.Subject.pbData = (BYTE *)encodedCommonName;
2933     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2934      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2935     if (buf)
2936     {
2937         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2938         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2939         LocalFree(buf);
2940     }
2941     /* Add a public key */
2942     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2943     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2944     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2945     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2946      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2947     if (buf)
2948     {
2949         ok(size == sizeof(v1CertWithPubKey) ||
2950          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2951         if (size == sizeof(v1CertWithPubKey))
2952             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2953         else if (size == sizeof(v1CertWithPubKeyNoNull))
2954             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2955              "Got unexpected value\n");
2956         LocalFree(buf);
2957     }
2958     /* Remove the public key, and add a subject key identifier extension */
2959     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2960     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2961     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2962     ext.pszObjId = oid_subject_key_identifier;
2963     ext.fCritical = FALSE;
2964     ext.Value.cbData = sizeof(octetCommonNameValue);
2965     ext.Value.pbData = octetCommonNameValue;
2966     info.cExtension = 1;
2967     info.rgExtension = &ext;
2968     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2969      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2970     if (buf)
2971     {
2972         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2973         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2974         LocalFree(buf);
2975     }
2976 }
2977
2978 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2979 {
2980     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2981      v1CertWithConstraints, v1CertWithSerial };
2982     BOOL ret;
2983     BYTE *buf = NULL;
2984     DWORD size = 0, i;
2985
2986     /* Test with NULL pbEncoded */
2987     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2988      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
2989     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2990      GetLastError() == OSS_BAD_ARG /* Win9x */),
2991      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
2992     if (0)
2993     {
2994         /* Crashes on win9x */
2995         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2996          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
2997         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2998          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2999     }
3000     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
3001      * minimum a cert must have a non-zero serial number, an issuer, and a
3002      * subject.
3003      */
3004     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3005     {
3006         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3007          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3008          &buf, &size);
3009         ok(!ret, "Expected failure\n");
3010     }
3011     /* Now check with serial number, subject and issuer specified */
3012     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3013      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3014     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3015     if (buf)
3016     {
3017         CERT_INFO *info = (CERT_INFO *)buf;
3018
3019         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3020         ok(info->SerialNumber.cbData == 1,
3021          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3022         ok(*info->SerialNumber.pbData == *serialNum,
3023          "Expected serial number %d, got %d\n", *serialNum,
3024          *info->SerialNumber.pbData);
3025         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3026          "Wrong size %d\n", info->Issuer.cbData);
3027         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3028          "Unexpected issuer\n");
3029         ok(info->Subject.cbData == sizeof(encodedCommonName),
3030          "Wrong size %d\n", info->Subject.cbData);
3031         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3032          info->Subject.cbData), "Unexpected subject\n");
3033         LocalFree(buf);
3034     }
3035     /* Check again with pub key specified */
3036     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3037      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3038      &buf, &size);
3039     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3040     if (buf)
3041     {
3042         CERT_INFO *info = (CERT_INFO *)buf;
3043
3044         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3045         ok(info->SerialNumber.cbData == 1,
3046          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3047         ok(*info->SerialNumber.pbData == *serialNum,
3048          "Expected serial number %d, got %d\n", *serialNum,
3049          *info->SerialNumber.pbData);
3050         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3051          "Wrong size %d\n", info->Issuer.cbData);
3052         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3053          "Unexpected issuer\n");
3054         ok(info->Subject.cbData == sizeof(encodedCommonName),
3055          "Wrong size %d\n", info->Subject.cbData);
3056         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3057          info->Subject.cbData), "Unexpected subject\n");
3058         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3059          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3060          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3061         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3062          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3063         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3064          sizeof(aKey)), "Unexpected public key\n");
3065         LocalFree(buf);
3066     }
3067 }
3068
3069 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3070  0xe, 0xf };
3071
3072 static const BYTE signedBigCert[] = {
3073  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3074  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3075  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3076  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3077  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3078  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3079  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3080  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3081  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3082  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3083  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3084  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3085
3086 static void test_encodeCert(DWORD dwEncoding)
3087 {
3088     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3089      * also that bigCert is a NULL-terminated string, so don't count its
3090      * last byte (otherwise the signed cert won't decode.)
3091      */
3092     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3093      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3094     BOOL ret;
3095     BYTE *buf = NULL;
3096     DWORD bufSize = 0;
3097
3098     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3099      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3100     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3101     if (buf)
3102     {
3103         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3104         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3105         LocalFree(buf);
3106     }
3107 }
3108
3109 static void test_decodeCert(DWORD dwEncoding)
3110 {
3111     BOOL ret;
3112     BYTE *buf = NULL;
3113     DWORD size = 0;
3114
3115     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3116      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3117     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3118     if (buf)
3119     {
3120         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3121
3122         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3123          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3124         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3125          "Unexpected cert\n");
3126         ok(info->Signature.cbData == sizeof(hash),
3127          "Wrong signature size %d\n", info->Signature.cbData);
3128         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3129          "Unexpected signature\n");
3130         LocalFree(buf);
3131     }
3132     /* A signed cert decodes as a CERT_INFO too */
3133     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3134      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3135     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3136     if (buf)
3137     {
3138         CERT_INFO *info = (CERT_INFO *)buf;
3139
3140         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3141         ok(info->SerialNumber.cbData == 1,
3142          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3143         ok(*info->SerialNumber.pbData == *serialNum,
3144          "Expected serial number %d, got %d\n", *serialNum,
3145          *info->SerialNumber.pbData);
3146         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3147          "Wrong size %d\n", info->Issuer.cbData);
3148         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3149          "Unexpected issuer\n");
3150         ok(info->Subject.cbData == sizeof(encodedCommonName),
3151          "Wrong size %d\n", info->Subject.cbData);
3152         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3153          info->Subject.cbData), "Unexpected subject\n");
3154         LocalFree(buf);
3155     }
3156 }
3157
3158 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3159 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3160  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3161  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3162 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3163  0x00, 0x03 };
3164 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3165  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3166  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3167 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3168  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3169  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3170  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3171  0x2e, 0x6f, 0x72, 0x67 };
3172 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3173  CRL_REASON_AFFILIATION_CHANGED;
3174
3175 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3176 {
3177     CRL_DIST_POINTS_INFO info = { 0 };
3178     CRL_DIST_POINT point = { { 0 } };
3179     CERT_ALT_NAME_ENTRY entry = { 0 };
3180     BOOL ret;
3181     BYTE *buf = NULL;
3182     DWORD size = 0;
3183
3184     /* Test with an empty info */
3185     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3186      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3187     ok(!ret && GetLastError() == E_INVALIDARG,
3188      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3189     /* Test with one empty dist point */
3190     info.cDistPoint = 1;
3191     info.rgDistPoint = &point;
3192     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3193      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3194     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3195     if (buf)
3196     {
3197         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3198         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3199         LocalFree(buf);
3200     }
3201     /* A dist point with an invalid name */
3202     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3203     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3204     U(entry).pwszURL = (LPWSTR)nihongoURL;
3205     U(point.DistPointName).FullName.cAltEntry = 1;
3206     U(point.DistPointName).FullName.rgAltEntry = &entry;
3207     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3208      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3209     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3210      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3211     /* The first invalid character is at index 7 */
3212     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3213      "Expected invalid char at index 7, got %d\n",
3214      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3215     /* A dist point with (just) a valid name */
3216     U(entry).pwszURL = (LPWSTR)url;
3217     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3218      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3219     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3220     if (buf)
3221     {
3222         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3223         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3224         LocalFree(buf);
3225     }
3226     /* A dist point with (just) reason flags */
3227     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3228     point.ReasonFlags.cbData = sizeof(crlReason);
3229     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3230     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3231      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3232     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3233     if (buf)
3234     {
3235         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3236         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3237         LocalFree(buf);
3238     }
3239     /* A dist point with just an issuer */
3240     point.ReasonFlags.cbData = 0;
3241     point.CRLIssuer.cAltEntry = 1;
3242     point.CRLIssuer.rgAltEntry = &entry;
3243     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3244      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3245     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3246     if (buf)
3247     {
3248         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3249         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3250         LocalFree(buf);
3251     }
3252     /* A dist point with both a name and an issuer */
3253     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3254     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3255      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3256     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3257     if (buf)
3258     {
3259         ok(size == sizeof(distPointWithUrlAndIssuer),
3260          "Wrong size %d\n", size);
3261         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3262         LocalFree(buf);
3263     }
3264 }
3265
3266 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3267 {
3268     BOOL ret;
3269     BYTE *buf = NULL;
3270     DWORD size = 0;
3271     PCRL_DIST_POINTS_INFO info;
3272     PCRL_DIST_POINT point;
3273     PCERT_ALT_NAME_ENTRY entry;
3274
3275     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3276      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3277      &buf, &size);
3278     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3279     if (ret)
3280     {
3281         info = (PCRL_DIST_POINTS_INFO)buf;
3282         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3283          "Wrong size %d\n", size);
3284         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3285          info->cDistPoint);
3286         point = info->rgDistPoint;
3287         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3288          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3289          point->DistPointName.dwDistPointNameChoice);
3290         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3291         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3292         LocalFree(buf);
3293     }
3294     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3295      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3296      &buf, &size);
3297     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3298     if (ret)
3299     {
3300         info = (PCRL_DIST_POINTS_INFO)buf;
3301         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3302          "Wrong size %d\n", size);
3303         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3304          info->cDistPoint);
3305         point = info->rgDistPoint;
3306         ok(point->DistPointName.dwDistPointNameChoice ==
3307          CRL_DIST_POINT_FULL_NAME,
3308          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3309          point->DistPointName.dwDistPointNameChoice);
3310         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3311          "Expected 1 name entry, got %d\n",
3312          U(point->DistPointName).FullName.cAltEntry);
3313         entry = U(point->DistPointName).FullName.rgAltEntry;
3314         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3315          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3316         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3317         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3318         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3319         LocalFree(buf);
3320     }
3321     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3322      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3323      NULL, &buf, &size);
3324     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3325     if (ret)
3326     {
3327         info = (PCRL_DIST_POINTS_INFO)buf;
3328         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3329          "Wrong size %d\n", size);
3330         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3331          info->cDistPoint);
3332         point = info->rgDistPoint;
3333         ok(point->DistPointName.dwDistPointNameChoice ==
3334          CRL_DIST_POINT_NO_NAME,
3335          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3336          point->DistPointName.dwDistPointNameChoice);
3337         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3338          "Expected reason length\n");
3339         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3340          "Unexpected reason\n");
3341         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3342         LocalFree(buf);
3343     }
3344     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3345      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3346      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3347     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3348     if (ret)
3349     {
3350         info = (PCRL_DIST_POINTS_INFO)buf;
3351         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3352          "Wrong size %d\n", size);
3353         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3354          info->cDistPoint);
3355         point = info->rgDistPoint;
3356         ok(point->DistPointName.dwDistPointNameChoice ==
3357          CRL_DIST_POINT_FULL_NAME,
3358          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3359          point->DistPointName.dwDistPointNameChoice);
3360         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3361          "Expected 1 name entry, got %d\n",
3362          U(point->DistPointName).FullName.cAltEntry);
3363         entry = U(point->DistPointName).FullName.rgAltEntry;
3364         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3365          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3366         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3367         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3368         ok(point->CRLIssuer.cAltEntry == 1,
3369          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3370         entry = point->CRLIssuer.rgAltEntry;
3371         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3372          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3373         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3374         LocalFree(buf);
3375     }
3376 }
3377
3378 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3379 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3380 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3381  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3382  0x67 };
3383
3384 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3385 {
3386     BOOL ret;
3387     BYTE *buf = NULL;
3388     DWORD size = 0;
3389     CRL_ISSUING_DIST_POINT point = { { 0 } };
3390     CERT_ALT_NAME_ENTRY entry;
3391
3392     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3393      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3394     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3395     {
3396         skip("no X509_ISSUING_DIST_POINT encode support\n");
3397         return;
3398     }
3399     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3400      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3401     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3402      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3403     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3404     if (buf)
3405     {
3406         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3407         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3408         LocalFree(buf);
3409     }
3410     /* nonsensical flags */
3411     point.fOnlyContainsUserCerts = TRUE;
3412     point.fOnlyContainsCACerts = TRUE;
3413     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3414      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3415     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3416     if (buf)
3417     {
3418         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3419         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3420         LocalFree(buf);
3421     }
3422     /* unimplemented name type */
3423     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3424     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3425     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3426      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3427     ok(!ret && GetLastError() == E_INVALIDARG,
3428      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3429     /* empty name */
3430     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3431     U(point.DistPointName).FullName.cAltEntry = 0;
3432     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3433      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3434     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3435     if (buf)
3436     {
3437         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3438         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3439         LocalFree(buf);
3440     }
3441     /* name with URL entry */
3442     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3443     U(entry).pwszURL = (LPWSTR)url;
3444     U(point.DistPointName).FullName.cAltEntry = 1;
3445     U(point.DistPointName).FullName.rgAltEntry = &entry;
3446     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3447      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3448     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3449     if (buf)
3450     {
3451         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3452         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3453         LocalFree(buf);
3454     }
3455 }
3456
3457 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3458  const CERT_ALT_NAME_ENTRY *got)
3459 {
3460     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3461      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3462      got->dwAltNameChoice);
3463     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3464     {
3465         switch (got->dwAltNameChoice)
3466         {
3467         case CERT_ALT_NAME_RFC822_NAME:
3468         case CERT_ALT_NAME_DNS_NAME:
3469         case CERT_ALT_NAME_EDI_PARTY_NAME:
3470         case CERT_ALT_NAME_URL:
3471         case CERT_ALT_NAME_REGISTERED_ID:
3472             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3473              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3474              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3475              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3476              "Unexpected name\n");
3477             break;
3478         case CERT_ALT_NAME_X400_ADDRESS:
3479         case CERT_ALT_NAME_DIRECTORY_NAME:
3480         case CERT_ALT_NAME_IP_ADDRESS:
3481             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3482                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3483             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3484                        U(*got).IPAddress.cbData), "Unexpected value\n");
3485             break;
3486         }
3487     }
3488 }
3489
3490 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3491  const CERT_ALT_NAME_INFO *got)
3492 {
3493     DWORD i;
3494
3495     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3496      expected->cAltEntry, got->cAltEntry);
3497     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3498         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3499 }
3500
3501 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3502  const CRL_DIST_POINT_NAME *got)
3503 {
3504     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3505      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3506     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3507         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3508 }
3509
3510 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3511  const CRL_ISSUING_DIST_POINT *got)
3512 {
3513     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3514     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3515      "Unexpected fOnlyContainsUserCerts\n");
3516     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3517      "Unexpected fOnlyContainsCACerts\n");
3518     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3519      "Unexpected reason flags\n");
3520     ok(got->fIndirectCRL == expected->fIndirectCRL,
3521      "Unexpected fIndirectCRL\n");
3522 }
3523
3524 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3525 {
3526     BOOL ret;
3527     BYTE *buf = NULL;
3528     DWORD size = 0;
3529     CRL_ISSUING_DIST_POINT point = { { 0 } };
3530
3531     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3532      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3533      &buf, &size);
3534     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3535     {
3536         skip("no X509_ISSUING_DIST_POINT decode support\n");
3537         return;
3538     }
3539     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3540     if (ret)
3541     {
3542         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3543         LocalFree(buf);
3544     }
3545     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3546      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3547      &buf, &size);
3548     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3549     if (ret)
3550     {
3551         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3552         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3553         LocalFree(buf);
3554     }
3555     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3556      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3557      &buf, &size);
3558     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3559     if (ret)
3560     {
3561         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3562         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3563         U(point.DistPointName).FullName.cAltEntry = 0;
3564         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3565         LocalFree(buf);
3566     }
3567     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3568      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3569     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3570     if (ret)
3571     {
3572         CERT_ALT_NAME_ENTRY entry;
3573
3574         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3575         U(entry).pwszURL = (LPWSTR)url;
3576         U(point.DistPointName).FullName.cAltEntry = 1;
3577         U(point.DistPointName).FullName.rgAltEntry = &entry;
3578         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3579         LocalFree(buf);
3580     }
3581 }
3582
3583 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3584  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3585  0x30, 0x5a };
3586 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3587  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3588  0x30, 0x30, 0x30, 0x30, 0x5a };
3589 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3590  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3591  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3592  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3593  0x5a };
3594 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3595  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3596  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3597  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3598  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3599  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3600 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3601  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3602  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3603  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3604  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3605  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3606 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3607  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3608  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3609  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3610  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3611  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3612  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3613 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3614  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3615  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3616  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3617  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3618  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3619  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3620 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3621  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3622  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3623  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3624  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3625  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3626  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3627 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3628  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3629  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3630  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3631  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3632  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3633  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3634
3635 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3636 {
3637     BOOL ret;
3638     BYTE *buf = NULL;
3639     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3640     DWORD size = 0;
3641     CRL_INFO info = { 0 };
3642     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3643     CERT_EXTENSION ext;
3644
3645     /* Test with a V1 CRL */
3646     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3647      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3648     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3649      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3650     if (buf)
3651     {
3652         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3653         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3654         LocalFree(buf);
3655     }
3656     /* Test v2 CRL */
3657     info.dwVersion = CRL_V2;
3658     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3659      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3660     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3661      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3662     if (buf)
3663     {
3664         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3665          v2CRL[1] + 2, size);
3666         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3667         LocalFree(buf);
3668     }
3669     /* v1 CRL with a name */
3670     info.dwVersion = CRL_V1;
3671     info.Issuer.cbData = sizeof(encodedCommonName);
3672     info.Issuer.pbData = (BYTE *)encodedCommonName;
3673     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3674      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3675     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3676     if (buf)
3677     {
3678         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3679         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3680         LocalFree(buf);
3681     }
3682     if (0)
3683     {
3684         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3685         info.cCRLEntry = 1;
3686         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3687          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3688         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3689          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3690     }
3691     /* now set an empty entry */
3692     info.cCRLEntry = 1;
3693     info.rgCRLEntry = &entry;
3694     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3695      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3696     if (buf)
3697     {
3698         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3699          "Wrong size %d\n", size);
3700         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3701          "Got unexpected value\n");
3702         LocalFree(buf);
3703     }
3704     /* an entry with a serial number */
3705     entry.SerialNumber.cbData = sizeof(serialNum);
3706     entry.SerialNumber.pbData = (BYTE *)serialNum;
3707     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3708      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3709     if (buf)
3710     {
3711         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3712          "Wrong size %d\n", size);
3713         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3714          "Got unexpected value\n");
3715         LocalFree(buf);
3716     }
3717     /* an entry with an extension */
3718     entry.cExtension = 1;
3719     entry.rgExtension = &criticalExt;
3720     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3721      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3722     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3723     if (buf)
3724     {
3725         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3726         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3727         LocalFree(buf);
3728     }
3729     /* a CRL with an extension */
3730     entry.cExtension = 0;
3731     info.cExtension = 1;
3732     info.rgExtension = &criticalExt;
3733     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3734      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3735     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3736     if (buf)
3737     {
3738         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3739         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3740         LocalFree(buf);
3741     }
3742     /* a v2 CRL with an extension, this time non-critical */
3743     info.dwVersion = CRL_V2;
3744     info.rgExtension = &nonCriticalExt;
3745     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3746      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3747     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3748     if (buf)
3749     {
3750         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3751         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3752         LocalFree(buf);
3753     }
3754     /* a v2 CRL with an issuing dist point extension */
3755     ext.pszObjId = oid_issuing_dist_point;
3756     ext.fCritical = TRUE;
3757     ext.Value.cbData = sizeof(urlIDP);
3758     ext.Value.pbData = (LPBYTE)urlIDP;
3759     entry.rgExtension = &ext;
3760     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3761      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3762     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3763     if (buf)
3764     {
3765         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3766         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3767         LocalFree(buf);
3768     }
3769 }
3770
3771 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3772  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3773  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3774  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3775  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3776  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3777  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3778  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3779  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3780  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3781  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3782  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3783  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3784  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3785  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3786  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3787  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3788  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3789  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3790  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3791  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3792  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3793  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3794  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3795  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3796  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3797  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3798  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3799  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3800  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3801  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3802  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3803  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3804  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3805  0xcd };
3806 static const BYTE verisignCRLWithLotsOfEntries[] = {
3807 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3808 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3809 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3810 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3811 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3812 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3813 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3814 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3815 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3816 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3817 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3818 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3819 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3820 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3821 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3822 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3823 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3824 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3825 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3826 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3827 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3828 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3829 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3830 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3831 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3832 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3833 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3834 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3835 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3836 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3837 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3838 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3839 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3840 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3841 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3842 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3843 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3844 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3845 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3846 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3847 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3848 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3849 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3850 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3851 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3852 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3853 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3854 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3855 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3856 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3857 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3858 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3859 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3860 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3861 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3862 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3863 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3864 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3865 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3866 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3867 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3868 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3869 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3870 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3871 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3872 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3873 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3874 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3875 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3876 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3877 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3878 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3879 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3880 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3881 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3882 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3883 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3884 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3885 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3886 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3887 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3888 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3889 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3890 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3891 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3892 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3893 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3894 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3895 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3896 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3897 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3898 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3899 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3900 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3901 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3902 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3903 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3904 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3905 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3906 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3907 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3908 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3909 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3910 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3911 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3912 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3913 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3914 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3915 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3916 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3917 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3918 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3919 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3920 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3921 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3922 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3923 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3924 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3925 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3926 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3927 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3928 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3929 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3930 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3931 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3932 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3933 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3934 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3935 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3936 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3937 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3938 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3939 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3940 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3941 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3942 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3943 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3944 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3945 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3946 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3947 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3948 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3949 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3950 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3951 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3952 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3953 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3954 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3955 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3956 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3957 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3958 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3959 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3960 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3961 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3962 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3963 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3964 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3965 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3966 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3967 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3968 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3969 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3970 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3971 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3972 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3973 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3974 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3975 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3976 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3977 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3978 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3979 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3980 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3981 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3982 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3983 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3984 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3985 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3986 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3987 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3988 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3989 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3990 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3991 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3992 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3993 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3994 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3995 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3996 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3997 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3998 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3999 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4000 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4001 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4002 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4003 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4004 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4005 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4006 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4007 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4008 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4009 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4010 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4011 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4012 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4013 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4014 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4015 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4016 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4017 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4018 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4019 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4020 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4021 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4022 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4023 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4024 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4025 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4026 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4027 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4028 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4029 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4030 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4031 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4032 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4033 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4034 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4035 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4036 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4037 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4038 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4039 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4040 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4041 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4042 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4043 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4044 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4045 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4046 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4047 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4048 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4049 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4050 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4051 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4052 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4053 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4054 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4055 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4056 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4057 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4058 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4059 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4060 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4061 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4062 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4063 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4064 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4065 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4066 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4067 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4068 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4069 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4070 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4071 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4072 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4073 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4074 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4075 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4076 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4077 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4078 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4079 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4080 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4081 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4082 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4083 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4084 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4085 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4086 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4087 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4088 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4089 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4090 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4091 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4092 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4093 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4094 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4095 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4096 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4097 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4098 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4099 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4100 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4101 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4102 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4103 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4104 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4105 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4106 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4107 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4108 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4109 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4110 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4111 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4112 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4113 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4114 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4115 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4116 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4117 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4118 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4119 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4120 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4121 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4122 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4123 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4124 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4125 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4126 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4127 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4128 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4129 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4130 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4131 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4132 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4133 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4134 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4135 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4136 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4137 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4138 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4139 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4140 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4141 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4142 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4143 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4144 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4145 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4146 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4147 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4148 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4149 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4150 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4151 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4152 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4153 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4154 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4155 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4156 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4157 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4158 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4159 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4160 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4161 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4162 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4163 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4164 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4165 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4166 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4167 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4168 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4169 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4170 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4171 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4172 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4173 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4174 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4175 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4176 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4177 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4178 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4179 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4180 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4181 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4182 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4183 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4184 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4185 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4186 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4187 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4188 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4189 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4190 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4191 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4192 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4193 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4194 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4195 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4196 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4197 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4198 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4199 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4200 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4201 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4202 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4203 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4204 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4205 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4206 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4207 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4208 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4209 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4210 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4211 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4212 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4213 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4214 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4215 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4216 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4217 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4218 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4219 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4220 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4221 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4222 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4223 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4224 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4225 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4226 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4227 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4228 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4229 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4230 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4231 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4232 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4233 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4234 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4235 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4236 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4237 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4238 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4239 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4240 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4241 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4242 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4243 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4244 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4245 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4246 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4247 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4248 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4249 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4250 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4251 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4252 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4253 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4254 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4255 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4256 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4257 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4258 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4259 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4260 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4261 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4262 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4263 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4264 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4265 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4266 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4267 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4268 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4269 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4270 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4271 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4272 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4273 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4274 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4275 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4276 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4277 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4278 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4279 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4280 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4281 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4282 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4283 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4284 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4285 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4286 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4287 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4288 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4289 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4290 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4291 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4292 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4293 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4294 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4295 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4296 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4297 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4298 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4299 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4300 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4301 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4302 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4303 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4304 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4305 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4306 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4307 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4308 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4309 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4310 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4311 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4312 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4313 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4314 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4315
4316 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4317 {
4318     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4319     BOOL ret;
4320     BYTE *buf = NULL;
4321     DWORD size = 0, i;
4322
4323     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4324     {
4325         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4326          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4327          &buf, &size);
4328         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4329          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4330          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4331          GetLastError());
4332     }
4333     /* at a minimum, a CRL must contain an issuer: */
4334     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4335      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4336      &buf, &size);
4337     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4338     if (buf)
4339     {
4340         CRL_INFO *info = (CRL_INFO *)buf;
4341
4342         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4343         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4344          info->cCRLEntry);
4345         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4346          "Wrong issuer size %d\n", info->Issuer.cbData);
4347         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4348          "Unexpected issuer\n");
4349         LocalFree(buf);
4350     }
4351     /* check decoding with an empty CRL entry */
4352     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4353      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4354      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4355     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4356      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4357      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4358      GetLastError());
4359     /* with a real CRL entry */
4360     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4361      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4362      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4363     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4364     if (buf)
4365     {
4366         CRL_INFO *info = (CRL_INFO *)buf;
4367         CRL_ENTRY *entry;
4368
4369         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4370         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4371          info->cCRLEntry);
4372         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4373         entry = info->rgCRLEntry;
4374         ok(entry->SerialNumber.cbData == 1,
4375          "Expected serial number size 1, got %d\n",
4376          entry->SerialNumber.cbData);
4377         ok(*entry->SerialNumber.pbData == *serialNum,
4378          "Expected serial number %d, got %d\n", *serialNum,
4379          *entry->SerialNumber.pbData);
4380         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4381          "Wrong issuer size %d\n", info->Issuer.cbData);
4382         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4383          "Unexpected issuer\n");
4384         LocalFree(buf);
4385     }
4386     /* a real CRL from verisign that has extensions */
4387     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4388      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4389      NULL, &buf, &size);
4390     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4391     if (buf)
4392     {
4393         CRL_INFO *info = (CRL_INFO *)buf;
4394         CRL_ENTRY *entry;
4395
4396         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4397         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4398          info->cCRLEntry);
4399         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4400         entry = info->rgCRLEntry;
4401         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4402          info->cExtension);
4403         LocalFree(buf);
4404     }
4405     /* another real CRL from verisign that has lots of entries */
4406     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4407      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4408      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4409     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4410     if (buf)
4411     {
4412         CRL_INFO *info = (CRL_INFO *)buf;
4413
4414         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4415         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4416          info->cCRLEntry);
4417         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4418          info->cExtension);
4419         LocalFree(buf);
4420     }
4421     /* and finally, with an extension */
4422     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4423      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4424      NULL, &buf, &size);
4425     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4426     if (buf)
4427     {
4428         CRL_INFO *info = (CRL_INFO *)buf;
4429         CRL_ENTRY *entry;
4430
4431         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4432         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4433          info->cCRLEntry);
4434         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4435         entry = info->rgCRLEntry;
4436         ok(entry->SerialNumber.cbData == 1,
4437          "Expected serial number size 1, got %d\n",
4438          entry->SerialNumber.cbData);
4439         ok(*entry->SerialNumber.pbData == *serialNum,
4440          "Expected serial number %d, got %d\n", *serialNum,
4441          *entry->SerialNumber.pbData);
4442         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4443          "Wrong issuer size %d\n", info->Issuer.cbData);
4444         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4445          "Unexpected issuer\n");
4446         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4447          info->cExtension);
4448         LocalFree(buf);
4449     }
4450     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4451      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4452      NULL, &buf, &size);
4453     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4454     if (buf)
4455     {
4456         CRL_INFO *info = (CRL_INFO *)buf;
4457
4458         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4459          info->cExtension);
4460         LocalFree(buf);
4461     }
4462     /* And again, with an issuing dist point */
4463     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4464      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4465      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4466     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4467     if (buf)
4468     {
4469         CRL_INFO *info = (CRL_INFO *)buf;
4470
4471         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4472          info->cExtension);
4473         LocalFree(buf);
4474     }
4475 }
4476
4477 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4478  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4479 static const BYTE encodedUsage[] = {
4480  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4481  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4482  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4483
4484 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4485 {
4486     BOOL ret;
4487     BYTE *buf = NULL;
4488     DWORD size = 0;
4489     CERT_ENHKEY_USAGE usage;
4490
4491     /* Test with empty usage */
4492     usage.cUsageIdentifier = 0;
4493     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4494      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4495     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4496     if (buf)
4497     {
4498         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4499         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4500         LocalFree(buf);
4501     }
4502     /* Test with a few usages */
4503     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4504     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4505     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4506      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4507     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4508     if (buf)
4509     {
4510         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4511         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4512         LocalFree(buf);
4513     }
4514 }
4515
4516 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4517 {
4518     BOOL ret;
4519     LPBYTE buf = NULL;
4520     DWORD size = 0;
4521
4522     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4523      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4524      &buf, &size);
4525     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4526     if (buf)
4527     {
4528         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4529
4530         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4531          "Wrong size %d\n", size);
4532         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4533          usage->cUsageIdentifier);
4534         LocalFree(buf);
4535     }
4536     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4537      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4538      &buf, &size);
4539     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4540     if (buf)
4541     {
4542         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4543         DWORD i;
4544
4545         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4546          "Wrong size %d\n", size);
4547         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4548          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4549         for (i = 0; i < usage->cUsageIdentifier; i++)
4550             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4551              "Expected OID %s, got %s\n", keyUsages[i],
4552              usage->rgpszUsageIdentifier[i]);
4553         LocalFree(buf);
4554     }
4555 }
4556
4557 static BYTE keyId[] = { 1,2,3,4 };
4558 static const BYTE authorityKeyIdWithId[] = {
4559  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4560 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4561  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4562  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4563 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4564
4565 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4566 {
4567     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4568     BOOL ret;
4569     BYTE *buf = NULL;
4570     DWORD size = 0;
4571
4572     /* Test with empty id */
4573     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4574      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4575     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4576     if (buf)
4577     {
4578         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4579         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4580         LocalFree(buf);
4581     }
4582     /* With just a key id */
4583     info.KeyId.cbData = sizeof(keyId);
4584     info.KeyId.pbData = keyId;
4585     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4586      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4587     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4588     if (buf)
4589     {
4590         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4591         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4592         LocalFree(buf);
4593     }
4594     /* With just an issuer */
4595     info.KeyId.cbData = 0;
4596     info.CertIssuer.cbData = sizeof(encodedCommonName);
4597     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4598     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4599      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4600     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4601     if (buf)
4602     {
4603         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4604          size);
4605         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4606         LocalFree(buf);
4607     }
4608     /* With just a serial number */
4609     info.CertIssuer.cbData = 0;
4610     info.CertSerialNumber.cbData = sizeof(serialNum);
4611     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4612     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4613      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4614     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4615     if (buf)
4616     {
4617         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4618          size);
4619         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4620         LocalFree(buf);
4621     }
4622 }
4623
4624 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4625 {
4626     BOOL ret;
4627     LPBYTE buf = NULL;
4628     DWORD size = 0;
4629
4630     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4631      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4632      &buf, &size);
4633     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4634     if (buf)
4635     {
4636         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4637
4638         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4639          size);
4640         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4641         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4642         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4643         LocalFree(buf);
4644     }
4645     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4646      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4647      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4648     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4649     if (buf)
4650     {
4651         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4652
4653         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4654          size);
4655         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4656         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4657          "Unexpected key id\n");
4658         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4659         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4660         LocalFree(buf);
4661     }
4662     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4663      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4664      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4665     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4666     if (buf)
4667     {
4668         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4669
4670         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4671          size);
4672         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4673         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4674          "Unexpected issuer len\n");
4675         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4676          sizeof(encodedCommonName)), "Unexpected issuer\n");
4677         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4678         LocalFree(buf);
4679     }
4680     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4681      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4682      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4683     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4684     if (buf)
4685     {
4686         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4687
4688         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4689          size);
4690         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4691         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4692         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4693          "Unexpected serial number len\n");
4694         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4695          "Unexpected serial number\n");
4696         LocalFree(buf);
4697     }
4698 }
4699
4700 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4701  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4702  0x6f,0x72,0x67 };
4703
4704 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4705 {
4706     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4707     CERT_ALT_NAME_ENTRY entry = { 0 };
4708     BOOL ret;
4709     BYTE *buf = NULL;
4710     DWORD size = 0;
4711
4712     /* Test with empty id */
4713     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4714      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4715     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4716     if (buf)
4717     {
4718         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4719         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4720         LocalFree(buf);
4721     }
4722     /* With just a key id */
4723     info.KeyId.cbData = sizeof(keyId);
4724     info.KeyId.pbData = keyId;
4725     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4726      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4727     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4728     if (buf)
4729     {
4730         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4731          size);
4732         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4733         LocalFree(buf);
4734     }
4735     /* With a bogus issuer name */
4736     info.KeyId.cbData = 0;
4737     info.AuthorityCertIssuer.cAltEntry = 1;
4738     info.AuthorityCertIssuer.rgAltEntry = &entry;
4739     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4740      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4741     ok(!ret && GetLastError() == E_INVALIDARG,
4742      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4743     /* With an issuer name */
4744     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4745     U(entry).pwszURL = (LPWSTR)url;
4746     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4747      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4748     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4749     if (buf)
4750     {
4751         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4752          size);
4753         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4754          "Unexpected value\n");
4755         LocalFree(buf);
4756     }
4757     /* With just a serial number */
4758     info.AuthorityCertIssuer.cAltEntry = 0;
4759     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4760     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4761     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4762      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4763     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4764     if (buf)
4765     {
4766         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4767          size);
4768         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4769         LocalFree(buf);
4770     }
4771 }
4772
4773 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4774 {
4775     BOOL ret;
4776     LPBYTE buf = NULL;
4777     DWORD size = 0;
4778
4779     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4780      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4781      &buf, &size);
4782     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4783     if (buf)
4784     {
4785         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4786
4787         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4788          size);
4789         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4790         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4791          "Expected no issuer name entries\n");
4792         ok(info->AuthorityCertSerialNumber.cbData == 0,
4793          "Expected no serial number\n");
4794         LocalFree(buf);
4795     }
4796     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4797      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4798      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4799     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4800     if (buf)
4801     {
4802         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4803
4804         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4805          size);
4806         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4807         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4808          "Unexpected key id\n");
4809         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4810          "Expected no issuer name entries\n");
4811         ok(info->AuthorityCertSerialNumber.cbData == 0,
4812          "Expected no serial number\n");
4813         LocalFree(buf);
4814     }
4815     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4816      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4817      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4818     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4819     if (buf)
4820     {
4821         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4822
4823         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4824          size);
4825         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4826         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4827          "Expected 1 issuer entry, got %d\n",
4828          info->AuthorityCertIssuer.cAltEntry);
4829         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4830          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4831          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4832         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4833          url), "Unexpected URL\n");
4834         ok(info->AuthorityCertSerialNumber.cbData == 0,
4835          "Expected no serial number\n");
4836         LocalFree(buf);
4837     }
4838     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4839      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4840      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4841     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4842     if (buf)
4843     {
4844         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4845
4846         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4847          size);
4848         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4849         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4850          "Expected no issuer name entries\n");
4851         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4852          "Unexpected serial number len\n");
4853         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4854          sizeof(serialNum)), "Unexpected serial number\n");
4855         LocalFree(buf);
4856     }
4857 }
4858
4859 static const BYTE authorityInfoAccessWithUrl[] = {
4860 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4861 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4862 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4863 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4864 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4865 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4866
4867 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4868 {
4869     static char oid1[] = "1.2.3";
4870     static char oid2[] = "1.5.6";
4871     BOOL ret;
4872     BYTE *buf = NULL;
4873     DWORD size = 0;
4874     CERT_ACCESS_DESCRIPTION accessDescription[2];
4875     CERT_AUTHORITY_INFO_ACCESS aia;
4876
4877     memset(accessDescription, 0, sizeof(accessDescription));
4878     aia.cAccDescr = 0;
4879     aia.rgAccDescr = NULL;
4880     /* Having no access descriptions is allowed */
4881     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4882      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4883     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4884     if (buf)
4885     {
4886         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4887         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4888         LocalFree(buf);
4889         buf = NULL;
4890     }
4891     /* It can't have an empty access method */
4892     aia.cAccDescr = 1;
4893     aia.rgAccDescr = accessDescription;
4894     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4895      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4896     ok(!ret && (GetLastError() == E_INVALIDARG ||
4897      GetLastError() == OSS_LIMITED /* Win9x */),
4898      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
4899     /* It can't have an empty location */
4900     accessDescription[0].pszAccessMethod = oid1;
4901     SetLastError(0xdeadbeef);
4902     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4903      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4904     ok(!ret && GetLastError() == E_INVALIDARG,
4905      "expected E_INVALIDARG, got %08x\n", GetLastError());
4906     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4907     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4908     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4909      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4910     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4911     if (buf)
4912     {
4913         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4914          size);
4915         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4916          "unexpected value\n");
4917         LocalFree(buf);
4918         buf = NULL;
4919     }
4920     accessDescription[1].pszAccessMethod = oid2;
4921     accessDescription[1].AccessLocation.dwAltNameChoice =
4922      CERT_ALT_NAME_IP_ADDRESS;
4923     U(accessDescription[1].AccessLocation).IPAddress.cbData =
4924      sizeof(encodedIPAddr);
4925     U(accessDescription[1].AccessLocation).IPAddress.pbData =
4926      (LPBYTE)encodedIPAddr;
4927     aia.cAccDescr = 2;
4928     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4929      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4930     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4931     if (buf)
4932     {
4933         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4934          "unexpected size %d\n", size);
4935         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4936          "unexpected value\n");
4937         LocalFree(buf);
4938         buf = NULL;
4939     }
4940 }
4941
4942 static void compareAuthorityInfoAccess(LPCSTR header,
4943  const CERT_AUTHORITY_INFO_ACCESS *expected,
4944  const CERT_AUTHORITY_INFO_ACCESS *got)
4945 {
4946     DWORD i;
4947
4948     ok(expected->cAccDescr == got->cAccDescr,
4949      "%s: expected %d access descriptions, got %d\n", header,
4950      expected->cAccDescr, got->cAccDescr);
4951     for (i = 0; i < expected->cAccDescr; i++)
4952     {
4953         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4954          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4955          header, i, expected->rgAccDescr[i].pszAccessMethod,
4956          got->rgAccDescr[i].pszAccessMethod);
4957         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4958          &got->rgAccDescr[i].AccessLocation);
4959     }
4960 }
4961
4962 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4963 {
4964     static char oid1[] = "1.2.3";
4965     static char oid2[] = "1.5.6";
4966     BOOL ret;
4967     LPBYTE buf = NULL;
4968     DWORD size = 0;
4969
4970     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4971      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4972      &buf, &size);
4973     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4974     if (buf)
4975     {
4976         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4977
4978         compareAuthorityInfoAccess("empty AIA", &aia,
4979          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4980         LocalFree(buf);
4981         buf = NULL;
4982     }
4983     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4984      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4985      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4986     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4987     if (buf)
4988     {
4989         CERT_ACCESS_DESCRIPTION accessDescription;
4990         CERT_AUTHORITY_INFO_ACCESS aia;
4991
4992         accessDescription.pszAccessMethod = oid1;
4993         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4994         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
4995         aia.cAccDescr = 1;
4996         aia.rgAccDescr = &accessDescription;
4997         compareAuthorityInfoAccess("AIA with URL", &aia,
4998          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4999         LocalFree(buf);
5000         buf = NULL;
5001     }
5002     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5003      authorityInfoAccessWithUrlAndIPAddr,
5004      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5005      NULL, &buf, &size);
5006     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5007     if (buf)
5008     {
5009         CERT_ACCESS_DESCRIPTION accessDescription[2];
5010         CERT_AUTHORITY_INFO_ACCESS aia;
5011
5012         accessDescription[0].pszAccessMethod = oid1;
5013         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5014         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5015         accessDescription[1].pszAccessMethod = oid2;
5016         accessDescription[1].AccessLocation.dwAltNameChoice =
5017          CERT_ALT_NAME_IP_ADDRESS;
5018         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5019          sizeof(encodedIPAddr);
5020         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5021          (LPBYTE)encodedIPAddr;
5022         aia.cAccDescr = 2;
5023         aia.rgAccDescr = accessDescription;
5024         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5025          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5026         LocalFree(buf);
5027         buf = NULL;
5028     }
5029 }
5030
5031 static const BYTE emptyCTL[] = {
5032 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5033 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5034 static const BYTE emptyCTLWithVersion1[] = {
5035 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5036 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5037 static const BYTE ctlWithUsageIdentifier[] = {
5038 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5039 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5040 static const BYTE ctlWithListIdentifier[] = {
5041 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5042 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5043 static const BYTE ctlWithSequenceNumber[] = {
5044 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5045 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5046 static const BYTE ctlWithThisUpdate[] = {
5047 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5048 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5049 static const BYTE ctlWithThisAndNextUpdate[] = {
5050 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5051 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5052 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5053 static const BYTE ctlWithAlgId[] = {
5054 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5055 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5056 static const BYTE ctlWithBogusEntry[] = {
5057 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5058 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5059 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5060 static const BYTE ctlWithOneEntry[] = {
5061 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5062 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5063 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5064 static const BYTE ctlWithTwoEntries[] = {
5065 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5066 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5067 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5068 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5069 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5070
5071 static void test_encodeCTL(DWORD dwEncoding)
5072 {
5073     static char oid1[] = "1.2.3";
5074     static char oid2[] = "1.5.6";
5075     char *pOid1 = oid1;
5076     BOOL ret;
5077     BYTE *buf = NULL;
5078     DWORD size = 0;
5079     CTL_INFO info;
5080     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5081     CTL_ENTRY ctlEntry[2];
5082     CRYPT_ATTRIBUTE attr1, attr2;
5083     CRYPT_ATTR_BLOB value1, value2;
5084
5085     memset(&info, 0, sizeof(info));
5086     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5087      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5088     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5089     if (buf)
5090     {
5091         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5092         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5093         LocalFree(buf);
5094         buf = NULL;
5095     }
5096     info.dwVersion = 1;
5097     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5098      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5099     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5100     if (buf)
5101     {
5102         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5103         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5104         LocalFree(buf);
5105         buf = NULL;
5106     }
5107     info.dwVersion = 0;
5108     info.SubjectUsage.cUsageIdentifier = 1;
5109     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5110     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5111      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5112     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5113     if (buf)
5114     {
5115         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5116          size);
5117         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5118         LocalFree(buf);
5119         buf = NULL;
5120     }
5121     info.SubjectUsage.cUsageIdentifier = 0;
5122     info.ListIdentifier.cbData = sizeof(serialNum);
5123     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5124     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5125      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5126     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5127     if (buf)
5128     {
5129         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5130         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5131         LocalFree(buf);
5132         buf = NULL;
5133     }
5134     info.ListIdentifier.cbData = 0;
5135     info.SequenceNumber.cbData = sizeof(serialNum);
5136     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5137     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5138      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5139     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5140     if (buf)
5141     {
5142         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5143          size);
5144         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5145         LocalFree(buf);
5146         buf = NULL;
5147     }
5148     info.SequenceNumber.cbData = 0;
5149     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5150     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5151      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5152     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5153     if (buf)
5154     {
5155         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5156         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5157         LocalFree(buf);
5158         buf = NULL;
5159     }
5160     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5161     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5162      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5163     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5164     if (buf)
5165     {
5166         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5167          size);
5168         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5169         LocalFree(buf);
5170         buf = NULL;
5171     }
5172     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5173     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5174     info.SubjectAlgorithm.pszObjId = oid2;
5175     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5176      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5177     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5178     if (buf)
5179     {
5180         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5181         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5182         LocalFree(buf);
5183         buf = NULL;
5184     }
5185     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5186      * (see tests below) but it'll encode fine.
5187      */
5188     info.SubjectAlgorithm.pszObjId = NULL;
5189     value1.cbData = sizeof(serialNum);
5190     value1.pbData = (LPBYTE)serialNum;
5191     attr1.pszObjId = oid1;
5192     attr1.cValue = 1;
5193     attr1.rgValue = &value1;
5194     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5195     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5196     ctlEntry[0].cAttribute = 1;
5197     ctlEntry[0].rgAttribute = &attr1;
5198     info.cCTLEntry = 1;
5199     info.rgCTLEntry = ctlEntry;
5200     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5201      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5202     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5203     if (buf)
5204     {
5205         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5206         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5207         LocalFree(buf);
5208         buf = NULL;
5209     }
5210     value1.cbData = sizeof(emptySequence);
5211     value1.pbData = (LPBYTE)emptySequence;
5212     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5213      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5214     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5215     if (buf)
5216     {
5217         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5218         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5219         LocalFree(buf);
5220         buf = NULL;
5221     }
5222     value2.cbData = sizeof(encodedIPAddr);
5223     value2.pbData = (LPBYTE)encodedIPAddr;
5224     attr2.pszObjId = oid2;
5225     attr2.cValue = 1;
5226     attr2.rgValue = &value2;
5227     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5228     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5229     ctlEntry[1].cAttribute = 1;
5230     ctlEntry[1].rgAttribute = &attr2;
5231     info.cCTLEntry = 2;
5232     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5233      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5234     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5235     if (buf)
5236     {
5237         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5238         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5239         LocalFree(buf);
5240         buf = NULL;
5241     }
5242 }
5243
5244 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5245  const CTL_INFO *got)
5246 {
5247     DWORD i, j, k;
5248
5249     ok(expected->dwVersion == got->dwVersion,
5250      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5251      got->dwVersion);
5252     ok(expected->SubjectUsage.cUsageIdentifier ==
5253      got->SubjectUsage.cUsageIdentifier,
5254      "%s: expected %d usage identifiers, got %d\n", header,
5255      expected->SubjectUsage.cUsageIdentifier,
5256      got->SubjectUsage.cUsageIdentifier);
5257     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5258         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5259          got->SubjectUsage.rgpszUsageIdentifier[i]),
5260          "%s[%d]: expected %s, got %s\n", header, i,
5261          expected->SubjectUsage.rgpszUsageIdentifier[i],
5262          got->SubjectUsage.rgpszUsageIdentifier[i]);
5263     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5264      "%s: expected list identifier of %d bytes, got %d\n", header,
5265      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5266     if (expected->ListIdentifier.cbData)
5267         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5268          expected->ListIdentifier.cbData),
5269          "%s: unexpected list identifier value\n", header);
5270     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5271      "%s: expected sequence number of %d bytes, got %d\n", header,
5272      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5273     if (expected->SequenceNumber.cbData)
5274         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5275          expected->SequenceNumber.cbData),
5276          "%s: unexpected sequence number value\n", header);
5277     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5278      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5279      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5280      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5281     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5282      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5283      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5284      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5285     if (expected->SubjectAlgorithm.pszObjId &&
5286      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5287         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5288          expected->SubjectAlgorithm.pszObjId);
5289     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5290         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5291          got->SubjectAlgorithm.pszObjId),
5292          "%s: expected subject algorithm %s, got %s\n", header,
5293          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5294     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5295      got->SubjectAlgorithm.Parameters.cbData,
5296      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5297      expected->SubjectAlgorithm.Parameters.cbData,
5298      got->SubjectAlgorithm.Parameters.cbData);
5299     if (expected->SubjectAlgorithm.Parameters.cbData)
5300         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5301          got->SubjectAlgorithm.Parameters.pbData,
5302          expected->SubjectAlgorithm.Parameters.cbData),
5303          "%s: unexpected subject algorithm parameter value\n", header);
5304     ok(expected->cCTLEntry == got->cCTLEntry,
5305      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5306      got->cCTLEntry);
5307     for (i = 0; i < expected->cCTLEntry; i++)
5308     {
5309         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5310          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5311          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5312          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5313          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5314         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5315             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5316              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5317              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5318              "%s[%d]: unexpected subject identifier value\n",
5319              header, i);
5320         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5321         {
5322             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5323              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5324              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5325              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5326              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5327             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5328             {
5329                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5330                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5331                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5332                  header, i, j, k,
5333                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5334                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5335                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5336                     ok(!memcmp(
5337                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5338                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5339                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5340                      "%s[%d][%d][%d]: unexpected value\n",
5341                      header, i, j, k);
5342             }
5343         }
5344     }
5345     ok(expected->cExtension == got->cExtension,
5346      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5347      got->cExtension);
5348     for (i = 0; i < expected->cExtension; i++)
5349     {
5350         ok(!strcmp(expected->rgExtension[i].pszObjId,
5351          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5352          header, i, expected->rgExtension[i].pszObjId,
5353          got->rgExtension[i].pszObjId);
5354         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5355          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5356          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5357         ok(expected->rgExtension[i].Value.cbData ==
5358          got->rgExtension[i].Value.cbData,
5359          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5360          header, i, expected->rgExtension[i].Value.cbData,
5361          got->rgExtension[i].Value.cbData);
5362         if (expected->rgExtension[i].Value.cbData)
5363             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5364              got->rgExtension[i].Value.pbData,
5365              expected->rgExtension[i].Value.cbData),
5366              "%s[%d]: unexpected extension value\n", header, i);
5367     }
5368 }
5369
5370 static const BYTE signedCTL[] = {
5371 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5372 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5373 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5374 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5375 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5376 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5377 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5378 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5379 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5380 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5381 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5382 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5383 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5384 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5385 static const BYTE signedCTLWithCTLInnerContent[] = {
5386 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5387 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5388 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5389 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5390 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5391 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5392 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5393 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5394 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5395 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5396 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5397 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5398 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5399 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5400 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5401 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5402 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5403 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5404 0x57,0x6c,0x0b,0x47,0xb8 };
5405
5406 static void test_decodeCTL(DWORD dwEncoding)
5407 {
5408     static char oid1[] = "1.2.3";
5409     static char oid2[] = "1.5.6";
5410     static BYTE nullData[] = { 5,0 };
5411     char *pOid1 = oid1;
5412     BOOL ret;
5413     BYTE *buf = NULL;
5414     DWORD size = 0;
5415     CTL_INFO info;
5416     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5417     CTL_ENTRY ctlEntry[2];
5418     CRYPT_ATTRIBUTE attr1, attr2;
5419     CRYPT_ATTR_BLOB value1, value2;
5420
5421     memset(&info, 0, sizeof(info));
5422     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5423      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5424     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5425     if (buf)
5426     {
5427         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5428         LocalFree(buf);
5429         buf = NULL;
5430     }
5431     info.dwVersion = 1;
5432     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5433      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5434      &size);
5435     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5436     if (buf)
5437     {
5438         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5439         LocalFree(buf);
5440         buf = NULL;
5441     }
5442     info.dwVersion = 0;
5443     info.SubjectUsage.cUsageIdentifier = 1;
5444     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5445     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5446      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5447      &buf, &size);
5448     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5449     if (buf)
5450     {
5451         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5452         LocalFree(buf);
5453         buf = NULL;
5454     }
5455     info.SubjectUsage.cUsageIdentifier = 0;
5456     info.ListIdentifier.cbData = sizeof(serialNum);
5457     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5458     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5459      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5460     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5461     if (buf)
5462     {
5463         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5464         LocalFree(buf);
5465         buf = NULL;
5466     }
5467     info.ListIdentifier.cbData = 0;
5468     info.SequenceNumber.cbData = sizeof(serialNum);
5469     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5470     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5471      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5472     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5473     if (buf)
5474     {
5475         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5476         LocalFree(buf);
5477         buf = NULL;
5478     }
5479     info.SequenceNumber.cbData = 0;
5480     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5481     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5482      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5483     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5484     if (buf)
5485     {
5486         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5487         LocalFree(buf);
5488         buf = NULL;
5489     }
5490     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5491     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5492      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5493      &buf, &size);
5494     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5495     if (buf)
5496     {
5497         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5498         LocalFree(buf);
5499         buf = NULL;
5500     }
5501     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5502     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5503     info.SubjectAlgorithm.pszObjId = oid2;
5504     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5505     info.SubjectAlgorithm.Parameters.pbData = nullData;
5506     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5507      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5508     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5509     if (buf)
5510     {
5511         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5512         LocalFree(buf);
5513         buf = NULL;
5514     }
5515     SetLastError(0xdeadbeef);
5516     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5517      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5518     ok(!ret &&
5519      (GetLastError() == CRYPT_E_ASN1_EOD ||
5520       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5521       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5522      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5523      GetLastError());
5524     info.SubjectAlgorithm.Parameters.cbData = 0;
5525     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5526     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5527     info.SubjectAlgorithm.pszObjId = oid2;
5528     info.SubjectAlgorithm.pszObjId = NULL;
5529     value1.cbData = sizeof(emptySequence);
5530     value1.pbData = (LPBYTE)emptySequence;
5531     attr1.pszObjId = oid1;
5532     attr1.cValue = 1;
5533     attr1.rgValue = &value1;
5534     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5535     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5536     ctlEntry[0].cAttribute = 1;
5537     ctlEntry[0].rgAttribute = &attr1;
5538     info.cCTLEntry = 1;
5539     info.rgCTLEntry = ctlEntry;
5540     SetLastError(0xdeadbeef);
5541     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5542      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5543     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5544     if (buf)
5545     {
5546         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5547         LocalFree(buf);
5548         buf = NULL;
5549     }
5550     value2.cbData = sizeof(encodedIPAddr);
5551     value2.pbData = (LPBYTE)encodedIPAddr;
5552     attr2.pszObjId = oid2;
5553     attr2.cValue = 1;
5554     attr2.rgValue = &value2;
5555     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5556     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5557     ctlEntry[1].cAttribute = 1;
5558     ctlEntry[1].rgAttribute = &attr2;
5559     info.cCTLEntry = 2;
5560     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5561      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5562     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5563     if (buf)
5564     {
5565         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5566         LocalFree(buf);
5567         buf = NULL;
5568     }
5569     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5570     SetLastError(0xdeadbeef);
5571     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5572      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5573     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5574      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5575      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5576      GetLastError());
5577     SetLastError(0xdeadbeef);
5578     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5579      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5580      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5581     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5582      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5583      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5584      GetLastError());
5585 }
5586
5587 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5588 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5589  0x03,0,0,0,0,0,0 };
5590 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5591  0xa0,0x01,0x01 };
5592 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5593  0x03,0x02,0x01,0x01 };
5594 static BYTE bogusDER[] = { 1 };
5595
5596 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5597 {
5598     BOOL ret;
5599     BYTE *buf = NULL;
5600     DWORD size = 0;
5601     CRYPT_CONTENT_INFO info = { 0 };
5602     char oid1[] = "1.2.3";
5603
5604     if (0)
5605     {
5606         /* Crashes on win9x */
5607         SetLastError(0xdeadbeef);
5608         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5609          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5610         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5611          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5612     }
5613     SetLastError(0xdeadbeef);
5614     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5615      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5616     ok(!ret && (GetLastError() == E_INVALIDARG ||
5617      GetLastError() == OSS_LIMITED /* Win9x */),
5618      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5619     info.pszObjId = oid1;
5620     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5621      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5622     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5623     if (buf)
5624     {
5625         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5626         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5627         LocalFree(buf);
5628     }
5629     info.Content.pbData = bogusDER;
5630     info.Content.cbData = sizeof(bogusDER);
5631     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5632      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5633     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5634     if (buf)
5635     {
5636         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5637         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5638         LocalFree(buf);
5639     }
5640     info.Content.pbData = (BYTE *)ints[0].encoded;
5641     info.Content.cbData = ints[0].encoded[1] + 2;
5642     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5643      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5644     if (buf)
5645     {
5646         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5647         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5648         LocalFree(buf);
5649     }
5650 }
5651
5652 static const BYTE indefiniteSignedPKCSContent[] = {
5653 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5654 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5655 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5656 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5657 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5658 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5659 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5660 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5661 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5662 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5663 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5664 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5665 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5666 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5667 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5668 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5669 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5670 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5671 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5672 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5673 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5674 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5675 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5676 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5677 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5678 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5679 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5680 0x00,0x00,0x00,0x00,0x00,0x00 };
5681
5682 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5683 {
5684     BOOL ret;
5685     LPBYTE buf = NULL;
5686     DWORD size = 0;
5687     CRYPT_CONTENT_INFO *info;
5688
5689     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5690      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5691      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5692     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5693     if (buf)
5694     {
5695         info = (CRYPT_CONTENT_INFO *)buf;
5696
5697         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5698          info->pszObjId);
5699         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5700          info->Content.cbData);
5701         LocalFree(buf);
5702     }
5703     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5704      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5705      0, NULL, NULL, &size);
5706     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5707     SetLastError(0xdeadbeef);
5708     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5709      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5710      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5711     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5712      * I doubt an app depends on that.
5713      */
5714     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5715      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5716      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5717      GetLastError());
5718     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5719      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5720      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5721     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5722     if (buf)
5723     {
5724         info = (CRYPT_CONTENT_INFO *)buf;
5725
5726         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5727          info->pszObjId);
5728         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5729          "Unexpected size %d\n", info->Content.cbData);
5730         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5731          info->Content.cbData), "Unexpected value\n");
5732         LocalFree(buf);
5733     }
5734     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5735      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5736      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5737     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5738     if (buf)
5739     {
5740         info = (CRYPT_CONTENT_INFO *)buf;
5741
5742         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5743          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5744         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5745          info->Content.cbData);
5746         LocalFree(buf);
5747     }
5748 }
5749
5750 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5751  0x00 };
5752 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5753  0x01 };
5754 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5755  0x02,0x01,0x01 };
5756
5757 static void test_encodePKCSAttribute(DWORD dwEncoding)
5758 {
5759     CRYPT_ATTRIBUTE attr = { 0 };
5760     BOOL ret;
5761     LPBYTE buf = NULL;
5762     DWORD size = 0;
5763     CRYPT_ATTR_BLOB blob;
5764     char oid[] = "1.2.3";
5765
5766     if (0)
5767     {
5768         /* Crashes on win9x */
5769         SetLastError(0xdeadbeef);
5770         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5771          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5772         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5773          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5774     }
5775     SetLastError(0xdeadbeef);
5776     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5777      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5778     ok(!ret && (GetLastError() == E_INVALIDARG ||
5779      GetLastError() == OSS_LIMITED /* Win9x */),
5780      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5781     attr.pszObjId = oid;
5782     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5783      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5784     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5785     if (buf)
5786     {
5787         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5788         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5789         LocalFree(buf);
5790     }
5791     blob.cbData = sizeof(bogusDER);
5792     blob.pbData = bogusDER;
5793     attr.cValue = 1;
5794     attr.rgValue = &blob;
5795     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5796      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5797     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5798     if (buf)
5799     {
5800         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5801         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5802         LocalFree(buf);
5803     }
5804     blob.pbData = (BYTE *)ints[0].encoded;
5805     blob.cbData = ints[0].encoded[1] + 2;
5806     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5807      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5808     if (buf)
5809     {
5810         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5811         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5812         LocalFree(buf);
5813     }
5814 }
5815
5816 static void test_decodePKCSAttribute(DWORD dwEncoding)
5817 {
5818     BOOL ret;
5819     LPBYTE buf = NULL;
5820     DWORD size = 0;
5821     CRYPT_ATTRIBUTE *attr;
5822
5823     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5824      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5825      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5826     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5827     if (buf)
5828     {
5829         attr = (CRYPT_ATTRIBUTE *)buf;
5830
5831         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5832          attr->pszObjId);
5833         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5834         LocalFree(buf);
5835     }
5836     SetLastError(0xdeadbeef);
5837     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5838      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5839      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5840     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5841      * I doubt an app depends on that.
5842      */
5843     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5844      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5845      GetLastError() == OSS_MORE_INPUT /* Win9x */),
5846      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
5847      GetLastError());
5848     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5849      intPKCSAttr, sizeof(intPKCSAttr),
5850      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5851     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5852     if (buf)
5853     {
5854         attr = (CRYPT_ATTRIBUTE *)buf;
5855
5856         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5857          attr->pszObjId);
5858         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5859         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5860          "Unexpected size %d\n", attr->rgValue[0].cbData);
5861         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5862          attr->rgValue[0].cbData), "Unexpected value\n");
5863         LocalFree(buf);
5864     }
5865 }
5866
5867 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5868 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5869  0x2a,0x03,0x31,0x00 };
5870 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5871  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5872
5873 static void test_encodePKCSAttributes(DWORD dwEncoding)
5874 {
5875     CRYPT_ATTRIBUTES attributes = { 0 };
5876     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5877     CRYPT_ATTR_BLOB blob;
5878     BOOL ret;
5879     LPBYTE buf = NULL;
5880     DWORD size = 0;
5881     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5882
5883     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5884      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5885     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5886     if (buf)
5887     {
5888         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5889         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5890         LocalFree(buf);
5891     }
5892     attributes.cAttr = 1;
5893     attributes.rgAttr = attr;
5894     SetLastError(0xdeadbeef);
5895     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5896      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5897     ok(!ret && (GetLastError() == E_INVALIDARG ||
5898      GetLastError() == OSS_LIMITED /* Win9x */),
5899      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5900     attr[0].pszObjId = oid1;
5901     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5902      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5903     if (buf)
5904     {
5905         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5906         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5907         LocalFree(buf);
5908     }
5909     attr[1].pszObjId = oid2;
5910     attr[1].cValue = 1;
5911     attr[1].rgValue = &blob;
5912     blob.pbData = (BYTE *)ints[0].encoded;
5913     blob.cbData = ints[0].encoded[1] + 2;
5914     attributes.cAttr = 2;
5915     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5916      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5917     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5918     if (buf)
5919     {
5920         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5921         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5922         LocalFree(buf);
5923     }
5924 }
5925
5926 static void test_decodePKCSAttributes(DWORD dwEncoding)
5927 {
5928     BOOL ret;
5929     LPBYTE buf = NULL;
5930     DWORD size = 0;
5931     CRYPT_ATTRIBUTES *attributes;
5932
5933     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5934      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5935      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5936     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5937     if (buf)
5938     {
5939         attributes = (CRYPT_ATTRIBUTES *)buf;
5940         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5941          attributes->cAttr);
5942         LocalFree(buf);
5943     }
5944     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5945      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5946      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5947     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5948     if (buf)
5949     {
5950         attributes = (CRYPT_ATTRIBUTES *)buf;
5951         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5952          attributes->cAttr);
5953         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5954          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5955         ok(attributes->rgAttr[0].cValue == 0,
5956          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5957         LocalFree(buf);
5958     }
5959     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5960      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5961      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5962     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5963     if (buf)
5964     {
5965         attributes = (CRYPT_ATTRIBUTES *)buf;
5966         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5967          attributes->cAttr);
5968         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5969          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5970         ok(attributes->rgAttr[0].cValue == 0,
5971          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5972         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5973          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5974         ok(attributes->rgAttr[1].cValue == 1,
5975          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5976         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5977          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5978         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5979          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5980         LocalFree(buf);
5981     }
5982 }
5983
5984 static const BYTE singleCapability[] = {
5985 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5986 static const BYTE twoCapabilities[] = {
5987 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5988 static const BYTE singleCapabilitywithNULL[] = {
5989 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5990
5991 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
5992 {
5993     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5994     BOOL ret;
5995     LPBYTE buf = NULL;
5996     DWORD size = 0;
5997     CRYPT_SMIME_CAPABILITY capability[2];
5998     CRYPT_SMIME_CAPABILITIES capabilities;
5999
6000     /* An empty capabilities is allowed */
6001     capabilities.cCapability = 0;
6002     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6003      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6004     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6005     if (buf)
6006     {
6007         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6008         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6009         LocalFree(buf);
6010     }
6011     /* A non-empty capabilities with an empty capability (lacking an OID) is
6012      * not allowed
6013      */
6014     capability[0].pszObjId = NULL;
6015     capability[0].Parameters.cbData = 0;
6016     capabilities.cCapability = 1;
6017     capabilities.rgCapability = capability;
6018     SetLastError(0xdeadbeef);
6019     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6020      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6021     ok(!ret && (GetLastError() == E_INVALIDARG ||
6022      GetLastError() == OSS_LIMITED /* Win9x */),
6023      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6024     capability[0].pszObjId = oid1;
6025     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6026      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6027     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6028     if (buf)
6029     {
6030         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6031         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6032         LocalFree(buf);
6033     }
6034     capability[1].pszObjId = oid2;
6035     capability[1].Parameters.cbData = 0;
6036     capabilities.cCapability = 2;
6037     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6038      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6039     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6040     if (buf)
6041     {
6042         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6043         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6044         LocalFree(buf);
6045     }
6046 }
6047
6048 static void compareSMimeCapabilities(LPCSTR header,
6049  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6050 {
6051     DWORD i;
6052
6053     ok(got->cCapability == expected->cCapability,
6054      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6055      got->cCapability);
6056     for (i = 0; i < expected->cCapability; i++)
6057     {
6058         ok(!strcmp(expected->rgCapability[i].pszObjId,
6059          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6060          header, i, expected->rgCapability[i].pszObjId,
6061          got->rgCapability[i].pszObjId);
6062         ok(expected->rgCapability[i].Parameters.cbData ==
6063          got->rgCapability[i].Parameters.cbData,
6064          "%s[%d]: expected %d bytes, got %d\n", header, i,
6065          expected->rgCapability[i].Parameters.cbData,
6066          got->rgCapability[i].Parameters.cbData);
6067         if (expected->rgCapability[i].Parameters.cbData)
6068             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6069              got->rgCapability[i].Parameters.pbData,
6070              expected->rgCapability[i].Parameters.cbData),
6071              "%s[%d]: unexpected value\n", header, i);
6072     }
6073 }
6074
6075 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6076 {
6077     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6078     BOOL ret;
6079     DWORD size = 0;
6080     CRYPT_SMIME_CAPABILITY capability[2];
6081     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6082
6083     SetLastError(0xdeadbeef);
6084     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6085      emptySequence, sizeof(emptySequence),
6086      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6087     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6088     if (ret)
6089     {
6090         capabilities.cCapability = 0;
6091         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6092         LocalFree(ptr);
6093     }
6094     SetLastError(0xdeadbeef);
6095     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6096      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6097      &ptr, &size);
6098     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6099     if (ret)
6100     {
6101         capability[0].pszObjId = oid1;
6102         capability[0].Parameters.cbData = 0;
6103         capabilities.cCapability = 1;
6104         capabilities.rgCapability = capability;
6105         compareSMimeCapabilities("single capability", &capabilities, ptr);
6106         LocalFree(ptr);
6107     }
6108     SetLastError(0xdeadbeef);
6109     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6110      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6111      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6112     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6113     if (ret)
6114     {
6115         BYTE NULLparam[] = {0x05, 0x00};
6116         capability[0].pszObjId = oid1;
6117         capability[0].Parameters.cbData = 2;
6118         capability[0].Parameters.pbData = NULLparam;
6119         capabilities.cCapability = 1;
6120         capabilities.rgCapability = capability;
6121         compareSMimeCapabilities("single capability with NULL", &capabilities,
6122          ptr);
6123         LocalFree(ptr);
6124     }
6125     SetLastError(0xdeadbeef);
6126     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6127     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6128     &ptr, &size);
6129     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6130     if (ret)
6131     {
6132         capability[0].Parameters.cbData = 0;
6133         capability[1].pszObjId = oid2;
6134         capability[1].Parameters.cbData = 0;
6135         capabilities.cCapability = 2;
6136         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6137         LocalFree(ptr);
6138     }
6139 }
6140
6141 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6142  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6143  0x67 };
6144 static const BYTE minimalPKCSSigner[] = {
6145  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6146  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6147  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6148 static const BYTE PKCSSignerWithSerial[] = {
6149  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6150  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6151  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6152  0x00 };
6153 static const BYTE PKCSSignerWithHashAlgo[] = {
6154  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6155  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6156  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6157  0x00,0x04,0x00 };
6158 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6159  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6160  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6161  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6162  0x06,0x05,0x00,0x04,0x00 };
6163 static const BYTE PKCSSignerWithHash[] = {
6164  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6165  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6166  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6167  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6168  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6169 static const BYTE PKCSSignerWithAuthAttr[] = {
6170 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6171 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6172 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6173 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6174 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6175 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6176 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6177
6178 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6179 {
6180     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6181     BOOL ret;
6182     LPBYTE buf = NULL;
6183     DWORD size = 0;
6184     CMSG_SIGNER_INFO info = { 0 };
6185     char oid_common_name[] = szOID_COMMON_NAME;
6186     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6187      (LPBYTE)encodedCommonName };
6188     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6189
6190     SetLastError(0xdeadbeef);
6191     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6192      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6193     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6194     {
6195         skip("no PKCS7_SIGNER_INFO encode support\n");
6196         return;
6197     }
6198     ok(!ret && (GetLastError() == E_INVALIDARG ||
6199      GetLastError() == OSS_LIMITED /* Win9x */),
6200      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6201     /* To be encoded, a signer must have an issuer at least, and the encoding
6202      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6203      * see decoding tests.)
6204      */
6205     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6206     info.Issuer.pbData = encodedCommonNameNoNull;
6207     SetLastError(0xdeadbeef);
6208     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6209      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6210     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6211         ok(!ret && GetLastError() == E_INVALIDARG,
6212          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6213     else
6214     {
6215         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6216          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6217         if (buf)
6218         {
6219             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6220             if (size == sizeof(minimalPKCSSigner))
6221                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6222             else
6223                 ok(0, "Unexpected value\n");
6224             LocalFree(buf);
6225         }
6226     }
6227     info.SerialNumber.cbData = sizeof(serialNum);
6228     info.SerialNumber.pbData = (BYTE *)serialNum;
6229     SetLastError(0xdeadbeef);
6230     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6231      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6232     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6233         ok(!ret && GetLastError() == E_INVALIDARG,
6234          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6235     else
6236     {
6237         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6238          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6239         if (buf)
6240         {
6241             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6242              size);
6243             if (size == sizeof(PKCSSignerWithSerial))
6244                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6245                  "Unexpected value\n");
6246             else
6247                 ok(0, "Unexpected value\n");
6248             LocalFree(buf);
6249         }
6250     }
6251     info.HashAlgorithm.pszObjId = oid1;
6252     SetLastError(0xdeadbeef);
6253     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6254      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6255     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6256         ok(!ret && GetLastError() == E_INVALIDARG,
6257          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6258     else
6259     {
6260         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6261          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6262         if (buf)
6263         {
6264             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6265              size);
6266             if (size == sizeof(PKCSSignerWithHashAlgo))
6267                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6268                  "Unexpected value\n");
6269             else
6270                 ok(0, "Unexpected value\n");
6271             LocalFree(buf);
6272         }
6273     }
6274     info.HashEncryptionAlgorithm.pszObjId = oid2;
6275     SetLastError(0xdeadbeef);
6276     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6277      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6278     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6279         ok(!ret && GetLastError() == E_INVALIDARG,
6280          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6281     else
6282     {
6283         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6284         if (buf)
6285         {
6286             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6287              "Unexpected size %d\n", size);
6288             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6289                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6290                  "Unexpected value\n");
6291             else
6292                 ok(0, "Unexpected value\n");
6293             LocalFree(buf);
6294         }
6295     }
6296     info.EncryptedHash.cbData = sizeof(hash);
6297     info.EncryptedHash.pbData = (BYTE *)hash;
6298     SetLastError(0xdeadbeef);
6299     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6300      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6301     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6302         ok(!ret && GetLastError() == E_INVALIDARG,
6303          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6304     else
6305     {
6306         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6307         if (buf)
6308         {
6309             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6310              size);
6311             if (size == sizeof(PKCSSignerWithHash))
6312                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6313                  "Unexpected value\n");
6314             else
6315                 ok(0, "Unexpected value\n");
6316             LocalFree(buf);
6317         }
6318     }
6319     info.AuthAttrs.cAttr = 1;
6320     info.AuthAttrs.rgAttr = &attr;
6321     SetLastError(0xdeadbeef);
6322     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6323      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6324     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6325         ok(!ret && GetLastError() == E_INVALIDARG,
6326          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6327     else
6328     {
6329         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6330         if (buf)
6331         {
6332             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6333              size);
6334             if (size == sizeof(PKCSSignerWithAuthAttr))
6335                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6336                  "Unexpected value\n");
6337             else
6338                 ok(0, "Unexpected value\n");
6339             LocalFree(buf);
6340         }
6341     }
6342 }
6343
6344 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6345 {
6346     BOOL ret;
6347     LPBYTE buf = NULL;
6348     DWORD size = 0;
6349     CMSG_SIGNER_INFO *info;
6350
6351     /* A PKCS signer can't be decoded without a serial number. */
6352     SetLastError(0xdeadbeef);
6353     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6354      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6355      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6356     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6357      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6358      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6359      GetLastError());
6360     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6361      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6362      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6363     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6364      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6365     if (buf)
6366     {
6367         info = (CMSG_SIGNER_INFO *)buf;
6368         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6369          info->dwVersion);
6370         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6371          "Unexpected size %d\n", info->Issuer.cbData);
6372         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6373          info->Issuer.cbData), "Unexpected value\n");
6374         ok(info->SerialNumber.cbData == sizeof(serialNum),
6375          "Unexpected size %d\n", info->SerialNumber.cbData);
6376         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6377          "Unexpected value\n");
6378         LocalFree(buf);
6379     }
6380     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6381      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6382      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6383     if (buf)
6384     {
6385         info = (CMSG_SIGNER_INFO *)buf;
6386         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6387          info->dwVersion);
6388         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6389          "Unexpected size %d\n", info->Issuer.cbData);
6390         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6391          info->Issuer.cbData), "Unexpected value\n");
6392         ok(info->SerialNumber.cbData == sizeof(serialNum),
6393          "Unexpected size %d\n", info->SerialNumber.cbData);
6394         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6395          "Unexpected value\n");
6396         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6397          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6398         LocalFree(buf);
6399     }
6400     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6401      PKCSSignerWithHashAndEncryptionAlgo,
6402      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6403      NULL, &buf, &size);
6404     if (buf)
6405     {
6406         info = (CMSG_SIGNER_INFO *)buf;
6407         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6408          info->dwVersion);
6409         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6410          "Unexpected size %d\n", info->Issuer.cbData);
6411         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6412          info->Issuer.cbData), "Unexpected value\n");
6413         ok(info->SerialNumber.cbData == sizeof(serialNum),
6414          "Unexpected size %d\n", info->SerialNumber.cbData);
6415         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6416          "Unexpected value\n");
6417         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6418          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6419         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6420          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6421         LocalFree(buf);
6422     }
6423     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6424      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6425      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6426     if (buf)
6427     {
6428         info = (CMSG_SIGNER_INFO *)buf;
6429         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6430          info->dwVersion);
6431         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6432          "Unexpected size %d\n", info->Issuer.cbData);
6433         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6434          info->Issuer.cbData), "Unexpected value\n");
6435         ok(info->SerialNumber.cbData == sizeof(serialNum),
6436          "Unexpected size %d\n", info->SerialNumber.cbData);
6437         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6438          "Unexpected value\n");
6439         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6440          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6441         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6442          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6443         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6444          info->EncryptedHash.cbData);
6445         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6446          "Unexpected value\n");
6447         LocalFree(buf);
6448     }
6449     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6450      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6451      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6452     if (buf)
6453     {
6454         info = (CMSG_SIGNER_INFO *)buf;
6455         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6456          info->AuthAttrs.cAttr);
6457         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6458          "Expected %s, got %s\n", szOID_COMMON_NAME,
6459          info->AuthAttrs.rgAttr[0].pszObjId);
6460         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6461          info->AuthAttrs.rgAttr[0].cValue);
6462         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6463          sizeof(encodedCommonName), "Unexpected size %d\n",
6464          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6465         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6466          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6467         LocalFree(buf);
6468     }
6469 }
6470
6471 static const BYTE CMSSignerWithKeyId[] = {
6472 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6473 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6474
6475 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6476 {
6477     BOOL ret;
6478     LPBYTE buf = NULL;
6479     DWORD size = 0;
6480     CMSG_CMS_SIGNER_INFO info = { 0 };
6481     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6482
6483     SetLastError(0xdeadbeef);
6484     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6485      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6486     ok(!ret, "Expected failure, got %d\n", ret);
6487     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6488     {
6489         skip("no CMS_SIGNER_INFO encode support\n");
6490         return;
6491     }
6492     ok(GetLastError() == E_INVALIDARG,
6493        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6494     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6495     SetLastError(0xdeadbeef);
6496     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6497      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6498     ok(!ret, "Expected failure, got %d\n", ret);
6499     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6500     {
6501         skip("no CMS_SIGNER_INFO encode support\n");
6502         return;
6503     }
6504     ok(GetLastError() == E_INVALIDARG,
6505        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6506     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6507      * be a key id or a issuer serial number with at least the issuer set, and
6508      * the encoding must include PKCS_7_ASN_ENCODING.
6509      * (That isn't enough to be decoded, see decoding tests.)
6510      */
6511     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6512      sizeof(encodedCommonNameNoNull);
6513     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6514     SetLastError(0xdeadbeef);
6515     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6516      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6517     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6518         ok(!ret && GetLastError() == E_INVALIDARG,
6519          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6520     else
6521     {
6522         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6523         if (buf)
6524         {
6525             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6526             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6527             LocalFree(buf);
6528         }
6529     }
6530     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6531     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6532     SetLastError(0xdeadbeef);
6533     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6534      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6535     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6536         ok(!ret && GetLastError() == E_INVALIDARG,
6537          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6538     else
6539     {
6540         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6541         if (buf)
6542         {
6543             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6544              size);
6545             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6546             LocalFree(buf);
6547         }
6548     }
6549     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6550     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6551     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6552     SetLastError(0xdeadbeef);
6553     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6554      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6555     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6556         ok(!ret && GetLastError() == E_INVALIDARG,
6557          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6558     else
6559     {
6560         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6561         if (buf)
6562         {
6563             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6564              size);
6565             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6566             LocalFree(buf);
6567         }
6568     }
6569     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6570      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6571      * (see RFC 3852, section 5.3.)
6572      */
6573     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6574     U(info.SignerId).HashId.cbData = sizeof(hash);
6575     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6576     SetLastError(0xdeadbeef);
6577     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6578      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6579     ok(!ret && GetLastError() == E_INVALIDARG,
6580      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6581     /* Now with a hash algo */
6582     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6583     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6584      sizeof(encodedCommonNameNoNull);
6585     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6586     info.HashAlgorithm.pszObjId = oid1;
6587     SetLastError(0xdeadbeef);
6588     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6589      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6590     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6591         ok(!ret && GetLastError() == E_INVALIDARG,
6592          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6593     else
6594     {
6595         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6596         if (buf)
6597         {
6598             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6599              size);
6600             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6601              "Unexpected value\n");
6602             LocalFree(buf);
6603         }
6604     }
6605     info.HashEncryptionAlgorithm.pszObjId = oid2;
6606     SetLastError(0xdeadbeef);
6607     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6608      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6609     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6610         ok(!ret && GetLastError() == E_INVALIDARG,
6611          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6612     else
6613     {
6614         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6615         if (buf)
6616         {
6617             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6618              "Unexpected size %d\n", size);
6619             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6620              "Unexpected value\n");
6621             LocalFree(buf);
6622         }
6623     }
6624     info.EncryptedHash.cbData = sizeof(hash);
6625     info.EncryptedHash.pbData = (BYTE *)hash;
6626     SetLastError(0xdeadbeef);
6627     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6628      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6629     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6630         ok(!ret && GetLastError() == E_INVALIDARG,
6631          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6632     else
6633     {
6634         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6635         if (buf)
6636         {
6637             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6638              size);
6639             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6640             LocalFree(buf);
6641         }
6642     }
6643 }
6644
6645 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6646 {
6647     BOOL ret;
6648     LPBYTE buf = NULL;
6649     DWORD size = 0;
6650     CMSG_CMS_SIGNER_INFO *info;
6651     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6652
6653     /* A CMS signer can't be decoded without a serial number. */
6654     SetLastError(0xdeadbeef);
6655     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6656      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6657      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6658     ok(!ret, "expected failure\n");
6659     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6660     {
6661         skip("no CMS_SIGNER_INFO decode support\n");
6662         return;
6663     }
6664     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6665      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6666     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6667      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6668      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6669     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6670     if (buf)
6671     {
6672         info = (CMSG_CMS_SIGNER_INFO *)buf;
6673         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6674          info->dwVersion);
6675         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6676          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6677          info->SignerId.dwIdChoice);
6678         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6679          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6680          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6681         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6682          encodedCommonNameNoNull,
6683          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6684          "Unexpected value\n");
6685         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6686          sizeof(serialNum), "Unexpected size %d\n",
6687          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6688         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6689          serialNum, sizeof(serialNum)), "Unexpected value\n");
6690         LocalFree(buf);
6691     }
6692     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6693      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6694      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6695     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6696     if (buf)
6697     {
6698         info = (CMSG_CMS_SIGNER_INFO *)buf;
6699         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6700          info->dwVersion);
6701         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6702          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6703          info->SignerId.dwIdChoice);
6704         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6705          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6706          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6707         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6708          encodedCommonNameNoNull,
6709          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6710          "Unexpected value\n");
6711         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6712          sizeof(serialNum), "Unexpected size %d\n",
6713          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6714         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6715          serialNum, sizeof(serialNum)), "Unexpected value\n");
6716         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6717          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6718         LocalFree(buf);
6719     }
6720     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6721      PKCSSignerWithHashAndEncryptionAlgo,
6722      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6723      NULL, &buf, &size);
6724     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6725     if (buf)
6726     {
6727         info = (CMSG_CMS_SIGNER_INFO *)buf;
6728         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6729          info->dwVersion);
6730         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6731          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6732          info->SignerId.dwIdChoice);
6733         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6734          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6735          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6736         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6737          encodedCommonNameNoNull,
6738          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6739          "Unexpected value\n");
6740         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6741          sizeof(serialNum), "Unexpected size %d\n",
6742          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6743         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6744          serialNum, sizeof(serialNum)), "Unexpected value\n");
6745         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6746          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6747         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6748          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6749         LocalFree(buf);
6750     }
6751     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6752      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6753      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6754     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6755     if (buf)
6756     {
6757         info = (CMSG_CMS_SIGNER_INFO *)buf;
6758         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6759          info->dwVersion);
6760         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6761          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6762          info->SignerId.dwIdChoice);
6763         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6764          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6765          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6766         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6767          encodedCommonNameNoNull,
6768          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6769          "Unexpected value\n");
6770         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6771          sizeof(serialNum), "Unexpected size %d\n",
6772          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6773         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6774          serialNum, sizeof(serialNum)), "Unexpected value\n");
6775         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6776          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6777         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6778          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6779         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6780          info->EncryptedHash.cbData);
6781         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6782          "Unexpected value\n");
6783         LocalFree(buf);
6784     }
6785     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6786      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6787      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6788     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6789     if (buf)
6790     {
6791         info = (CMSG_CMS_SIGNER_INFO *)buf;
6792         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6793          info->dwVersion);
6794         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6795          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6796          info->SignerId.dwIdChoice);
6797         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6798          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6799         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6800          "Unexpected value\n");
6801         LocalFree(buf);
6802     }
6803 }
6804
6805 static BYTE emptyDNSPermittedConstraints[] = {
6806 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6807 static BYTE emptyDNSExcludedConstraints[] = {
6808 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6809 static BYTE DNSExcludedConstraints[] = {
6810 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6811 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6812 static BYTE permittedAndExcludedConstraints[] = {
6813 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6814 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6815 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6816 static BYTE permittedAndExcludedWithMinConstraints[] = {
6817 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6818 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6819 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6820 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6821 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6822 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6823 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6824
6825 static void test_encodeNameConstraints(DWORD dwEncoding)
6826 {
6827     BOOL ret;
6828     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6829     CERT_GENERAL_SUBTREE permitted = { { 0 } };
6830     CERT_GENERAL_SUBTREE excluded = { { 0 } };
6831     LPBYTE buf;
6832     DWORD size;
6833
6834     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6835      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6836     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6837     {
6838         skip("no X509_NAME_CONSTRAINTS encode support\n");
6839         return;
6840     }
6841     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6842     if (ret)
6843     {
6844         ok(size == sizeof(emptySequence), "Unexpected size\n");
6845         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6846         LocalFree(buf);
6847     }
6848     constraints.cPermittedSubtree = 1;
6849     constraints.rgPermittedSubtree = &permitted;
6850     SetLastError(0xdeadbeef);
6851     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6852      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6853     ok(!ret && GetLastError() == E_INVALIDARG,
6854      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6855     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6856     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6857      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6858     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6859     if (ret)
6860     {
6861         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6862         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6863          "Unexpected value\n");
6864         LocalFree(buf);
6865     }
6866     constraints.cPermittedSubtree = 0;
6867     constraints.cExcludedSubtree = 1;
6868     constraints.rgExcludedSubtree = &excluded;
6869     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6870     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6871      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6872     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6873     if (ret)
6874     {
6875         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6876         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6877          "Unexpected value\n");
6878         LocalFree(buf);
6879     }
6880     U(excluded.Base).pwszURL = (LPWSTR)url;
6881     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6882      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6883     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6884     if (ret)
6885     {
6886         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6887         ok(!memcmp(buf, DNSExcludedConstraints, size),
6888          "Unexpected value\n");
6889         LocalFree(buf);
6890     }
6891     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6892     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6893     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6894     constraints.cPermittedSubtree = 1;
6895     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6896      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6897     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6898     if (ret)
6899     {
6900         ok(size == sizeof(permittedAndExcludedConstraints),
6901          "Unexpected size\n");
6902         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6903          "Unexpected value\n");
6904         LocalFree(buf);
6905     }
6906     permitted.dwMinimum = 5;
6907     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6908      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6909     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6910     if (ret)
6911     {
6912         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6913          "Unexpected size\n");
6914         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6915          "Unexpected value\n");
6916         LocalFree(buf);
6917     }
6918     permitted.fMaximum = TRUE;
6919     permitted.dwMaximum = 3;
6920     SetLastError(0xdeadbeef);
6921     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6922      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6923     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6924     if (ret)
6925     {
6926         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6927          "Unexpected size\n");
6928         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6929          "Unexpected value\n");
6930         LocalFree(buf);
6931     }
6932 }
6933
6934 struct EncodedNameConstraints
6935 {
6936     CRYPT_DATA_BLOB            encoded;
6937     CERT_NAME_CONSTRAINTS_INFO constraints;
6938 };
6939
6940 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6941  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6942 static CERT_GENERAL_SUBTREE DNSSubtree = {
6943  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6944 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6945  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6946 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6947  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6948 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6949  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6950
6951 struct EncodedNameConstraints encodedNameConstraints[] = {
6952  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6953  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6954    { 1, &emptyDNSSubtree, 0, NULL } },
6955  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6956    { 0, NULL, 1, &emptyDNSSubtree } },
6957  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6958    { 0, NULL, 1, &DNSSubtree } },
6959  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6960    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6961  { { sizeof(permittedAndExcludedWithMinConstraints),
6962      permittedAndExcludedWithMinConstraints },
6963    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6964  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6965      permittedAndExcludedWithMinMaxConstraints },
6966    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6967 };
6968
6969 static void test_decodeNameConstraints(DWORD dwEncoding)
6970 {
6971     BOOL ret;
6972     DWORD i;
6973     CERT_NAME_CONSTRAINTS_INFO *constraints;
6974
6975     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6976     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6977     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6978     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6979     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6980     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6981     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6982     for (i = 0;
6983      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6984      i++)
6985     {
6986         DWORD size;
6987
6988         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6989          encodedNameConstraints[i].encoded.pbData,
6990          encodedNameConstraints[i].encoded.cbData,
6991          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
6992         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6993         {
6994             skip("no X509_NAME_CONSTRAINTS decode support\n");
6995             return;
6996         }
6997         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
6998         if (ret)
6999         {
7000             DWORD j;
7001
7002             if (constraints->cPermittedSubtree !=
7003              encodedNameConstraints[i].constraints.cPermittedSubtree)
7004                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7005                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7006                  constraints->cPermittedSubtree);
7007             if (constraints->cPermittedSubtree ==
7008              encodedNameConstraints[i].constraints.cPermittedSubtree)
7009             {
7010                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7011                 {
7012                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7013                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7014                 }
7015             }
7016             if (constraints->cExcludedSubtree !=
7017              encodedNameConstraints[i].constraints.cExcludedSubtree)
7018                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7019                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7020                  constraints->cExcludedSubtree);
7021             if (constraints->cExcludedSubtree ==
7022              encodedNameConstraints[i].constraints.cExcludedSubtree)
7023             {
7024                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7025                 {
7026                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7027                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7028                 }
7029             }
7030             LocalFree(constraints);
7031         }
7032     }
7033 }
7034
7035 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7036  'n','o','t','i','c','e',0 };
7037 static const BYTE noticeWithDisplayText[] = {
7038  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7039  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7040  0x00,0x69,0x00,0x63,0x00,0x65
7041 };
7042 static char org[] = "Wine";
7043 static int noticeNumbers[] = { 2,3 };
7044 static BYTE noticeWithReference[] = {
7045  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7046  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7047  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7048  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7049 };
7050
7051 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7052 {
7053     BOOL ret;
7054     LPBYTE buf;
7055     DWORD size;
7056     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7057     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7058
7059     memset(&notice, 0, sizeof(notice));
7060     ret = pCryptEncodeObjectEx(dwEncoding,
7061      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7062      NULL, &buf, &size);
7063     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7064     {
7065         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7066         return;
7067     }
7068     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7069     if (ret)
7070     {
7071         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7072         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7073         LocalFree(buf);
7074     }
7075     notice.pszDisplayText = noticeText;
7076     ret = pCryptEncodeObjectEx(dwEncoding,
7077      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7078      NULL, &buf, &size);
7079     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7080     if (ret)
7081     {
7082         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7083         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7084         LocalFree(buf);
7085     }
7086     reference.pszOrganization = org;
7087     reference.cNoticeNumbers = 2;
7088     reference.rgNoticeNumbers = noticeNumbers;
7089     notice.pNoticeReference = &reference;
7090     ret = pCryptEncodeObjectEx(dwEncoding,
7091      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7092      NULL, &buf, &size);
7093     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7094     if (ret)
7095     {
7096         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7097         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7098         LocalFree(buf);
7099     }
7100 }
7101
7102 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7103 {
7104     BOOL ret;
7105     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7106     DWORD size;
7107
7108     ret = pCryptDecodeObjectEx(dwEncoding,
7109      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7110      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7111      &notice, &size);
7112     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7113     {
7114         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7115         return;
7116     }
7117     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7118     if (ret)
7119     {
7120         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7121         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7122         LocalFree(notice);
7123     }
7124     ret = pCryptDecodeObjectEx(dwEncoding,
7125      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7126      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7127      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7128     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7129     if (ret)
7130     {
7131         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7132          "unexpected display text\n");
7133         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7134         LocalFree(notice);
7135     }
7136     ret = pCryptDecodeObjectEx(dwEncoding,
7137      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7138      noticeWithReference, sizeof(noticeWithReference),
7139      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7140     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7141     if (ret)
7142     {
7143         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7144          "unexpected display text\n");
7145         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7146         if (notice->pNoticeReference)
7147         {
7148             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7149              "unexpected organization %s\n",
7150              notice->pNoticeReference->pszOrganization);
7151             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7152              "expected 2 notice numbers, got %d\n",
7153              notice->pNoticeReference->cNoticeNumbers);
7154             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7155              "unexpected notice number %d\n",
7156              notice->pNoticeReference->rgNoticeNumbers[0]);
7157             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7158              "unexpected notice number %d\n",
7159              notice->pNoticeReference->rgNoticeNumbers[1]);
7160         }
7161         LocalFree(notice);
7162     }
7163 }
7164
7165 static char oid_any_policy[] = "2.5.29.32.0";
7166 static const BYTE policiesWithAnyPolicy[] = {
7167  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7168 };
7169 static char oid1[] = "1.2.3";
7170 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7171 static const BYTE twoPolicies[] = {
7172  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7173  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7174  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7175  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7176  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7177  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7178 };
7179
7180 static void test_encodeCertPolicies(DWORD dwEncoding)
7181 {
7182     BOOL ret;
7183     CERT_POLICIES_INFO info;
7184     CERT_POLICY_INFO policy[2];
7185     CERT_POLICY_QUALIFIER_INFO qualifier;
7186     LPBYTE buf;
7187     DWORD size;
7188
7189     memset(&info, 0, sizeof(info));
7190     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7191      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7192     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7193     if (ret)
7194     {
7195         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7196         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7197         LocalFree(buf);
7198     }
7199     memset(policy, 0, sizeof(policy));
7200     info.cPolicyInfo = 1;
7201     info.rgPolicyInfo = policy;
7202     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7203      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7204     ok(!ret && (GetLastError() == E_INVALIDARG ||
7205      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7206      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7207     policy[0].pszPolicyIdentifier = oid_any_policy;
7208     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7209      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7210     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7211     if (ret)
7212     {
7213         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7214         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7215         LocalFree(buf);
7216     }
7217     policy[1].pszPolicyIdentifier = oid1;
7218     memset(&qualifier, 0, sizeof(qualifier));
7219     qualifier.pszPolicyQualifierId = oid_user_notice;
7220     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7221     qualifier.Qualifier.pbData = noticeWithReference;
7222     policy[1].cPolicyQualifier = 1;
7223     policy[1].rgPolicyQualifier = &qualifier;
7224     info.cPolicyInfo = 2;
7225     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7226      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7227     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7228     if (ret)
7229     {
7230         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7231         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7232         LocalFree(buf);
7233     }
7234 }
7235
7236 static void test_decodeCertPolicies(DWORD dwEncoding)
7237 {
7238     BOOL ret;
7239     CERT_POLICIES_INFO *info;
7240     DWORD size;
7241
7242     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7243      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7244      &info, &size);
7245     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7246     if (ret)
7247     {
7248         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7249          info->cPolicyInfo);
7250         LocalFree(info);
7251     }
7252     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7253      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7254      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7255     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7256     if (ret)
7257     {
7258         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7259          info->cPolicyInfo);
7260         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7261          "unexpected policy id %s\n",
7262          info->rgPolicyInfo[0].pszPolicyIdentifier);
7263         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7264          "unexpected policy qualifier count %d\n",
7265          info->rgPolicyInfo[0].cPolicyQualifier);
7266         LocalFree(info);
7267     }
7268     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7269      twoPolicies, sizeof(twoPolicies),
7270      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7271     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7272     if (ret)
7273     {
7274         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7275          info->cPolicyInfo);
7276         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7277          "unexpected policy id %s\n",
7278          info->rgPolicyInfo[0].pszPolicyIdentifier);
7279         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7280          "unexpected policy qualifier count %d\n",
7281          info->rgPolicyInfo[0].cPolicyQualifier);
7282         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7283          "unexpected policy id %s\n",
7284          info->rgPolicyInfo[1].pszPolicyIdentifier);
7285         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7286          "unexpected policy qualifier count %d\n",
7287          info->rgPolicyInfo[1].cPolicyQualifier);
7288         ok(!strcmp(
7289          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7290          oid_user_notice), "unexpected policy qualifier id %s\n",
7291          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7292         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7293          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7294          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7295         ok(!memcmp(
7296          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7297          noticeWithReference, sizeof(noticeWithReference)),
7298          "unexpected qualifier value\n");
7299         LocalFree(info);
7300     }
7301 }
7302
7303 /* Free *pInfo with HeapFree */
7304 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7305 {
7306     BOOL ret;
7307     DWORD size = 0;
7308     HCRYPTKEY key;
7309
7310     /* This crashes
7311     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7312      */
7313     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7314     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7315      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7316     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7317      &size);
7318     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7319      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7320     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7321      NULL, &size);
7322     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7323      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7324     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7325      0, NULL, NULL, &size);
7326     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7327      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7328     /* Test with no key */
7329     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7330      0, NULL, NULL, &size);
7331     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7332      GetLastError());
7333     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7334     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7335     if (ret)
7336     {
7337         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7338          NULL, 0, NULL, NULL, &size);
7339         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7340         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7341         if (*pInfo)
7342         {
7343             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7344              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7345             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7346              GetLastError());
7347             if (ret)
7348             {
7349                 /* By default (we passed NULL as the OID) the OID is
7350                  * szOID_RSA_RSA.
7351                  */
7352                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7353                  "Expected %s, got %s\n", szOID_RSA_RSA,
7354                  (*pInfo)->Algorithm.pszObjId);
7355             }
7356         }
7357     }
7358     CryptDestroyKey(key);
7359 }
7360
7361 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7362  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7363  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7364  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7365  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7366  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7367  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7368  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7369  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7370  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7371  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7372  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7373  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7374  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7375  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7376  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7377  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7378  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7379  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7380  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7381  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7382  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7383  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7384  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7385  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7386
7387 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7388 {
7389     BOOL ret;
7390     HCRYPTKEY key;
7391     PCCERT_CONTEXT context;
7392     DWORD dwSize;
7393     ALG_ID ai;
7394
7395     /* These crash
7396     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7397     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7398     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7399     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7400      NULL);
7401      */
7402     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7403     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7404      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7405     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7406     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7407      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7408     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7409      &key);
7410     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7411      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7412
7413     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7414     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7415      &key);
7416     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7417
7418     dwSize = sizeof(ai);
7419     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7420     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7421     if(ret)
7422     {
7423       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7424       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7425     }
7426
7427     CryptDestroyKey(key);
7428
7429     /* Repeat with forced algorithm */
7430     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7431      &key);
7432     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7433
7434     dwSize = sizeof(ai);
7435     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7436     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7437     if(ret)
7438     {
7439       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7440       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7441     }
7442
7443     CryptDestroyKey(key);
7444
7445     /* Test importing a public key from a certificate context */
7446     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7447      sizeof(expiredCert));
7448     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7449      GetLastError());
7450     if (context)
7451     {
7452         ok(!strcmp(szOID_RSA_RSA,
7453          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7454          "Expected %s, got %s\n", szOID_RSA_RSA,
7455          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7456         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7457          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7458         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7459         CryptDestroyKey(key);
7460         CertFreeCertificateContext(context);
7461     }
7462 }
7463
7464 static const char cspName[] = "WineCryptTemp";
7465
7466 static void testPortPublicKeyInfo(void)
7467 {
7468     HCRYPTPROV csp;
7469     BOOL ret;
7470     PCERT_PUBLIC_KEY_INFO info = NULL;
7471
7472     /* Just in case a previous run failed, delete this thing */
7473     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7474      CRYPT_DELETEKEYSET);
7475     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7476      CRYPT_NEWKEYSET);
7477
7478     testExportPublicKey(csp, &info);
7479     testImportPublicKey(csp, info);
7480
7481     HeapFree(GetProcessHeap(), 0, info);
7482     CryptReleaseContext(csp, 0);
7483     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7484      CRYPT_DELETEKEYSET);
7485 }
7486
7487 START_TEST(encode)
7488 {
7489     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7490      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7491     HMODULE hCrypt32;
7492     DWORD i;
7493
7494     hCrypt32 = GetModuleHandleA("crypt32.dll");
7495     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7496     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7497     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7498     {
7499         win_skip("CryptDecodeObjectEx() is not available\n");
7500         return;
7501     }
7502
7503     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7504     {
7505         test_encodeInt(encodings[i]);
7506         test_decodeInt(encodings[i]);
7507         test_encodeEnumerated(encodings[i]);
7508         test_decodeEnumerated(encodings[i]);
7509         test_encodeFiletime(encodings[i]);
7510         test_decodeFiletime(encodings[i]);
7511         test_encodeName(encodings[i]);
7512         test_decodeName(encodings[i]);
7513         test_encodeUnicodeName(encodings[i]);
7514         test_decodeUnicodeName(encodings[i]);
7515         test_encodeNameValue(encodings[i]);
7516         test_decodeNameValue(encodings[i]);
7517         test_encodeUnicodeNameValue(encodings[i]);
7518         test_decodeUnicodeNameValue(encodings[i]);
7519         test_encodeAltName(encodings[i]);
7520         test_decodeAltName(encodings[i]);
7521         test_encodeOctets(encodings[i]);
7522         test_decodeOctets(encodings[i]);
7523         test_encodeBits(encodings[i]);
7524         test_decodeBits(encodings[i]);
7525         test_encodeBasicConstraints(encodings[i]);
7526         test_decodeBasicConstraints(encodings[i]);
7527         test_encodeRsaPublicKey(encodings[i]);
7528         test_decodeRsaPublicKey(encodings[i]);
7529         test_encodeSequenceOfAny(encodings[i]);
7530         test_decodeSequenceOfAny(encodings[i]);
7531         test_encodeExtensions(encodings[i]);
7532         test_decodeExtensions(encodings[i]);
7533         test_encodePublicKeyInfo(encodings[i]);
7534         test_decodePublicKeyInfo(encodings[i]);
7535         test_encodeCertToBeSigned(encodings[i]);
7536         test_decodeCertToBeSigned(encodings[i]);
7537         test_encodeCert(encodings[i]);
7538         test_decodeCert(encodings[i]);
7539         test_encodeCRLDistPoints(encodings[i]);
7540         test_decodeCRLDistPoints(encodings[i]);
7541         test_encodeCRLIssuingDistPoint(encodings[i]);
7542         test_decodeCRLIssuingDistPoint(encodings[i]);
7543         test_encodeCRLToBeSigned(encodings[i]);
7544         test_decodeCRLToBeSigned(encodings[i]);
7545         test_encodeEnhancedKeyUsage(encodings[i]);
7546         test_decodeEnhancedKeyUsage(encodings[i]);
7547         test_encodeAuthorityKeyId(encodings[i]);
7548         test_decodeAuthorityKeyId(encodings[i]);
7549         test_encodeAuthorityKeyId2(encodings[i]);
7550         test_decodeAuthorityKeyId2(encodings[i]);
7551         test_encodeAuthorityInfoAccess(encodings[i]);
7552         test_decodeAuthorityInfoAccess(encodings[i]);
7553         test_encodeCTL(encodings[i]);
7554         test_decodeCTL(encodings[i]);
7555         test_encodePKCSContentInfo(encodings[i]);
7556         test_decodePKCSContentInfo(encodings[i]);
7557         test_encodePKCSAttribute(encodings[i]);
7558         test_decodePKCSAttribute(encodings[i]);
7559         test_encodePKCSAttributes(encodings[i]);
7560         test_decodePKCSAttributes(encodings[i]);
7561         test_encodePKCSSMimeCapabilities(encodings[i]);
7562         test_decodePKCSSMimeCapabilities(encodings[i]);
7563         test_encodePKCSSignerInfo(encodings[i]);
7564         test_decodePKCSSignerInfo(encodings[i]);
7565         test_encodeCMSSignerInfo(encodings[i]);
7566         test_decodeCMSSignerInfo(encodings[i]);
7567         test_encodeNameConstraints(encodings[i]);
7568         test_decodeNameConstraints(encodings[i]);
7569         test_encodePolicyQualifierUserNotice(encodings[i]);
7570         test_decodePolicyQualifierUserNotice(encodings[i]);
7571         test_encodeCertPolicies(encodings[i]);
7572         test_decodeCertPolicies(encodings[i]);
7573     }
7574     testPortPublicKeyInfo();
7575 }