mshtml: Added IHTMLDOMNode::insertBefore implementation.
[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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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, (BYTE *)&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              (BYTE *)&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, (BYTE *)&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          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
474 }
475
476 static const char *printSystemTime(const SYSTEMTIME *st)
477 {
478     static char buf[25];
479
480     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
481      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
482     return buf;
483 }
484
485 static const char *printFileTime(const FILETIME *ft)
486 {
487     static char buf[25];
488     SYSTEMTIME st;
489
490     FileTimeToSystemTime(ft, &st);
491     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
492      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
493     return buf;
494 }
495
496 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
497 {
498     SYSTEMTIME st;
499
500     FileTimeToSystemTime(got, &st);
501     ok(expected->wYear == st.wYear &&
502      expected->wMonth == st.wMonth &&
503      expected->wDay == st.wDay &&
504      expected->wHour == st.wHour &&
505      expected->wMinute == st.wMinute &&
506      expected->wSecond == st.wSecond &&
507      abs(expected->wMilliseconds - st.wMilliseconds) <= 1,
508      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
509      printSystemTime(expected), printFileTime(got));
510 }
511
512 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
513  const struct encodedFiletime *time)
514 {
515     FILETIME ft = { 0 };
516     DWORD size = sizeof(ft);
517     BOOL ret;
518
519     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
520      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
521     /* years other than 1950-2050 are not allowed for encodings other than
522      * X509_CHOICE_OF_TIME.
523      */
524     if (structType == X509_CHOICE_OF_TIME ||
525      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
526     {
527         ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
528          GetLastError());
529         compareTime(&time->sysTime, &ft);
530     }
531     else
532         ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
533          GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
534          "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
535          GetLastError());
536 }
537
538 static const BYTE bin20[] = {
539     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
540 static const BYTE bin21[] = {
541     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
542 static const BYTE bin22[] = {
543     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
544
545 static const struct encodedFiletime times[] = {
546  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
547  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
548  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
549 };
550
551 static void test_encodeFiletime(DWORD dwEncoding)
552 {
553     DWORD i;
554
555     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
556     {
557         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
558         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
559         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
560     }
561 }
562
563 static const BYTE bin23[] = {
564     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
565 static const BYTE bin24[] = {
566     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
567 static const BYTE bin25[] = {
568     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
569 static const BYTE bin26[] = {
570     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
571 static const BYTE bin27[] = {
572     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
573 static const BYTE bin28[] = {
574     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
575 static const BYTE bin29[] = {
576     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
577 static const BYTE bin30[] = {
578     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
579 static const BYTE bin31[] = {
580     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
581 static const BYTE bin32[] = {
582     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
583 static const BYTE bin33[] = {
584     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
585 static const BYTE bin34[] = {
586     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
587 static const BYTE bin35[] = {
588     0x17,0x08, '4','5','0','6','0','6','1','6'};
589 static const BYTE bin36[] = {
590     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
591 static const BYTE bin37[] = {
592     0x18,0x04, '2','1','4','5'};
593 static const BYTE bin38[] = {
594     0x18,0x08, '2','1','4','5','0','6','0','6'};
595
596 static void test_decodeFiletime(DWORD dwEncoding)
597 {
598     static const struct encodedFiletime otherTimes[] = {
599      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
600      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
601      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
602      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
603      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
604      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
605      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
606      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
607      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
608      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
609      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
610      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
611     };
612     /* An oddball case that succeeds in Windows, but doesn't seem correct
613      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
614      */
615     static const unsigned char *bogusTimes[] = {
616      /* oddly, this succeeds on Windows, with year 2765
617      "\x18" "\x0f" "21r50606161000Z",
618       */
619      bin35,
620      bin36,
621      bin37,
622      bin38,
623     };
624     DWORD i, size;
625     FILETIME ft1 = { 0 }, ft2 = { 0 };
626     BOOL ret;
627
628     /* Check bogus length with non-NULL buffer */
629     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
630     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
631     size = 1;
632     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
633      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
634     ok(!ret && GetLastError() == ERROR_MORE_DATA,
635      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
636     /* Normal tests */
637     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
638     {
639         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
640         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
641         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
642     }
643     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
644     {
645         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
646         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
647         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
648     }
649     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
650     {
651         size = sizeof(ft1);
652         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
653          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
654         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
655          GetLastError() == OSS_DATA_ERROR /* Win9x */),
656          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
657          GetLastError());
658     }
659 }
660
661 static const char commonName[] = "Juan Lang";
662 static const char surName[] = "Lang";
663
664 static const BYTE emptySequence[] = { 0x30, 0 };
665 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
666 static const BYTE twoRDNs[] = {
667     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
668     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
669     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
670 static const BYTE encodedTwoRDNs[] = {
671 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
672 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
673 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
674 0x6e,0x67,0x00,
675 };
676
677 static const BYTE us[] = { 0x55, 0x53 };
678 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
679  0x74, 0x61 };
680 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
681  0x6f, 0x6c, 0x69, 0x73 };
682 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
683  0x76, 0x65, 0x72, 0x73 };
684 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
685  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
686 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
687  0x73, 0x74 };
688 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
689  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
690
691 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
692 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
693
694 static CHAR oid_us[]            = "2.5.4.6",
695             oid_minnesota[]     = "2.5.4.8",
696             oid_minneapolis[]   = "2.5.4.7",
697             oid_codeweavers[]   = "2.5.4.10",
698             oid_wine[]          = "2.5.4.11",
699             oid_localhostAttr[] = "2.5.4.3",
700             oid_aric[]          = "1.2.840.113549.1.9.1";
701 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
702                                     { RDNA(minnesota) },
703                                     { RDNA(minneapolis) },
704                                     { RDNA(codeweavers) },
705                                     { RDNA(wine) },
706                                     { RDNA(localhostAttr) },
707                                     { RDNIA5(aric) } };
708 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
709                                            { RDNA(localhostAttr) },
710                                            { RDNA(minnesota) },
711                                            { RDNA(minneapolis) },
712                                            { RDNA(codeweavers) },
713                                            { RDNA(wine) },
714                                            { RDNIA5(aric) } };
715
716 #undef RDNIA5
717 #undef RDNA
718
719 static const BYTE encodedRDNAttrs[] = {
720 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
721 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
722 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
723 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
724 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
725 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
726 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
727 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
728 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
729 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
730 };
731
732 static void test_encodeName(DWORD dwEncoding)
733 {
734     CERT_RDN_ATTR attrs[2];
735     CERT_RDN rdn;
736     CERT_NAME_INFO info;
737     static CHAR oid_common_name[] = szOID_COMMON_NAME,
738                 oid_sur_name[]    = szOID_SUR_NAME;
739     BYTE *buf = NULL;
740     DWORD size = 0;
741     BOOL ret;
742
743     if (0)
744     {
745         /* Test with NULL pvStructInfo (crashes on win9x) */
746         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
747          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
748         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
749          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
750     }
751     /* Test with empty CERT_NAME_INFO */
752     info.cRDN = 0;
753     info.rgRDN = NULL;
754     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
755      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
756     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
757     if (buf)
758     {
759         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
760          "Got unexpected encoding for empty name\n");
761         LocalFree(buf);
762     }
763     if (0)
764     {
765         /* Test with bogus CERT_RDN (crashes on win9x) */
766         info.cRDN = 1;
767         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
768          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
769         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
770          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
771     }
772     /* Test with empty CERT_RDN */
773     rdn.cRDNAttr = 0;
774     rdn.rgRDNAttr = NULL;
775     info.cRDN = 1;
776     info.rgRDN = &rdn;
777     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
778      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
779     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
780     if (buf)
781     {
782         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
783          "Got unexpected encoding for empty RDN array\n");
784         LocalFree(buf);
785     }
786     if (0)
787     {
788         /* Test with bogus attr array (crashes on win9x) */
789         rdn.cRDNAttr = 1;
790         rdn.rgRDNAttr = NULL;
791         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
792          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
793         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
794          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
795     }
796     /* oddly, a bogus OID is accepted by Windows XP; not testing.
797     attrs[0].pszObjId = "bogus";
798     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
799     attrs[0].Value.cbData = sizeof(commonName);
800     attrs[0].Value.pbData = (BYTE *)commonName;
801     rdn.cRDNAttr = 1;
802     rdn.rgRDNAttr = attrs;
803     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
804      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
805     ok(!ret, "Expected failure, got success\n");
806      */
807     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
808      * the encoded attributes to be swapped.
809      */
810     attrs[0].pszObjId = oid_common_name;
811     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
812     attrs[0].Value.cbData = sizeof(commonName);
813     attrs[0].Value.pbData = (BYTE *)commonName;
814     attrs[1].pszObjId = oid_sur_name;
815     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
816     attrs[1].Value.cbData = sizeof(surName);
817     attrs[1].Value.pbData = (BYTE *)surName;
818     rdn.cRDNAttr = 2;
819     rdn.rgRDNAttr = attrs;
820     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
821      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
822     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
823     if (buf)
824     {
825         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
826          "Got unexpected encoding for two RDN array\n");
827         LocalFree(buf);
828     }
829     /* A name can be "encoded" with previously encoded RDN attrs. */
830     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
831     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
832     attrs[0].Value.cbData = sizeof(twoRDNs);
833     rdn.cRDNAttr = 1;
834     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
835      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
836     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
837     if (buf)
838     {
839         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
840         ok(!memcmp(buf, encodedTwoRDNs, size),
841          "Unexpected value for re-endoded two RDN array\n");
842         LocalFree(buf);
843     }
844     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
845     rdn.cRDNAttr = 1;
846     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
847     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
848      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
849     ok(!ret && GetLastError() == E_INVALIDARG,
850      "Expected E_INVALIDARG, got %08x\n", GetLastError());
851     /* Test a more complex name */
852     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
853     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
854     info.cRDN = 1;
855     info.rgRDN = &rdn;
856     buf = NULL;
857     size = 0;
858     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
859      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
860     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
861     if (ret)
862     {
863         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
864         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
865         LocalFree(buf);
866     }
867 }
868
869 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
870 static WCHAR surNameW[] = { 'L','a','n','g',0 };
871
872 static const BYTE twoRDNsNoNull[] = {
873  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
874  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
875  0x20,0x4c,0x61,0x6e,0x67 };
876 static const BYTE anyType[] = {
877  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
878  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
879  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
880  0x61,0x4c,0x67,0x6e };
881
882 static void test_encodeUnicodeName(DWORD dwEncoding)
883 {
884     CERT_RDN_ATTR attrs[2];
885     CERT_RDN rdn;
886     CERT_NAME_INFO info;
887     static CHAR oid_common_name[] = szOID_COMMON_NAME,
888                 oid_sur_name[]    = szOID_SUR_NAME;
889     BYTE *buf = NULL;
890     DWORD size = 0;
891     BOOL ret;
892
893     if (0)
894     {
895         /* Test with NULL pvStructInfo (crashes on win9x) */
896         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
897          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
898         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
899          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
900     }
901     /* Test with empty CERT_NAME_INFO */
902     info.cRDN = 0;
903     info.rgRDN = NULL;
904     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
905      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
906     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
907     if (buf)
908     {
909         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
910          "Got unexpected encoding for empty name\n");
911         LocalFree(buf);
912     }
913     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
914      * encoding (the NULL).
915      */
916     attrs[0].pszObjId = oid_common_name;
917     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
918     attrs[0].Value.cbData = sizeof(commonNameW);
919     attrs[0].Value.pbData = (BYTE *)commonNameW;
920     rdn.cRDNAttr = 1;
921     rdn.rgRDNAttr = attrs;
922     info.cRDN = 1;
923     info.rgRDN = &rdn;
924     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
925      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
926     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
927      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
928     ok(size == 9, "Unexpected error index %08x\n", size);
929     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
930      * forces the order of the encoded attributes to be swapped.
931      */
932     attrs[0].pszObjId = oid_common_name;
933     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
934     attrs[0].Value.cbData = 0;
935     attrs[0].Value.pbData = (BYTE *)commonNameW;
936     attrs[1].pszObjId = oid_sur_name;
937     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
938     attrs[1].Value.cbData = 0;
939     attrs[1].Value.pbData = (BYTE *)surNameW;
940     rdn.cRDNAttr = 2;
941     rdn.rgRDNAttr = attrs;
942     info.cRDN = 1;
943     info.rgRDN = &rdn;
944     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
945      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
946     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
947     if (buf)
948     {
949         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
950          "Got unexpected encoding for two RDN array\n");
951         LocalFree(buf);
952     }
953     /* A name can be "encoded" with previously encoded RDN attrs. */
954     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
955     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
956     attrs[0].Value.cbData = sizeof(twoRDNs);
957     rdn.cRDNAttr = 1;
958     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
959      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
960     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
961     if (buf)
962     {
963         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
964         ok(!memcmp(buf, encodedTwoRDNs, size),
965          "Unexpected value for re-endoded two RDN array\n");
966         LocalFree(buf);
967     }
968     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
969     rdn.cRDNAttr = 1;
970     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
971     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
972      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
973     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
974     if (buf)
975     {
976         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
977         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
978         LocalFree(buf);
979     }
980 }
981
982 static void compareNameValues(const CERT_NAME_VALUE *expected,
983  const CERT_NAME_VALUE *got)
984 {
985     ok(got->dwValueType == expected->dwValueType,
986      "Expected string type %d, got %d\n", expected->dwValueType,
987      got->dwValueType);
988     ok(got->Value.cbData == expected->Value.cbData,
989      "String type %d: unexpected data size, got %d, expected %d\n",
990      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
991     if (got->Value.cbData && got->Value.pbData)
992         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
993          min(got->Value.cbData, expected->Value.cbData)),
994          "String type %d: unexpected value\n", expected->dwValueType);
995 }
996
997 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
998  const CERT_RDN_ATTR *got)
999 {
1000     if (expected->pszObjId && strlen(expected->pszObjId))
1001     {
1002         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1003          expected->pszObjId);
1004         if (got->pszObjId)
1005         {
1006             ok(!strcmp(got->pszObjId, expected->pszObjId),
1007              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1008              expected->pszObjId);
1009         }
1010     }
1011     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1012      (const CERT_NAME_VALUE *)&got->dwValueType);
1013 }
1014
1015 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1016 {
1017     ok(got->cRDNAttr == expected->cRDNAttr,
1018      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1019     if (got->cRDNAttr)
1020     {
1021         DWORD i;
1022
1023         for (i = 0; i < got->cRDNAttr; i++)
1024             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1025     }
1026 }
1027
1028 static void compareNames(const CERT_NAME_INFO *expected,
1029  const CERT_NAME_INFO *got)
1030 {
1031     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1032      expected->cRDN, got->cRDN);
1033     if (got->cRDN)
1034     {
1035         DWORD i;
1036
1037         for (i = 0; i < got->cRDN; i++)
1038             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1039     }
1040 }
1041
1042 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1043 static const BYTE twoRDNsExtraBytes[] = {
1044     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1045     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1046     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1047
1048 static void test_decodeName(DWORD dwEncoding)
1049 {
1050     BYTE *buf = NULL;
1051     DWORD bufSize = 0;
1052     BOOL ret;
1053     CERT_RDN rdn;
1054     CERT_NAME_INFO info = { 1, &rdn };
1055
1056     /* test empty name */
1057     bufSize = 0;
1058     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1059      emptySequence[1] + 2,
1060      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1061      (BYTE *)&buf, &bufSize);
1062     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1063     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1064      * decoder works the same way, so only test the count.
1065      */
1066     if (buf)
1067     {
1068         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1069         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1070          "Expected 0 RDNs in empty info, got %d\n",
1071          ((CERT_NAME_INFO *)buf)->cRDN);
1072         LocalFree(buf);
1073     }
1074     /* test empty name with indefinite-length encoding */
1075     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1076      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1077      (BYTE *)&buf, &bufSize);
1078     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1079     if (ret)
1080     {
1081         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1082         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1083          "Expected 0 RDNs in empty info, got %d\n",
1084          ((CERT_NAME_INFO *)buf)->cRDN);
1085         LocalFree(buf);
1086     }
1087     /* test empty RDN */
1088     bufSize = 0;
1089     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1090      emptyRDNs[1] + 2,
1091      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1092      (BYTE *)&buf, &bufSize);
1093     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1094     if (buf)
1095     {
1096         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1097
1098         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1099          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1100          "Got unexpected value for empty RDN\n");
1101         LocalFree(buf);
1102     }
1103     /* test two RDN attrs */
1104     bufSize = 0;
1105     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1106      twoRDNs[1] + 2,
1107      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1108      (BYTE *)&buf, &bufSize);
1109     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1110     if (buf)
1111     {
1112         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1113                     oid_common_name[] = szOID_COMMON_NAME;
1114
1115         CERT_RDN_ATTR attrs[] = {
1116          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1117           (BYTE *)surName } },
1118          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1119           (BYTE *)commonName } },
1120         };
1121
1122         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1123         rdn.rgRDNAttr = attrs;
1124         compareNames(&info, (CERT_NAME_INFO *)buf);
1125         LocalFree(buf);
1126     }
1127     /* test that two RDN attrs with extra bytes succeeds */
1128     bufSize = 0;
1129     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1130      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1131     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1132     /* And, a slightly more complicated name */
1133     buf = NULL;
1134     bufSize = 0;
1135     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1136      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1137     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1138     if (ret)
1139     {
1140         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1141         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1142         compareNames(&info, (CERT_NAME_INFO *)buf);
1143         LocalFree(buf);
1144     }
1145 }
1146
1147 static void test_decodeUnicodeName(DWORD dwEncoding)
1148 {
1149     BYTE *buf = NULL;
1150     DWORD bufSize = 0;
1151     BOOL ret;
1152     CERT_RDN rdn;
1153     CERT_NAME_INFO info = { 1, &rdn };
1154
1155     /* test empty name */
1156     bufSize = 0;
1157     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1158      emptySequence[1] + 2,
1159      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1160      (BYTE *)&buf, &bufSize);
1161     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1162     if (buf)
1163     {
1164         ok(bufSize == sizeof(CERT_NAME_INFO),
1165          "Got wrong bufSize %d\n", bufSize);
1166         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1167          "Expected 0 RDNs in empty info, got %d\n",
1168          ((CERT_NAME_INFO *)buf)->cRDN);
1169         LocalFree(buf);
1170     }
1171     /* test empty RDN */
1172     bufSize = 0;
1173     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1174      emptyRDNs[1] + 2,
1175      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1176      (BYTE *)&buf, &bufSize);
1177     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1178     if (buf)
1179     {
1180         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1181
1182         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1183          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1184          "Got unexpected value for empty RDN\n");
1185         LocalFree(buf);
1186     }
1187     /* test two RDN attrs */
1188     bufSize = 0;
1189     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1190      sizeof(twoRDNsNoNull),
1191      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1192      (BYTE *)&buf, &bufSize);
1193     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1194     if (buf)
1195     {
1196         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1197                     oid_common_name[] = szOID_COMMON_NAME;
1198
1199         CERT_RDN_ATTR attrs[] = {
1200          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1201          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1202          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1203          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1204         };
1205
1206         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1207         rdn.rgRDNAttr = attrs;
1208         compareNames(&info, (CERT_NAME_INFO *)buf);
1209         LocalFree(buf);
1210     }
1211 }
1212
1213 struct EncodedNameValue
1214 {
1215     CERT_NAME_VALUE value;
1216     const BYTE *encoded;
1217     DWORD encodedSize;
1218 };
1219
1220 static const char bogusIA5[] = "\x80";
1221 static const char bogusPrintable[] = "~";
1222 static const char bogusNumeric[] = "A";
1223 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1224 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1225 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1226 static BYTE octetCommonNameValue[] = {
1227  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1228 static BYTE numericCommonNameValue[] = {
1229  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1230 static BYTE printableCommonNameValue[] = {
1231  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1232 static BYTE t61CommonNameValue[] = {
1233  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1234 static BYTE videotexCommonNameValue[] = {
1235  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1236 static BYTE ia5CommonNameValue[] = {
1237  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1238 static BYTE graphicCommonNameValue[] = {
1239  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1240 static BYTE visibleCommonNameValue[] = {
1241  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1242 static BYTE generalCommonNameValue[] = {
1243  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1244 static BYTE bmpCommonNameValue[] = {
1245  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1246  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1247 static BYTE utf8CommonNameValue[] = {
1248  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1249
1250 static struct EncodedNameValue nameValues[] = {
1251  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1252      octetCommonNameValue, sizeof(octetCommonNameValue) },
1253  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1254      numericCommonNameValue, sizeof(numericCommonNameValue) },
1255  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1256      printableCommonNameValue, sizeof(printableCommonNameValue) },
1257  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1258      t61CommonNameValue, sizeof(t61CommonNameValue) },
1259  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1260      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1261  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1262      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1263  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1264      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1265  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1266      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1267  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1268      generalCommonNameValue, sizeof(generalCommonNameValue) },
1269  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1270      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1271  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1272      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1273  /* The following tests succeed under Windows, but really should fail,
1274   * they contain characters that are illegal for the encoding.  I'm
1275   * including them to justify my lazy encoding.
1276   */
1277  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1278      sizeof(bin42) },
1279  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1280      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1281  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1282      bin44, sizeof(bin44) },
1283 };
1284
1285 static void test_encodeNameValue(DWORD dwEncoding)
1286 {
1287     BYTE *buf = NULL;
1288     DWORD size = 0, i;
1289     BOOL ret;
1290     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1291
1292     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1293     value.Value.pbData = printableCommonNameValue;
1294     value.Value.cbData = sizeof(printableCommonNameValue);
1295     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1296      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1297     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1298     if (buf)
1299     {
1300         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1301          size);
1302         ok(!memcmp(buf, printableCommonNameValue, size),
1303          "Unexpected encoding\n");
1304         LocalFree(buf);
1305     }
1306     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1307     {
1308         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1309          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1310          &size);
1311         ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1312          nameValues[i].value.dwValueType, GetLastError());
1313         if (buf)
1314         {
1315             ok(size == nameValues[i].encodedSize,
1316              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1317             ok(!memcmp(buf, nameValues[i].encoded, size),
1318              "Got unexpected encoding\n");
1319             LocalFree(buf);
1320         }
1321     }
1322 }
1323
1324 static void test_decodeNameValue(DWORD dwEncoding)
1325 {
1326     int i;
1327     BYTE *buf = NULL;
1328     DWORD bufSize = 0;
1329     BOOL ret;
1330
1331     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1332     {
1333         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1334          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1335          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1336          (BYTE *)&buf, &bufSize);
1337         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1338          nameValues[i].value.dwValueType, GetLastError());
1339         if (buf)
1340         {
1341             compareNameValues(&nameValues[i].value,
1342              (const CERT_NAME_VALUE *)buf);
1343             LocalFree(buf);
1344         }
1345     }
1346 }
1347
1348 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1349 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1350 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1351  'h','q','.','o','r','g',0 };
1352 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1353  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1354  0x6f, 0x72, 0x67 };
1355 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1356  0x575b, 0 };
1357 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1358 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1359  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1360 static const BYTE localhost[] = { 127, 0, 0, 1 };
1361 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1362  0x01 };
1363 static const unsigned char encodedCommonName[] = {
1364     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1365 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1366 static const BYTE encodedDirectoryName[] = {
1367 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1368 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1369
1370 static void test_encodeAltName(DWORD dwEncoding)
1371 {
1372     CERT_ALT_NAME_INFO info = { 0 };
1373     CERT_ALT_NAME_ENTRY entry = { 0 };
1374     BYTE *buf = NULL;
1375     DWORD size = 0;
1376     BOOL ret;
1377     char oid[] = "1.2.3";
1378
1379     /* Test with empty info */
1380     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1381      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1382     if (buf)
1383     {
1384         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1385         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1386         LocalFree(buf);
1387     }
1388     /* Test with an empty entry */
1389     info.cAltEntry = 1;
1390     info.rgAltEntry = &entry;
1391     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1392      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1393     ok(!ret && GetLastError() == E_INVALIDARG,
1394      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1395     /* Test with an empty pointer */
1396     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1397     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1398      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1399     if (buf)
1400     {
1401         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1402         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1403         LocalFree(buf);
1404     }
1405     /* Test with a real URL */
1406     U(entry).pwszURL = (LPWSTR)url;
1407     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1408      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1409     if (buf)
1410     {
1411         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1412         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1413         LocalFree(buf);
1414     }
1415     /* Now with the URL containing an invalid IA5 char */
1416     U(entry).pwszURL = (LPWSTR)nihongoURL;
1417     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1418      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1419     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1420      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1421     /* The first invalid character is at index 7 */
1422     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1423      "Expected invalid char at index 7, got %d\n",
1424      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1425     /* Now with the URL missing a scheme */
1426     U(entry).pwszURL = (LPWSTR)dnsName;
1427     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1428      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1429     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1430     if (buf)
1431     {
1432         /* This succeeds, but it shouldn't, so don't worry about conforming */
1433         LocalFree(buf);
1434     }
1435     /* Now with a DNS name */
1436     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1437     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1438      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1439     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1440     if (buf)
1441     {
1442         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1443         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1444         LocalFree(buf);
1445     }
1446     /* Test with an IP address */
1447     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1448     U(entry).IPAddress.cbData = sizeof(localhost);
1449     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1450     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1451      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1452     if (buf)
1453     {
1454         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1455         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1456         LocalFree(buf);
1457     }
1458     /* Test with OID */
1459     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1460     U(entry).pszRegisteredID = oid;
1461     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1462      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1463     if (buf)
1464     {
1465         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1466         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1467         LocalFree(buf);
1468     }
1469     /* Test with directory name */
1470     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1471     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1472     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1473     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1474      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1475     if (buf)
1476     {
1477         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1478         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1479         LocalFree(buf);
1480     }
1481 }
1482
1483 static void test_decodeAltName(DWORD dwEncoding)
1484 {
1485     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1486      0x00, 0x00, 0x01 };
1487     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1488      0x01 };
1489     BOOL ret;
1490     BYTE *buf = NULL;
1491     DWORD bufSize = 0;
1492     CERT_ALT_NAME_INFO *info;
1493
1494     /* Test some bogus ones first */
1495     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1496      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1497      NULL, (BYTE *)&buf, &bufSize);
1498     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1499      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1500      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1501      GetLastError());
1502     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1503      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1504      &bufSize);
1505     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1506      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1507      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1508      GetLastError());
1509     /* Now expected cases */
1510     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1511      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1512      &bufSize);
1513     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1514     if (buf)
1515     {
1516         info = (CERT_ALT_NAME_INFO *)buf;
1517
1518         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1519          info->cAltEntry);
1520         LocalFree(buf);
1521     }
1522     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1523      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1524      &bufSize);
1525     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1526     if (buf)
1527     {
1528         info = (CERT_ALT_NAME_INFO *)buf;
1529
1530         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1531          info->cAltEntry);
1532         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1533          "Expected CERT_ALT_NAME_URL, got %d\n",
1534          info->rgAltEntry[0].dwAltNameChoice);
1535         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1536          "Expected empty URL\n");
1537         LocalFree(buf);
1538     }
1539     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1540      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1541     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1542     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1543      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1544      &bufSize);
1545     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1546     if (buf)
1547     {
1548         info = (CERT_ALT_NAME_INFO *)buf;
1549
1550         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1551          info->cAltEntry);
1552         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1553          "Expected CERT_ALT_NAME_URL, got %d\n",
1554          info->rgAltEntry[0].dwAltNameChoice);
1555         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1556         LocalFree(buf);
1557     }
1558     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1559      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1560      &bufSize);
1561     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1562     if (buf)
1563     {
1564         info = (CERT_ALT_NAME_INFO *)buf;
1565
1566         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1567          info->cAltEntry);
1568         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1569          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1570          info->rgAltEntry[0].dwAltNameChoice);
1571         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1572          "Unexpected DNS name\n");
1573         LocalFree(buf);
1574     }
1575     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1576      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1577      &bufSize);
1578     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1579     if (buf)
1580     {
1581         info = (CERT_ALT_NAME_INFO *)buf;
1582
1583         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1584          info->cAltEntry);
1585         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1586          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1587          info->rgAltEntry[0].dwAltNameChoice);
1588         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1589          "Unexpected IP address length %d\n",
1590           U(info->rgAltEntry[0]).IPAddress.cbData);
1591         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1592          sizeof(localhost)), "Unexpected IP address value\n");
1593         LocalFree(buf);
1594     }
1595     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1596      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1597      &bufSize);
1598     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1599     if (buf)
1600     {
1601         info = (CERT_ALT_NAME_INFO *)buf;
1602
1603         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1604          info->cAltEntry);
1605         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1606          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1607          info->rgAltEntry[0].dwAltNameChoice);
1608         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1609            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1610         LocalFree(buf);
1611     }
1612     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1613      encodedDirectoryName, sizeof(encodedDirectoryName),
1614      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1615     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1616     if (buf)
1617     {
1618         info = (CERT_ALT_NAME_INFO *)buf;
1619
1620         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1621          info->cAltEntry);
1622         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1623          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1624          info->rgAltEntry[0].dwAltNameChoice);
1625         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1626          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1627           U(info->rgAltEntry[0]).DirectoryName.cbData);
1628         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1629          encodedCommonName, sizeof(encodedCommonName)),
1630          "Unexpected directory name value\n");
1631         LocalFree(buf);
1632     }
1633 }
1634
1635 struct UnicodeExpectedError
1636 {
1637     DWORD   valueType;
1638     LPCWSTR str;
1639     DWORD   errorIndex;
1640     DWORD   error;
1641 };
1642
1643 static const WCHAR oneW[] = { '1',0 };
1644 static const WCHAR aW[] = { 'a',0 };
1645 static const WCHAR quoteW[] = { '"', 0 };
1646
1647 static struct UnicodeExpectedError unicodeErrors[] = {
1648  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1649  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1650  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1651  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1652  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1653  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1654 };
1655
1656 struct UnicodeExpectedResult
1657 {
1658     DWORD           valueType;
1659     LPCWSTR         str;
1660     CRYPT_DATA_BLOB encoded;
1661 };
1662
1663 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1664 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1665 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1666 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1667 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1668 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1669 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1670 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1671 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1672 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1673 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1674 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1675  0x5b };
1676 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1677  0x6f,0x5b };
1678 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1679  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1680 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1681  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1682
1683 static struct UnicodeExpectedResult unicodeResults[] = {
1684  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1685  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1686  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1687  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1688  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1689  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1690  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1691  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1692  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1693  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1694  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1695  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1696  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1697 };
1698
1699 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1700  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1701  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1702 };
1703
1704 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1705 {
1706     BYTE *buf = NULL;
1707     DWORD size = 0, i;
1708     BOOL ret;
1709     CERT_NAME_VALUE value;
1710
1711     if (0)
1712     {
1713         /* Crashes on win9x */
1714         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1715          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1716         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1717          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1718     }
1719     /* Have to have a string of some sort */
1720     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1721     value.Value.pbData = NULL;
1722     value.Value.cbData = 0;
1723     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1724      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1725     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1726      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1727     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1728     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1729      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1730     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1731      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1732     value.dwValueType = CERT_RDN_ANY_TYPE;
1733     value.Value.pbData = (LPBYTE)oneW;
1734     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1735      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1736     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1737      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1738     value.Value.cbData = sizeof(oneW);
1739     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1740      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1741     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1742      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1743     /* An encoded string with specified length isn't good enough either */
1744     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1745     value.Value.pbData = oneUniversal;
1746     value.Value.cbData = sizeof(oneUniversal);
1747     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1748      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1749     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1750      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1751     /* More failure checking */
1752     value.Value.cbData = 0;
1753     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1754     {
1755         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1756         value.dwValueType = unicodeErrors[i].valueType;
1757         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1758          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1759         ok(!ret && GetLastError() == unicodeErrors[i].error,
1760          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1761          unicodeErrors[i].error, GetLastError());
1762         ok(size == unicodeErrors[i].errorIndex,
1763          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1764          size);
1765     }
1766     /* cbData can be zero if the string is NULL-terminated */
1767     value.Value.cbData = 0;
1768     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1769     {
1770         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1771         value.dwValueType = unicodeResults[i].valueType;
1772         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1773          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1774         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1775         if (buf)
1776         {
1777             ok(size == unicodeResults[i].encoded.cbData,
1778              "Value type %d: expected size %d, got %d\n",
1779              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1780             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1781              "Value type %d: unexpected value\n", value.dwValueType);
1782             LocalFree(buf);
1783         }
1784     }
1785     /* These "encode," but they do so by truncating each unicode character
1786      * rather than properly encoding it.  Kept separate from the proper results,
1787      * because the encoded forms won't decode to their original strings.
1788      */
1789     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1790     {
1791         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1792         value.dwValueType = unicodeWeirdness[i].valueType;
1793         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1794          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1795         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1796         if (buf)
1797         {
1798             ok(size == unicodeWeirdness[i].encoded.cbData,
1799              "Value type %d: expected size %d, got %d\n",
1800              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1801             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1802              "Value type %d: unexpected value\n", value.dwValueType);
1803             LocalFree(buf);
1804         }
1805     }
1806 }
1807
1808 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1809 {
1810     if (n <= 0) return 0;
1811     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1812     return *str1 - *str2;
1813 }
1814
1815 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1816 {
1817     DWORD i;
1818
1819     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1820     {
1821         BYTE *buf = NULL;
1822         BOOL ret;
1823         DWORD size = 0;
1824
1825         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1826          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1827          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1828         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1829         if (ret && buf)
1830         {
1831             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1832
1833             ok(value->dwValueType == unicodeResults[i].valueType,
1834              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1835              value->dwValueType);
1836             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1837              value->Value.cbData / sizeof(WCHAR)),
1838              "Unexpected decoded value for index %d (value type %d)\n", i,
1839              unicodeResults[i].valueType);
1840             LocalFree(buf);
1841         }
1842     }
1843 }
1844
1845 struct encodedOctets
1846 {
1847     const BYTE *val;
1848     const BYTE *encoded;
1849 };
1850
1851 static const unsigned char bin46[] = { 'h','i',0 };
1852 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1853 static const unsigned char bin48[] = {
1854      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1855 static const unsigned char bin49[] = {
1856      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1857 static const unsigned char bin50[] = { 0 };
1858 static const unsigned char bin51[] = { 0x04,0x00,0 };
1859
1860 static const struct encodedOctets octets[] = {
1861     { bin46, bin47 },
1862     { bin48, bin49 },
1863     { bin50, bin51 },
1864 };
1865
1866 static void test_encodeOctets(DWORD dwEncoding)
1867 {
1868     CRYPT_DATA_BLOB blob;
1869     DWORD i;
1870
1871     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1872     {
1873         BYTE *buf = NULL;
1874         BOOL ret;
1875         DWORD bufSize = 0;
1876
1877         blob.cbData = strlen((const char*)octets[i].val);
1878         blob.pbData = (BYTE*)octets[i].val;
1879         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1880          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1881         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1882         if (buf)
1883         {
1884             ok(buf[0] == 4,
1885              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1886             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1887              buf[1], octets[i].encoded[1]);
1888             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1889              octets[i].encoded[1] + 1), "Got unexpected value\n");
1890             LocalFree(buf);
1891         }
1892     }
1893 }
1894
1895 static void test_decodeOctets(DWORD dwEncoding)
1896 {
1897     DWORD i;
1898
1899     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1900     {
1901         BYTE *buf = NULL;
1902         BOOL ret;
1903         DWORD bufSize = 0;
1904
1905         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1906          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1907          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1908         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1909         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1910          "Expected size >= %d, got %d\n",
1911            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1912         ok(buf != NULL, "Expected allocated buffer\n");
1913         if (buf)
1914         {
1915             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1916
1917             if (blob->cbData)
1918                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1919                  "Unexpected value\n");
1920             LocalFree(buf);
1921         }
1922     }
1923 }
1924
1925 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1926
1927 struct encodedBits
1928 {
1929     DWORD cUnusedBits;
1930     const BYTE *encoded;
1931     DWORD cbDecoded;
1932     const BYTE *decoded;
1933 };
1934
1935 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1936 static const unsigned char bin53[] = { 0xff,0xff };
1937 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1938 static const unsigned char bin55[] = { 0xff,0xfe };
1939 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1940 static const unsigned char bin57[] = { 0xfe };
1941 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1942
1943 static const struct encodedBits bits[] = {
1944     /* normal test cases */
1945     { 0, bin52, 2, bin53 },
1946     { 1, bin54, 2, bin55 },
1947     /* strange test case, showing cUnusedBits >= 8 is allowed */
1948     { 9, bin56, 1, bin57 },
1949     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1950     { 17, bin58, 0, NULL },
1951 };
1952
1953 static void test_encodeBits(DWORD dwEncoding)
1954 {
1955     DWORD i;
1956
1957     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1958     {
1959         CRYPT_BIT_BLOB blob;
1960         BOOL ret;
1961         BYTE *buf = NULL;
1962         DWORD bufSize = 0;
1963
1964         blob.cbData = sizeof(bytesToEncode);
1965         blob.pbData = (BYTE *)bytesToEncode;
1966         blob.cUnusedBits = bits[i].cUnusedBits;
1967         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1968          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1969         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1970         if (buf)
1971         {
1972             ok(bufSize == bits[i].encoded[1] + 2,
1973              "Got unexpected size %d, expected %d\n", bufSize,
1974              bits[i].encoded[1] + 2);
1975             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1976              "Unexpected value\n");
1977             LocalFree(buf);
1978         }
1979     }
1980 }
1981
1982 static void test_decodeBits(DWORD dwEncoding)
1983 {
1984     static const BYTE ber[] = "\x03\x02\x01\xff";
1985     static const BYTE berDecoded = 0xfe;
1986     DWORD i;
1987     BOOL ret;
1988     BYTE *buf = NULL;
1989     DWORD bufSize = 0;
1990
1991     /* normal cases */
1992     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1993     {
1994         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1995          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1996          &bufSize);
1997         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1998         if (buf)
1999         {
2000             CRYPT_BIT_BLOB *blob;
2001
2002             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2003                "Got unexpected size %d\n", bufSize);
2004             blob = (CRYPT_BIT_BLOB *)buf;
2005             ok(blob->cbData == bits[i].cbDecoded,
2006              "Got unexpected length %d, expected %d\n", blob->cbData,
2007              bits[i].cbDecoded);
2008             if (blob->cbData && bits[i].cbDecoded)
2009                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2010                  "Unexpected value\n");
2011             LocalFree(buf);
2012         }
2013     }
2014     /* special case: check that something that's valid in BER but not in DER
2015      * decodes successfully
2016      */
2017     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2018      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2019     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2020     if (buf)
2021     {
2022         CRYPT_BIT_BLOB *blob;
2023
2024         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2025            "Got unexpected size %d\n", bufSize);
2026         blob = (CRYPT_BIT_BLOB *)buf;
2027         ok(blob->cbData == sizeof(berDecoded),
2028            "Got unexpected length %d\n", blob->cbData);
2029         if (blob->cbData)
2030             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2031         LocalFree(buf);
2032     }
2033 }
2034
2035 struct Constraints2
2036 {
2037     CERT_BASIC_CONSTRAINTS2_INFO info;
2038     const BYTE *encoded;
2039 };
2040
2041 static const unsigned char bin59[] = { 0x30,0x00 };
2042 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2043 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2044 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2045 static const struct Constraints2 constraints2[] = {
2046  /* empty constraints */
2047  { { FALSE, FALSE, 0}, bin59 },
2048  /* can be a CA */
2049  { { TRUE,  FALSE, 0}, bin60 },
2050  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2051   * but that's not the case
2052   */
2053  { { FALSE, TRUE,  0}, bin61 },
2054  /* can be a CA and has path length constraints set */
2055  { { TRUE,  TRUE,  1}, bin62 },
2056 };
2057
2058 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2059 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2060  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2061  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2062  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2063 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2064  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2065  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2066  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2067  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2068
2069 static void test_encodeBasicConstraints(DWORD dwEncoding)
2070 {
2071     DWORD i, bufSize = 0;
2072     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2073     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2074      (LPBYTE)encodedDomainName };
2075     BOOL ret;
2076     BYTE *buf = NULL;
2077
2078     /* First test with the simpler info2 */
2079     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2080     {
2081         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2082          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2083          &bufSize);
2084         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2085         if (buf)
2086         {
2087             ok(bufSize == constraints2[i].encoded[1] + 2,
2088              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2089              bufSize);
2090             ok(!memcmp(buf, constraints2[i].encoded,
2091              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2092             LocalFree(buf);
2093         }
2094     }
2095     /* Now test with more complex basic constraints */
2096     info.SubjectType.cbData = 0;
2097     info.fPathLenConstraint = FALSE;
2098     info.cSubtreesConstraint = 0;
2099     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2100      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2101     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2102     if (buf)
2103     {
2104         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2105         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2106          "Unexpected value\n");
2107         LocalFree(buf);
2108     }
2109     /* None of the certs I examined had any subtree constraint, but I test one
2110      * anyway just in case.
2111      */
2112     info.cSubtreesConstraint = 1;
2113     info.rgSubtreesConstraint = &nameBlob;
2114     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2115      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2116     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2117     if (buf)
2118     {
2119         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2120         ok(!memcmp(buf, constraintWithDomainName,
2121          sizeof(constraintWithDomainName)), "Unexpected value\n");
2122         LocalFree(buf);
2123     }
2124     /* FIXME: test encoding with subject type. */
2125 }
2126
2127 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2128
2129 static void test_decodeBasicConstraints(DWORD dwEncoding)
2130 {
2131     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2132      0xff };
2133     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2134     DWORD i;
2135     BOOL ret;
2136     BYTE *buf = NULL;
2137     DWORD bufSize = 0;
2138
2139     /* First test with simpler info2 */
2140     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2141     {
2142         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2143          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2144          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2145         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2146          GetLastError());
2147         if (buf)
2148         {
2149             CERT_BASIC_CONSTRAINTS2_INFO *info =
2150              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2151
2152             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2153              "Unexpected value for item %d\n", i);
2154             LocalFree(buf);
2155         }
2156     }
2157     /* Check with the order of encoded elements inverted */
2158     buf = (PBYTE)1;
2159     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2160      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2161      &bufSize);
2162     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2163      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2164      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2165      GetLastError());
2166     ok(!buf, "Expected buf to be set to NULL\n");
2167     /* Check with a non-DER bool */
2168     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2169      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2170      (BYTE *)&buf, &bufSize);
2171     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2172     if (buf)
2173     {
2174         CERT_BASIC_CONSTRAINTS2_INFO *info =
2175          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2176
2177         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2178         LocalFree(buf);
2179     }
2180     /* Check with a non-basic constraints value */
2181     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2182      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2183      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2184     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2185      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2186      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2187      GetLastError());
2188     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2189     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2190      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2191      (BYTE *)&buf, &bufSize);
2192     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2193     if (buf)
2194     {
2195         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2196
2197         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2198         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2199         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2200         LocalFree(buf);
2201     }
2202     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2203      constraintWithDomainName, sizeof(constraintWithDomainName),
2204      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2205     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2206     if (buf)
2207     {
2208         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2209
2210         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2211         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2212         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2213         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2214         {
2215             ok(info->rgSubtreesConstraint[0].cbData ==
2216              sizeof(encodedDomainName), "Wrong size %d\n",
2217              info->rgSubtreesConstraint[0].cbData);
2218             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2219              sizeof(encodedDomainName)), "Unexpected value\n");
2220         }
2221         LocalFree(buf);
2222     }
2223 }
2224
2225 /* These are terrible public keys of course, I'm just testing encoding */
2226 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2227 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2228 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2229 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2230 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2231 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2232 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2233 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2234
2235 struct EncodedRSAPubKey
2236 {
2237     const BYTE *modulus;
2238     size_t modulusLen;
2239     const BYTE *encoded;
2240     size_t decodedModulusLen;
2241 };
2242
2243 struct EncodedRSAPubKey rsaPubKeys[] = {
2244     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2245     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2246     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2247     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2248 };
2249
2250 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2251 {
2252     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2253     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2254     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2255     BOOL ret;
2256     BYTE *buf = NULL;
2257     DWORD bufSize = 0, i;
2258
2259     /* Try with a bogus blob type */
2260     hdr->bType = 2;
2261     hdr->bVersion = CUR_BLOB_VERSION;
2262     hdr->reserved = 0;
2263     hdr->aiKeyAlg = CALG_RSA_KEYX;
2264     rsaPubKey->magic = 0x31415352;
2265     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2266     rsaPubKey->pubexp = 65537;
2267     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2268      sizeof(modulus1));
2269
2270     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2271      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2272      &bufSize);
2273     ok(!ret && GetLastError() == E_INVALIDARG,
2274      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2275     /* Now with a bogus reserved field */
2276     hdr->bType = PUBLICKEYBLOB;
2277     hdr->reserved = 1;
2278     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2279      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2280      &bufSize);
2281     if (buf)
2282     {
2283         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2284          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2285         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2286         LocalFree(buf);
2287     }
2288     /* Now with a bogus blob version */
2289     hdr->reserved = 0;
2290     hdr->bVersion = 0;
2291     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2292      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2293      &bufSize);
2294     if (buf)
2295     {
2296         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2297          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2298         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2299         LocalFree(buf);
2300     }
2301     /* And with a bogus alg ID */
2302     hdr->bVersion = CUR_BLOB_VERSION;
2303     hdr->aiKeyAlg = CALG_DES;
2304     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2305      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2306      &bufSize);
2307     if (buf)
2308     {
2309         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2310          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2311         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2312         LocalFree(buf);
2313     }
2314     /* Check a couple of RSA-related OIDs */
2315     hdr->aiKeyAlg = CALG_RSA_KEYX;
2316     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2317      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2318     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2319      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2320     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2321      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2322     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2323      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2324     /* Finally, all valid */
2325     hdr->aiKeyAlg = CALG_RSA_KEYX;
2326     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2327     {
2328         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2329          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2330         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2331          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2332         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2333         if (buf)
2334         {
2335             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2336              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2337              bufSize);
2338             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2339              "Unexpected value\n");
2340             LocalFree(buf);
2341         }
2342     }
2343 }
2344
2345 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2346 {
2347     DWORD i;
2348     LPBYTE buf = NULL;
2349     DWORD bufSize = 0;
2350     BOOL ret;
2351
2352     /* Try with a bad length */
2353     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2354      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2355      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2356     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2357      "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2358     /* Try with a couple of RSA-related OIDs */
2359     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2360      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2361      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2362     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2363      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2364     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2365      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2366      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2367     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2368      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2369     /* Now try success cases */
2370     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2371     {
2372         bufSize = 0;
2373         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2374          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2375          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2376         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2377         if (buf)
2378         {
2379             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2380             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2381
2382             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2383              rsaPubKeys[i].decodedModulusLen,
2384              "Wrong size %d\n", bufSize);
2385             ok(hdr->bType == PUBLICKEYBLOB,
2386              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2387              hdr->bType);
2388             ok(hdr->bVersion == CUR_BLOB_VERSION,
2389              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2390              CUR_BLOB_VERSION, hdr->bVersion);
2391             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2392              hdr->reserved);
2393             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2394              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2395             ok(rsaPubKey->magic == 0x31415352,
2396              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2397             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2398              "Wrong bit len %d\n", rsaPubKey->bitlen);
2399             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2400              rsaPubKey->pubexp);
2401             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2402              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2403              "Unexpected modulus\n");
2404             LocalFree(buf);
2405         }
2406     }
2407 }
2408
2409 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2410  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2411  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2412
2413 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2414  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2415  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2416  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2417
2418 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2419 {
2420     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2421     CRYPT_SEQUENCE_OF_ANY seq;
2422     DWORD i;
2423     BOOL ret;
2424     BYTE *buf = NULL;
2425     DWORD bufSize = 0;
2426
2427     /* Encode a homogeneous sequence */
2428     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2429     {
2430         blobs[i].cbData = ints[i].encoded[1] + 2;
2431         blobs[i].pbData = (BYTE *)ints[i].encoded;
2432     }
2433     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2434     seq.rgValue = blobs;
2435
2436     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2437      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2438     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2439     if (buf)
2440     {
2441         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2442         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2443         LocalFree(buf);
2444     }
2445     /* Change the type of the first element in the sequence, and give it
2446      * another go
2447      */
2448     blobs[0].cbData = times[0].encodedTime[1] + 2;
2449     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2450     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2451      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2452     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2453     if (buf)
2454     {
2455         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2456         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2457          "Unexpected value\n");
2458         LocalFree(buf);
2459     }
2460 }
2461
2462 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2463 {
2464     BOOL ret;
2465     BYTE *buf = NULL;
2466     DWORD bufSize = 0;
2467
2468     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2469      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2470     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2471     if (buf)
2472     {
2473         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2474         DWORD i;
2475
2476         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2477          "Wrong elements %d\n", seq->cValue);
2478         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2479         {
2480             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2481              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2482              seq->rgValue[i].cbData);
2483             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2484              ints[i].encoded[1] + 2), "Unexpected value\n");
2485         }
2486         LocalFree(buf);
2487     }
2488     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2489      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2490      &bufSize);
2491     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2492     if (buf)
2493     {
2494         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2495
2496         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2497          "Wrong elements %d\n", seq->cValue);
2498         /* Just check the first element since it's all that changed */
2499         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2500          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2501          seq->rgValue[0].cbData);
2502         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2503          times[0].encodedTime[1] + 2), "Unexpected value\n");
2504         LocalFree(buf);
2505     }
2506 }
2507
2508 struct encodedExtensions
2509 {
2510     CERT_EXTENSIONS exts;
2511     const BYTE *encoded;
2512 };
2513
2514 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2515 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2516 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2517 static CERT_EXTENSION criticalExt =
2518  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2519 static CERT_EXTENSION nonCriticalExt =
2520  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2521
2522 static const BYTE ext0[] = { 0x30,0x00 };
2523 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2524                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2525 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2526                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2527
2528 static const struct encodedExtensions exts[] = {
2529  { { 0, NULL }, ext0 },
2530  { { 1, &criticalExt }, ext1 },
2531  { { 1, &nonCriticalExt }, ext2 },
2532 };
2533
2534 static void test_encodeExtensions(DWORD dwEncoding)
2535 {
2536     DWORD i;
2537
2538     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2539     {
2540         BOOL ret;
2541         BYTE *buf = NULL;
2542         DWORD bufSize = 0;
2543
2544         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2545          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2546         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2547         if (buf)
2548         {
2549             ok(bufSize == exts[i].encoded[1] + 2,
2550              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2551             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2552              "Unexpected value\n");
2553             LocalFree(buf);
2554         }
2555     }
2556 }
2557
2558 static void test_decodeExtensions(DWORD dwEncoding)
2559 {
2560     DWORD i;
2561
2562     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2563     {
2564         BOOL ret;
2565         BYTE *buf = NULL;
2566         DWORD bufSize = 0;
2567
2568         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2569          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2570          NULL, (BYTE *)&buf, &bufSize);
2571         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2572         if (buf)
2573         {
2574             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2575             DWORD j;
2576
2577             ok(ext->cExtension == exts[i].exts.cExtension,
2578              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2579              ext->cExtension);
2580             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2581             {
2582                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2583                  exts[i].exts.rgExtension[j].pszObjId),
2584                  "Expected OID %s, got %s\n",
2585                  exts[i].exts.rgExtension[j].pszObjId,
2586                  ext->rgExtension[j].pszObjId);
2587                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2588                  exts[i].exts.rgExtension[j].Value.pbData,
2589                  exts[i].exts.rgExtension[j].Value.cbData),
2590                  "Unexpected value\n");
2591             }
2592             LocalFree(buf);
2593         }
2594     }
2595 }
2596
2597 /* MS encodes public key info with a NULL if the algorithm identifier's
2598  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2599  * it encodes them by omitting the algorithm parameters.  This latter approach
2600  * seems more correct, so accept either form.
2601  */
2602 struct encodedPublicKey
2603 {
2604     CERT_PUBLIC_KEY_INFO info;
2605     const BYTE *encoded;
2606     const BYTE *encodedNoNull;
2607     CERT_PUBLIC_KEY_INFO decoded;
2608 };
2609
2610 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2611  0xe, 0xf };
2612 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2613
2614 static const unsigned char bin64[] = {
2615     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2616 static const unsigned char bin65[] = {
2617     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2618 static const unsigned char bin66[] = {
2619     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2620 static const unsigned char bin67[] = {
2621     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2622 static const unsigned char bin68[] = {
2623     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2624     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2625 static const unsigned char bin69[] = {
2626     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2627     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2628 static const unsigned char bin70[] = {
2629     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2630     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2631     0x0f};
2632 static const unsigned char bin71[] = {
2633     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2634     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2635     0x0f};
2636 static unsigned char bin72[] = { 0x05,0x00};
2637
2638 static CHAR oid_bogus[] = "1.2.3",
2639             oid_rsa[]   = szOID_RSA;
2640
2641 static const struct encodedPublicKey pubKeys[] = {
2642  /* with a bogus OID */
2643  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2644   bin64, bin65,
2645   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2646  /* some normal keys */
2647  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2648   bin66, bin67,
2649   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2650  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2651   bin68, bin69,
2652   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2653  /* with add'l parameters--note they must be DER-encoded */
2654  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2655   (BYTE *)aKey, 0 } },
2656   bin70, bin71,
2657   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2658   (BYTE *)aKey, 0 } } },
2659 };
2660
2661 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2662 {
2663     DWORD i;
2664
2665     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2666     {
2667         BOOL ret;
2668         BYTE *buf = NULL;
2669         DWORD bufSize = 0;
2670
2671         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2672          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2673          &bufSize);
2674         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2675         if (buf)
2676         {
2677             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2678              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2679              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2680              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2681             if (bufSize == pubKeys[i].encoded[1] + 2)
2682                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2683                  "Unexpected value\n");
2684             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2685                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2686                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2687             LocalFree(buf);
2688         }
2689     }
2690 }
2691
2692 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2693  const CERT_PUBLIC_KEY_INFO *got)
2694 {
2695     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2696      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2697      got->Algorithm.pszObjId);
2698     ok(expected->Algorithm.Parameters.cbData ==
2699      got->Algorithm.Parameters.cbData,
2700      "Expected parameters of %d bytes, got %d\n",
2701      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2702     if (expected->Algorithm.Parameters.cbData)
2703         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2704          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2705          "Unexpected algorithm parameters\n");
2706     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2707      "Expected public key of %d bytes, got %d\n",
2708      expected->PublicKey.cbData, got->PublicKey.cbData);
2709     if (expected->PublicKey.cbData)
2710         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2711          got->PublicKey.cbData), "Unexpected public key value\n");
2712 }
2713
2714 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2715 {
2716     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2717      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2718      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2719      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2720     DWORD i;
2721     BOOL ret;
2722     BYTE *buf = NULL;
2723     DWORD bufSize = 0;
2724
2725     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2726     {
2727         /* The NULL form decodes to the decoded member */
2728         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2729          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2730          NULL, (BYTE *)&buf, &bufSize);
2731         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2732         if (buf)
2733         {
2734             comparePublicKeyInfo(&pubKeys[i].decoded,
2735              (CERT_PUBLIC_KEY_INFO *)buf);
2736             LocalFree(buf);
2737         }
2738         /* The non-NULL form decodes to the original */
2739         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2740          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2741          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2742         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2743         if (buf)
2744         {
2745             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2746             LocalFree(buf);
2747         }
2748     }
2749     /* Test with bogus (not valid DER) parameters */
2750     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2751      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2752      NULL, (BYTE *)&buf, &bufSize);
2753     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2754      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2755 }
2756
2757 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2758  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2759  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2760  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2761  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2762 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2763  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2764  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2765  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2766  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2767 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2768  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2769  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2770  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2771  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2772 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2773  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2774  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2775  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2776  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2777  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2778  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2779 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2780  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2781  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2782  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2783  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2784  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2785  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2786 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2787  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2788  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2789  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2790  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2791  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2792  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2793  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2794  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2795  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2796 static const BYTE v1CertWithPubKey[] = {
2797 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2798 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2799 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2800 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2801 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2802 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2803 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2804 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2805 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2806 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2807 0x01,0x01 };
2808 static const BYTE v1CertWithPubKeyNoNull[] = {
2809 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2810 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2811 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2812 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2813 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2814 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2815 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2816 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2817 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2818 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2819 static const BYTE v1CertWithSubjectKeyId[] = {
2820 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2821 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2822 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2823 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2824 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2825 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2826 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2827 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2828 0x4c,0x61,0x6e,0x67,0x00 };
2829
2830 static const BYTE serialNum[] = { 0x01 };
2831
2832 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2833 {
2834     BOOL ret;
2835     BYTE *buf = NULL;
2836     DWORD size = 0;
2837     CERT_INFO info = { 0 };
2838     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2839     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2840     CERT_EXTENSION ext;
2841
2842     if (0)
2843     {
2844         /* Test with NULL pvStructInfo (crashes on win9x) */
2845         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2846          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2847         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2848          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2849     }
2850     /* Test with a V1 cert */
2851     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2852      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2853     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2854     if (buf)
2855     {
2856         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2857          v1Cert[1] + 2, size);
2858         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2859         LocalFree(buf);
2860     }
2861     /* Test v2 cert */
2862     info.dwVersion = CERT_V2;
2863     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2864      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2865     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2866     if (buf)
2867     {
2868         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2869         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2870         LocalFree(buf);
2871     }
2872     /* Test v3 cert */
2873     info.dwVersion = CERT_V3;
2874     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2875      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2876     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2877     if (buf)
2878     {
2879         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2880         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2881         LocalFree(buf);
2882     }
2883     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2884      * API doesn't prevent it)
2885      */
2886     info.dwVersion = CERT_V1;
2887     info.cExtension = 1;
2888     info.rgExtension = &criticalExt;
2889     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2890      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2891     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2892     if (buf)
2893     {
2894         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2895         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2896         LocalFree(buf);
2897     }
2898     /* test v1 cert with a serial number */
2899     info.SerialNumber.cbData = sizeof(serialNum);
2900     info.SerialNumber.pbData = (BYTE *)serialNum;
2901     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2902      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2903     if (buf)
2904     {
2905         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2906         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2907         LocalFree(buf);
2908     }
2909     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2910     info.Issuer.cbData = sizeof(encodedCommonName);
2911     info.Issuer.pbData = (BYTE *)encodedCommonName;
2912     info.Subject.cbData = sizeof(encodedCommonName);
2913     info.Subject.pbData = (BYTE *)encodedCommonName;
2914     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2915      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2916     if (buf)
2917     {
2918         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2919         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2920         LocalFree(buf);
2921     }
2922     /* Add a public key */
2923     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2924     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2925     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2926     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2927      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2928     if (buf)
2929     {
2930         ok(size == sizeof(v1CertWithPubKey) ||
2931          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2932         if (size == sizeof(v1CertWithPubKey))
2933             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2934         else if (size == sizeof(v1CertWithPubKeyNoNull))
2935             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2936              "Got unexpected value\n");
2937         LocalFree(buf);
2938     }
2939     /* Remove the public key, and add a subject key identifier extension */
2940     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2941     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2942     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2943     ext.pszObjId = oid_subject_key_identifier;
2944     ext.fCritical = FALSE;
2945     ext.Value.cbData = sizeof(octetCommonNameValue);
2946     ext.Value.pbData = (BYTE *)octetCommonNameValue;
2947     info.cExtension = 1;
2948     info.rgExtension = &ext;
2949     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2950      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2951     if (buf)
2952     {
2953         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2954         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2955         LocalFree(buf);
2956     }
2957 }
2958
2959 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2960 {
2961     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2962      v1CertWithConstraints, v1CertWithSerial };
2963     BOOL ret;
2964     BYTE *buf = NULL;
2965     DWORD size = 0, i;
2966
2967     /* Test with NULL pbEncoded */
2968     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2969      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2970     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2971      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2972     if (0)
2973     {
2974         /* Crashes on win9x */
2975         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2976          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2977         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2978          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2979     }
2980     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2981      * minimum a cert must have a non-zero serial number, an issuer, and a
2982      * subject.
2983      */
2984     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2985     {
2986         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2987          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2988          (BYTE *)&buf, &size);
2989         ok(!ret, "Expected failure\n");
2990     }
2991     /* Now check with serial number, subject and issuer specified */
2992     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2993      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2994     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2995     if (buf)
2996     {
2997         CERT_INFO *info = (CERT_INFO *)buf;
2998
2999         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3000         ok(info->SerialNumber.cbData == 1,
3001          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3002         ok(*info->SerialNumber.pbData == *serialNum,
3003          "Expected serial number %d, got %d\n", *serialNum,
3004          *info->SerialNumber.pbData);
3005         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3006          "Wrong size %d\n", info->Issuer.cbData);
3007         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3008          "Unexpected issuer\n");
3009         ok(info->Subject.cbData == sizeof(encodedCommonName),
3010          "Wrong size %d\n", info->Subject.cbData);
3011         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3012          info->Subject.cbData), "Unexpected subject\n");
3013         LocalFree(buf);
3014     }
3015     /* Check again with pub key specified */
3016     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3017      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3018      (BYTE *)&buf, &size);
3019     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3020     if (buf)
3021     {
3022         CERT_INFO *info = (CERT_INFO *)buf;
3023
3024         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3025         ok(info->SerialNumber.cbData == 1,
3026          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3027         ok(*info->SerialNumber.pbData == *serialNum,
3028          "Expected serial number %d, got %d\n", *serialNum,
3029          *info->SerialNumber.pbData);
3030         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3031          "Wrong size %d\n", info->Issuer.cbData);
3032         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3033          "Unexpected issuer\n");
3034         ok(info->Subject.cbData == sizeof(encodedCommonName),
3035          "Wrong size %d\n", info->Subject.cbData);
3036         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3037          info->Subject.cbData), "Unexpected subject\n");
3038         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3039          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3040          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3041         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3042          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3043         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3044          sizeof(aKey)), "Unexpected public key\n");
3045         LocalFree(buf);
3046     }
3047 }
3048
3049 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3050  0xe, 0xf };
3051
3052 static const BYTE signedBigCert[] = {
3053  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3054  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3055  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3056  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3057  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3058  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3059  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3060  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3061  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3062  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3063  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3064  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3065
3066 static void test_encodeCert(DWORD dwEncoding)
3067 {
3068     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3069      * also that bigCert is a NULL-terminated string, so don't count its
3070      * last byte (otherwise the signed cert won't decode.)
3071      */
3072     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3073      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3074     BOOL ret;
3075     BYTE *buf = NULL;
3076     DWORD bufSize = 0;
3077
3078     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3079      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
3080     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3081     if (buf)
3082     {
3083         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3084         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3085         LocalFree(buf);
3086     }
3087 }
3088
3089 static void test_decodeCert(DWORD dwEncoding)
3090 {
3091     BOOL ret;
3092     BYTE *buf = NULL;
3093     DWORD size = 0;
3094
3095     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3096      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3097     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3098     if (buf)
3099     {
3100         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3101
3102         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3103          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3104         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3105          "Unexpected cert\n");
3106         ok(info->Signature.cbData == sizeof(hash),
3107          "Wrong signature size %d\n", info->Signature.cbData);
3108         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3109          "Unexpected signature\n");
3110         LocalFree(buf);
3111     }
3112     /* A signed cert decodes as a CERT_INFO too */
3113     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3114      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3115     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3116     if (buf)
3117     {
3118         CERT_INFO *info = (CERT_INFO *)buf;
3119
3120         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3121         ok(info->SerialNumber.cbData == 1,
3122          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3123         ok(*info->SerialNumber.pbData == *serialNum,
3124          "Expected serial number %d, got %d\n", *serialNum,
3125          *info->SerialNumber.pbData);
3126         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3127          "Wrong size %d\n", info->Issuer.cbData);
3128         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3129          "Unexpected issuer\n");
3130         ok(info->Subject.cbData == sizeof(encodedCommonName),
3131          "Wrong size %d\n", info->Subject.cbData);
3132         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3133          info->Subject.cbData), "Unexpected subject\n");
3134         LocalFree(buf);
3135     }
3136 }
3137
3138 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3139 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3140  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3141  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3142 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3143  0x00, 0x03 };
3144 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3145  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3146  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3147 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3148  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3149  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3150  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3151  0x2e, 0x6f, 0x72, 0x67 };
3152 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3153  CRL_REASON_AFFILIATION_CHANGED;
3154
3155 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3156 {
3157     CRL_DIST_POINTS_INFO info = { 0 };
3158     CRL_DIST_POINT point = { { 0 } };
3159     CERT_ALT_NAME_ENTRY entry = { 0 };
3160     BOOL ret;
3161     BYTE *buf = NULL;
3162     DWORD size = 0;
3163
3164     /* Test with an empty info */
3165     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3166      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3167     ok(!ret && GetLastError() == E_INVALIDARG,
3168      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3169     /* Test with one empty dist point */
3170     info.cDistPoint = 1;
3171     info.rgDistPoint = &point;
3172     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3173      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3174     if (buf)
3175     {
3176         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3177         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3178         LocalFree(buf);
3179     }
3180     /* A dist point with an invalid name */
3181     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3182     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3183     U(entry).pwszURL = (LPWSTR)nihongoURL;
3184     U(point.DistPointName).FullName.cAltEntry = 1;
3185     U(point.DistPointName).FullName.rgAltEntry = &entry;
3186     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3187      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3188     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3189      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3190     /* The first invalid character is at index 7 */
3191     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3192      "Expected invalid char at index 7, got %d\n",
3193      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3194     /* A dist point with (just) a valid name */
3195     U(entry).pwszURL = (LPWSTR)url;
3196     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3197      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3198     if (buf)
3199     {
3200         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3201         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3202         LocalFree(buf);
3203     }
3204     /* A dist point with (just) reason flags */
3205     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3206     point.ReasonFlags.cbData = sizeof(crlReason);
3207     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3208     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3209      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3210     if (buf)
3211     {
3212         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3213         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3214         LocalFree(buf);
3215     }
3216     /* A dist point with just an issuer */
3217     point.ReasonFlags.cbData = 0;
3218     point.CRLIssuer.cAltEntry = 1;
3219     point.CRLIssuer.rgAltEntry = &entry;
3220     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3221      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3222     if (buf)
3223     {
3224         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3225         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3226         LocalFree(buf);
3227     }
3228     /* A dist point with both a name and an issuer */
3229     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3230     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3231      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3232     if (buf)
3233     {
3234         ok(size == sizeof(distPointWithUrlAndIssuer),
3235          "Wrong size %d\n", size);
3236         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3237         LocalFree(buf);
3238     }
3239 }
3240
3241 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3242 {
3243     BOOL ret;
3244     BYTE *buf = NULL;
3245     DWORD size = 0;
3246     PCRL_DIST_POINTS_INFO info;
3247     PCRL_DIST_POINT point;
3248     PCERT_ALT_NAME_ENTRY entry;
3249
3250     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3251      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3252      (BYTE *)&buf, &size);
3253     if (ret)
3254     {
3255         info = (PCRL_DIST_POINTS_INFO)buf;
3256         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3257          "Wrong size %d\n", size);
3258         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3259          info->cDistPoint);
3260         point = info->rgDistPoint;
3261         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3262          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3263          point->DistPointName.dwDistPointNameChoice);
3264         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3265         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3266         LocalFree(buf);
3267     }
3268     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3269      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3270      (BYTE *)&buf, &size);
3271     if (ret)
3272     {
3273         info = (PCRL_DIST_POINTS_INFO)buf;
3274         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3275          "Wrong size %d\n", size);
3276         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3277          info->cDistPoint);
3278         point = info->rgDistPoint;
3279         ok(point->DistPointName.dwDistPointNameChoice ==
3280          CRL_DIST_POINT_FULL_NAME,
3281          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3282          point->DistPointName.dwDistPointNameChoice);
3283         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3284          "Expected 1 name entry, got %d\n",
3285          U(point->DistPointName).FullName.cAltEntry);
3286         entry = U(point->DistPointName).FullName.rgAltEntry;
3287         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3288          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3289         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
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      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3296      NULL, (BYTE *)&buf, &size);
3297     if (ret)
3298     {
3299         info = (PCRL_DIST_POINTS_INFO)buf;
3300         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3301          "Wrong size %d\n", size);
3302         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3303          info->cDistPoint);
3304         point = info->rgDistPoint;
3305         ok(point->DistPointName.dwDistPointNameChoice ==
3306          CRL_DIST_POINT_NO_NAME,
3307          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3308          point->DistPointName.dwDistPointNameChoice);
3309         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3310          "Expected reason length\n");
3311         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3312          "Unexpected reason\n");
3313         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3314         LocalFree(buf);
3315     }
3316     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3317      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3318      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3319     if (ret)
3320     {
3321         info = (PCRL_DIST_POINTS_INFO)buf;
3322         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3323          "Wrong size %d\n", size);
3324         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3325          info->cDistPoint);
3326         point = info->rgDistPoint;
3327         ok(point->DistPointName.dwDistPointNameChoice ==
3328          CRL_DIST_POINT_FULL_NAME,
3329          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3330          point->DistPointName.dwDistPointNameChoice);
3331         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3332          "Expected 1 name entry, got %d\n",
3333          U(point->DistPointName).FullName.cAltEntry);
3334         entry = U(point->DistPointName).FullName.rgAltEntry;
3335         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3336          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3337         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3338         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3339         ok(point->CRLIssuer.cAltEntry == 1,
3340          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3341         entry = point->CRLIssuer.rgAltEntry;
3342         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3343          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3344         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3345         LocalFree(buf);
3346     }
3347 }
3348
3349 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3350 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3351 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3352  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3353  0x67 };
3354
3355 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3356 {
3357     BOOL ret;
3358     BYTE *buf = NULL;
3359     DWORD size = 0;
3360     CRL_ISSUING_DIST_POINT point = { { 0 } };
3361     CERT_ALT_NAME_ENTRY entry;
3362
3363     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3364      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3365     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3366     {
3367         skip("no X509_ISSUING_DIST_POINT encode support\n");
3368         return;
3369     }
3370     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3371      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3372     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3373      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3374     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3375     if (buf)
3376     {
3377         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3378         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3379         LocalFree(buf);
3380     }
3381     /* nonsensical flags */
3382     point.fOnlyContainsUserCerts = TRUE;
3383     point.fOnlyContainsCACerts = TRUE;
3384     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3385      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3386     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3387     if (buf)
3388     {
3389         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3390         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3391         LocalFree(buf);
3392     }
3393     /* unimplemented name type */
3394     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3395     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3396     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3397      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3398     ok(!ret && GetLastError() == E_INVALIDARG,
3399      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3400     /* empty name */
3401     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3402     U(point.DistPointName).FullName.cAltEntry = 0;
3403     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3404      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3405     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3406     if (buf)
3407     {
3408         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3409         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3410         LocalFree(buf);
3411     }
3412     /* name with URL entry */
3413     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3414     U(entry).pwszURL = (LPWSTR)url;
3415     U(point.DistPointName).FullName.cAltEntry = 1;
3416     U(point.DistPointName).FullName.rgAltEntry = &entry;
3417     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3418      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3419     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3420     if (buf)
3421     {
3422         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3423         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3424         LocalFree(buf);
3425     }
3426 }
3427
3428 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3429  const CERT_ALT_NAME_ENTRY *got)
3430 {
3431     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3432      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3433      got->dwAltNameChoice);
3434     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3435     {
3436         switch (got->dwAltNameChoice)
3437         {
3438         case CERT_ALT_NAME_RFC822_NAME:
3439         case CERT_ALT_NAME_DNS_NAME:
3440         case CERT_ALT_NAME_EDI_PARTY_NAME:
3441         case CERT_ALT_NAME_URL:
3442         case CERT_ALT_NAME_REGISTERED_ID:
3443             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3444              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3445              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3446              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3447              "Unexpected name\n");
3448             break;
3449         case CERT_ALT_NAME_X400_ADDRESS:
3450         case CERT_ALT_NAME_DIRECTORY_NAME:
3451         case CERT_ALT_NAME_IP_ADDRESS:
3452             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3453                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3454             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3455                        U(*got).IPAddress.cbData), "Unexpected value\n");
3456             break;
3457         }
3458     }
3459 }
3460
3461 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3462  const CERT_ALT_NAME_INFO *got)
3463 {
3464     DWORD i;
3465
3466     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3467      expected->cAltEntry, got->cAltEntry);
3468     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3469         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3470 }
3471
3472 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3473  const CRL_DIST_POINT_NAME *got)
3474 {
3475     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3476      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3477     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3478         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3479 }
3480
3481 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3482  const CRL_ISSUING_DIST_POINT *got)
3483 {
3484     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3485     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3486      "Unexpected fOnlyContainsUserCerts\n");
3487     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3488      "Unexpected fOnlyContainsCACerts\n");
3489     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3490      "Unexpected reason flags\n");
3491     ok(got->fIndirectCRL == expected->fIndirectCRL,
3492      "Unexpected fIndirectCRL\n");
3493 }
3494
3495 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3496 {
3497     BOOL ret;
3498     BYTE *buf = NULL;
3499     DWORD size = 0;
3500     CRL_ISSUING_DIST_POINT point = { { 0 } };
3501
3502     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3503      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3504      (BYTE *)&buf, &size);
3505     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3506     {
3507         skip("no X509_ISSUING_DIST_POINT decode support\n");
3508         return;
3509     }
3510     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3511     if (ret)
3512     {
3513         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3514         LocalFree(buf);
3515     }
3516     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3517      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3518      (BYTE *)&buf, &size);
3519     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3520     if (ret)
3521     {
3522         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3523         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3524         LocalFree(buf);
3525     }
3526     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3527      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3528      (BYTE *)&buf, &size);
3529     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3530     if (ret)
3531     {
3532         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3533         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3534         U(point.DistPointName).FullName.cAltEntry = 0;
3535         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3536         LocalFree(buf);
3537     }
3538     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3539      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3540     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3541     if (ret)
3542     {
3543         CERT_ALT_NAME_ENTRY entry;
3544
3545         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3546         U(entry).pwszURL = (LPWSTR)url;
3547         U(point.DistPointName).FullName.cAltEntry = 1;
3548         U(point.DistPointName).FullName.rgAltEntry = &entry;
3549         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3550         LocalFree(buf);
3551     }
3552 }
3553
3554 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3555  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3556  0x30, 0x5a };
3557 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3558  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3559  0x30, 0x30, 0x30, 0x30, 0x5a };
3560 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3561  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3562  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3563  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3564  0x5a };
3565 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3566  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3567  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3568  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3569  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3570  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3571 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3572  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3573  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3574  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3575  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3576  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3577 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3578  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3579  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3580  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3581  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3582  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3583  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3584 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3585  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3586  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3587  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3588  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3589  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3590  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3591 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3592  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3593  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3594  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3595  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3596  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3597  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3598 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3599  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3600  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3601  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3602  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3603  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3604  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3605
3606 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3607 {
3608     BOOL ret;
3609     BYTE *buf = NULL;
3610     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3611     DWORD size = 0;
3612     CRL_INFO info = { 0 };
3613     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3614     CERT_EXTENSION ext;
3615
3616     /* Test with a V1 CRL */
3617     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3618      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3619     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3620     if (buf)
3621     {
3622         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3623         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3624         LocalFree(buf);
3625     }
3626     /* Test v2 CRL */
3627     info.dwVersion = CRL_V2;
3628     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3629      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3630     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3631     if (buf)
3632     {
3633         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3634          v2CRL[1] + 2, size);
3635         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3636         LocalFree(buf);
3637     }
3638     /* v1 CRL with a name */
3639     info.dwVersion = CRL_V1;
3640     info.Issuer.cbData = sizeof(encodedCommonName);
3641     info.Issuer.pbData = (BYTE *)encodedCommonName;
3642     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3643      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3644     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3645     if (buf)
3646     {
3647         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3648         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3649         LocalFree(buf);
3650     }
3651     if (0)
3652     {
3653         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3654         info.cCRLEntry = 1;
3655         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3656          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3657         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3658          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3659     }
3660     /* now set an empty entry */
3661     info.cCRLEntry = 1;
3662     info.rgCRLEntry = &entry;
3663     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3664      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3665     if (buf)
3666     {
3667         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3668          "Wrong size %d\n", size);
3669         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3670          "Got unexpected value\n");
3671         LocalFree(buf);
3672     }
3673     /* an entry with a serial number */
3674     entry.SerialNumber.cbData = sizeof(serialNum);
3675     entry.SerialNumber.pbData = (BYTE *)serialNum;
3676     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3677      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3678     if (buf)
3679     {
3680         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3681          "Wrong size %d\n", size);
3682         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3683          "Got unexpected value\n");
3684         LocalFree(buf);
3685     }
3686     /* an entry with an extension */
3687     entry.cExtension = 1;
3688     entry.rgExtension = &criticalExt;
3689     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3690      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3691     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3692     if (buf)
3693     {
3694         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3695         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3696         LocalFree(buf);
3697     }
3698     /* a CRL with an extension */
3699     entry.cExtension = 0;
3700     info.cExtension = 1;
3701     info.rgExtension = &criticalExt;
3702     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3703      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3704     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3705     if (buf)
3706     {
3707         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3708         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3709         LocalFree(buf);
3710     }
3711     /* a v2 CRL with an extension, this time non-critical */
3712     info.dwVersion = CRL_V2;
3713     info.rgExtension = &nonCriticalExt;
3714     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3715      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3716     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3717     if (buf)
3718     {
3719         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3720         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3721         LocalFree(buf);
3722     }
3723     /* a v2 CRL with an issuing dist point extension */
3724     ext.pszObjId = oid_issuing_dist_point;
3725     ext.fCritical = TRUE;
3726     ext.Value.cbData = sizeof(urlIDP);
3727     ext.Value.pbData = (LPBYTE)urlIDP;
3728     entry.rgExtension = &ext;
3729     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3730      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3731     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3732     if (buf)
3733     {
3734         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3735         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3736         LocalFree(buf);
3737     }
3738 }
3739
3740 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3741  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3742  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3743  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3744  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3745  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3746  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3747  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3748  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3749  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3750  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3751  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3752  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3753  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3754  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3755  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3756  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3757  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3758  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3759  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3760  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3761  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3762  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3763  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3764  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3765  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3766  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3767  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3768  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3769  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3770  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3771  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3772  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3773  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3774  0xcd };
3775 static const BYTE verisignCRLWithLotsOfEntries[] = {
3776 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3777 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3778 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3779 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3780 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3781 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3782 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3783 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3784 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3785 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3786 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3787 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3788 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3789 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3790 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3791 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3792 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3793 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3794 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3795 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3796 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3797 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3798 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3799 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3800 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3801 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3802 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3803 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3804 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3805 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3806 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3807 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3808 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3809 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3810 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3811 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3812 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3813 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3814 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3815 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3816 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3817 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3818 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3819 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3820 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3821 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3822 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3823 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3824 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3825 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3826 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3827 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3828 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3829 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3830 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3831 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3832 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3833 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3834 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3835 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3836 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3837 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3838 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3839 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3840 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3841 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3842 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3843 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3844 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3845 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3846 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3847 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3848 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3849 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3850 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3851 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3852 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3853 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3854 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3855 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3856 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3857 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3858 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3859 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3860 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3861 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3862 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3863 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3864 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3865 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3866 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3867 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3868 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3869 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3870 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3871 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3872 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3873 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3874 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3875 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3876 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3877 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3878 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3879 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3880 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3881 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3882 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3883 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3884 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3885 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3886 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3887 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3888 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3889 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3890 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3891 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3892 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3893 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3894 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3895 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3896 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3897 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3898 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3899 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3900 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3901 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3902 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3903 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3904 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3905 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3906 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3907 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3908 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3909 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3910 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3911 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3912 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3913 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3914 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3915 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3916 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3917 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3918 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3919 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3920 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3921 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3922 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3923 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3924 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3925 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3926 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3927 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3928 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3929 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3930 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3931 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3932 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3933 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3934 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3935 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3936 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3937 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3938 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3939 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3940 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3941 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3942 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3943 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3944 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3945 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3946 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3947 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3948 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3949 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3950 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3951 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3952 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3953 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3954 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3955 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3956 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3957 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3958 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3959 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3960 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3961 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3962 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3963 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3964 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3965 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3966 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3967 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3968 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3969 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3970 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3971 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3972 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3973 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3974 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3975 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3976 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3977 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3978 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3979 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3980 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3981 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3982 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3983 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3984 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3985 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3986 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3987 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3988 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3989 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3990 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3991 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3992 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3993 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3994 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3995 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3996 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3997 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3998 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3999 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4000 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4001 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4002 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4003 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4004 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4005 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4006 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4007 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4008 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4009 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4010 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4011 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4012 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4013 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4014 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4015 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4016 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4017 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4018 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4019 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4020 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4021 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4022 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4023 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4024 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4025 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4026 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4027 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4028 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4029 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4030 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4031 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4032 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4033 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4034 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4035 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4036 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4037 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4038 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4039 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4040 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4041 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4042 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4043 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4044 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4045 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4046 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4047 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4048 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4049 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4050 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4051 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4052 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4053 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4054 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4055 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4056 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4057 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4058 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4059 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4060 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4061 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4062 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4063 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4064 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4065 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4066 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4067 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4068 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4069 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4070 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4071 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4072 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4073 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4074 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4075 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4076 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4077 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4078 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4079 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4080 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4081 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4082 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4083 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4084 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4085 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4086 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4087 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4088 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4089 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4090 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4091 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4092 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4093 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4094 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4095 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4096 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4097 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4098 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4099 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4100 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4101 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4102 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4103 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4104 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4105 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4106 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4107 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4108 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4109 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4110 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4111 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4112 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4113 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4114 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4115 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4116 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4117 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4118 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4119 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4120 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4121 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4122 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4123 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4124 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4125 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4126 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4127 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4128 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4129 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4130 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4131 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4132 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4133 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4134 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4135 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4136 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4137 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4138 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4139 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4140 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4141 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4142 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4143 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4144 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4145 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4146 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4147 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4148 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4149 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4150 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4151 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4152 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4153 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4154 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4155 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4156 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4157 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4158 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4159 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4160 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4161 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4162 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4163 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4164 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4165 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4166 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4167 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4168 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4169 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4170 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4171 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4172 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4173 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4174 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4175 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4176 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4177 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4178 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4179 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4180 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4181 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4182 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4183 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4184 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4185 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4186 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4187 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4188 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4189 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4190 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4191 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4192 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4193 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4194 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4195 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4196 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4197 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4198 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4199 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4200 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4201 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4202 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4203 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4204 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4205 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4206 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4207 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4208 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4209 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4210 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4211 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4212 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4213 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4214 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4215 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4216 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4217 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4218 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4219 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4220 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4221 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4222 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4223 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4224 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4225 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4226 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4227 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4228 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4229 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4230 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4231 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4232 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4233 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4234 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4235 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4236 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4237 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4238 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4239 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4240 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4241 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4242 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4243 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4244 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4245 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4246 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4247 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4248 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4249 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4250 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4251 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4252 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4253 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4254 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4255 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4256 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4257 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4258 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4259 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4260 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4261 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4262 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4263 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4264 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4265 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4266 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4267 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4268 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4269 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4270 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4271 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4272 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4273 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4274 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4275 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4276 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4277 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4278 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4279 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4280 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4281 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4282 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4283 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4284
4285 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4286 {
4287     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4288     BOOL ret;
4289     BYTE *buf = NULL;
4290     DWORD size = 0, i;
4291
4292     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4293     {
4294         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4295          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4296          (BYTE *)&buf, &size);
4297         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4298          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4299     }
4300     /* at a minimum, a CRL must contain an issuer: */
4301     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4302      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4303      (BYTE *)&buf, &size);
4304     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4305     if (buf)
4306     {
4307         CRL_INFO *info = (CRL_INFO *)buf;
4308
4309         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4310         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4311          info->cCRLEntry);
4312         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4313          "Wrong issuer size %d\n", info->Issuer.cbData);
4314         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4315          "Unexpected issuer\n");
4316         LocalFree(buf);
4317     }
4318     /* check decoding with an empty CRL entry */
4319     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4320      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4321      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4322     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4323      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4324     /* with a real CRL entry */
4325     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4326      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4327      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4328     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4329     if (buf)
4330     {
4331         CRL_INFO *info = (CRL_INFO *)buf;
4332         CRL_ENTRY *entry;
4333
4334         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4335         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4336          info->cCRLEntry);
4337         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4338         entry = info->rgCRLEntry;
4339         ok(entry->SerialNumber.cbData == 1,
4340          "Expected serial number size 1, got %d\n",
4341          entry->SerialNumber.cbData);
4342         ok(*entry->SerialNumber.pbData == *serialNum,
4343          "Expected serial number %d, got %d\n", *serialNum,
4344          *entry->SerialNumber.pbData);
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     /* a real CRL from verisign that has extensions */
4352     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4353      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4354      NULL, (BYTE *)&buf, &size);
4355     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4356     if (buf)
4357     {
4358         CRL_INFO *info = (CRL_INFO *)buf;
4359         CRL_ENTRY *entry;
4360
4361         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4362         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4363          info->cCRLEntry);
4364         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4365         entry = info->rgCRLEntry;
4366         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4367          info->cExtension);
4368         LocalFree(buf);
4369     }
4370     /* another real CRL from verisign that has lots of entries */
4371     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4372      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4373      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4374     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4375     if (buf)
4376     {
4377         CRL_INFO *info = (CRL_INFO *)buf;
4378
4379         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4380         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4381          info->cCRLEntry);
4382         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4383          info->cExtension);
4384         LocalFree(buf);
4385     }
4386     /* and finally, with an extension */
4387     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4388      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4389      NULL, (BYTE *)&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 == 1, "Expected 1 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(entry->SerialNumber.cbData == 1,
4402          "Expected serial number size 1, got %d\n",
4403          entry->SerialNumber.cbData);
4404         ok(*entry->SerialNumber.pbData == *serialNum,
4405          "Expected serial number %d, got %d\n", *serialNum,
4406          *entry->SerialNumber.pbData);
4407         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4408          "Wrong issuer size %d\n", info->Issuer.cbData);
4409         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4410          "Unexpected issuer\n");
4411         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4412          info->cExtension);
4413         LocalFree(buf);
4414     }
4415     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4416      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4417      NULL, (BYTE *)&buf, &size);
4418     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4419     if (buf)
4420     {
4421         CRL_INFO *info = (CRL_INFO *)buf;
4422
4423         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4424          info->cExtension);
4425         LocalFree(buf);
4426     }
4427     /* And again, with an issuing dist point */
4428     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4429      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4430      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4431     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4432     if (buf)
4433     {
4434         CRL_INFO *info = (CRL_INFO *)buf;
4435
4436         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4437          info->cExtension);
4438         LocalFree(buf);
4439     }
4440 }
4441
4442 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4443  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4444 static const BYTE encodedUsage[] = {
4445  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4446  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4447  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4448
4449 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4450 {
4451     BOOL ret;
4452     BYTE *buf = NULL;
4453     DWORD size = 0;
4454     CERT_ENHKEY_USAGE usage;
4455
4456     /* Test with empty usage */
4457     usage.cUsageIdentifier = 0;
4458     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4459      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4460     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4461     if (buf)
4462     {
4463         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4464         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4465         LocalFree(buf);
4466     }
4467     /* Test with a few usages */
4468     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4469     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4470     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4471      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4472     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4473     if (buf)
4474     {
4475         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4476         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4477         LocalFree(buf);
4478     }
4479 }
4480
4481 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4482 {
4483     BOOL ret;
4484     LPBYTE buf = NULL;
4485     DWORD size = 0;
4486
4487     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4488      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4489      (BYTE *)&buf, &size);
4490     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4491     if (buf)
4492     {
4493         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4494
4495         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4496          "Wrong size %d\n", size);
4497         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4498          usage->cUsageIdentifier);
4499         LocalFree(buf);
4500     }
4501     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4502      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4503      (BYTE *)&buf, &size);
4504     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4505     if (buf)
4506     {
4507         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4508         DWORD i;
4509
4510         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4511          "Wrong size %d\n", size);
4512         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4513          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4514         for (i = 0; i < usage->cUsageIdentifier; i++)
4515             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4516              "Expected OID %s, got %s\n", keyUsages[i],
4517              usage->rgpszUsageIdentifier[i]);
4518         LocalFree(buf);
4519     }
4520 }
4521
4522 static BYTE keyId[] = { 1,2,3,4 };
4523 static const BYTE authorityKeyIdWithId[] = {
4524  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4525 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4526  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4527  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4528 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4529
4530 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4531 {
4532     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4533     BOOL ret;
4534     BYTE *buf = NULL;
4535     DWORD size = 0;
4536
4537     /* Test with empty id */
4538     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4539      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4540     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4541     if (buf)
4542     {
4543         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4544         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4545         LocalFree(buf);
4546     }
4547     /* With just a key id */
4548     info.KeyId.cbData = sizeof(keyId);
4549     info.KeyId.pbData = keyId;
4550     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4551      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4552     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4553     if (buf)
4554     {
4555         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4556         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4557         LocalFree(buf);
4558     }
4559     /* With just an issuer */
4560     info.KeyId.cbData = 0;
4561     info.CertIssuer.cbData = sizeof(encodedCommonName);
4562     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4563     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4564      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4565     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4566     if (buf)
4567     {
4568         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4569          size);
4570         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4571         LocalFree(buf);
4572     }
4573     /* With just a serial number */
4574     info.CertIssuer.cbData = 0;
4575     info.CertSerialNumber.cbData = sizeof(serialNum);
4576     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4577     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4578      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4579     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4580     if (buf)
4581     {
4582         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4583          size);
4584         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4585         LocalFree(buf);
4586     }
4587 }
4588
4589 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4590 {
4591     BOOL ret;
4592     LPBYTE buf = NULL;
4593     DWORD size = 0;
4594
4595     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4596      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4597      (BYTE *)&buf, &size);
4598     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4599     if (buf)
4600     {
4601         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4602
4603         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4604          size);
4605         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4606         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4607         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4608         LocalFree(buf);
4609     }
4610     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4611      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4612      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4613     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4614     if (buf)
4615     {
4616         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4617
4618         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4619          size);
4620         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4621         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4622          "Unexpected key id\n");
4623         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4624         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4625         LocalFree(buf);
4626     }
4627     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4628      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4629      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4630     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4631     if (buf)
4632     {
4633         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4634
4635         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4636          size);
4637         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4638         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4639          "Unexpected issuer len\n");
4640         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4641          sizeof(encodedCommonName)), "Unexpected issuer\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      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4647      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&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 == 0, "Expected no key id\n");
4656         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4657         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4658          "Unexpected serial number len\n");
4659         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4660          "Unexpected serial number\n");
4661         LocalFree(buf);
4662     }
4663 }
4664
4665 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4666  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4667  0x6f,0x72,0x67 };
4668
4669 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4670 {
4671     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4672     CERT_ALT_NAME_ENTRY entry = { 0 };
4673     BOOL ret;
4674     BYTE *buf = NULL;
4675     DWORD size = 0;
4676
4677     /* Test with empty id */
4678     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4679      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4680     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4681     if (buf)
4682     {
4683         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4684         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4685         LocalFree(buf);
4686     }
4687     /* With just a key id */
4688     info.KeyId.cbData = sizeof(keyId);
4689     info.KeyId.pbData = keyId;
4690     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4691      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4692     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4693     if (buf)
4694     {
4695         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4696          size);
4697         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4698         LocalFree(buf);
4699     }
4700     /* With a bogus issuer name */
4701     info.KeyId.cbData = 0;
4702     info.AuthorityCertIssuer.cAltEntry = 1;
4703     info.AuthorityCertIssuer.rgAltEntry = &entry;
4704     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4705      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4706     ok(!ret && GetLastError() == E_INVALIDARG,
4707      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4708     /* With an issuer name */
4709     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4710     U(entry).pwszURL = (LPWSTR)url;
4711     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4712      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4713     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4714     if (buf)
4715     {
4716         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4717          size);
4718         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4719          "Unexpected value\n");
4720         LocalFree(buf);
4721     }
4722     /* With just a serial number */
4723     info.AuthorityCertIssuer.cAltEntry = 0;
4724     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4725     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4726     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4727      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4728     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4729     if (buf)
4730     {
4731         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4732          size);
4733         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4734         LocalFree(buf);
4735     }
4736 }
4737
4738 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4739 {
4740     BOOL ret;
4741     LPBYTE buf = NULL;
4742     DWORD size = 0;
4743
4744     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4745      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4746      (BYTE *)&buf, &size);
4747     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4748     if (buf)
4749     {
4750         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4751
4752         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4753          size);
4754         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4755         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4756          "Expected no issuer name entries\n");
4757         ok(info->AuthorityCertSerialNumber.cbData == 0,
4758          "Expected no serial number\n");
4759         LocalFree(buf);
4760     }
4761     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4762      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4763      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4764     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4765     if (buf)
4766     {
4767         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4768
4769         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4770          size);
4771         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4772         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4773          "Unexpected key id\n");
4774         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4775          "Expected no issuer name entries\n");
4776         ok(info->AuthorityCertSerialNumber.cbData == 0,
4777          "Expected no serial number\n");
4778         LocalFree(buf);
4779     }
4780     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4781      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4782      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4783     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4784     if (buf)
4785     {
4786         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4787
4788         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4789          size);
4790         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4791         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4792          "Expected 1 issuer entry, got %d\n",
4793          info->AuthorityCertIssuer.cAltEntry);
4794         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4795          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4796          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4797         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4798          url), "Unexpected URL\n");
4799         ok(info->AuthorityCertSerialNumber.cbData == 0,
4800          "Expected no serial number\n");
4801         LocalFree(buf);
4802     }
4803     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4804      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4805      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4806     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4807     if (buf)
4808     {
4809         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4810
4811         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4812          size);
4813         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4814         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4815          "Expected no issuer name entries\n");
4816         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4817          "Unexpected serial number len\n");
4818         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4819          sizeof(serialNum)), "Unexpected serial number\n");
4820         LocalFree(buf);
4821     }
4822 }
4823
4824 static const BYTE authorityInfoAccessWithUrl[] = {
4825 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4826 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4827 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4828 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4829 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4830 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4831
4832 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4833 {
4834     static char oid1[] = "1.2.3";
4835     static char oid2[] = "1.5.6";
4836     BOOL ret;
4837     BYTE *buf = NULL;
4838     DWORD size = 0;
4839     CERT_ACCESS_DESCRIPTION accessDescription[2];
4840     CERT_AUTHORITY_INFO_ACCESS aia;
4841
4842     memset(accessDescription, 0, sizeof(accessDescription));
4843     aia.cAccDescr = 0;
4844     aia.rgAccDescr = NULL;
4845     /* Having no access descriptions is allowed */
4846     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4847      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4848     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4849     if (buf)
4850     {
4851         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4852         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4853         LocalFree(buf);
4854         buf = NULL;
4855     }
4856     /* It can't have an empty access method */
4857     aia.cAccDescr = 1;
4858     aia.rgAccDescr = accessDescription;
4859     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4860      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4861     ok(!ret && GetLastError() == E_INVALIDARG,
4862      "expected E_INVALIDARG, got %08x\n", GetLastError());
4863     /* It can't have an empty location */
4864     accessDescription[0].pszAccessMethod = oid1;
4865     SetLastError(0xdeadbeef);
4866     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4867      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4868     ok(!ret && GetLastError() == E_INVALIDARG,
4869      "expected E_INVALIDARG, got %08x\n", GetLastError());
4870     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4871     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4872     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4873      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4874     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4875     if (buf)
4876     {
4877         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4878          size);
4879         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4880          "unexpected value\n");
4881         LocalFree(buf);
4882         buf = NULL;
4883     }
4884     accessDescription[1].pszAccessMethod = oid2;
4885     accessDescription[1].AccessLocation.dwAltNameChoice =
4886      CERT_ALT_NAME_IP_ADDRESS;
4887     U(accessDescription[1].AccessLocation).IPAddress.cbData =
4888      sizeof(encodedIPAddr);
4889     U(accessDescription[1].AccessLocation).IPAddress.pbData =
4890      (LPBYTE)encodedIPAddr;
4891     aia.cAccDescr = 2;
4892     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4893      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4894     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4895     if (buf)
4896     {
4897         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4898          "unexpected size %d\n", size);
4899         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4900          "unexpected value\n");
4901         LocalFree(buf);
4902         buf = NULL;
4903     }
4904 }
4905
4906 static void compareAuthorityInfoAccess(LPCSTR header,
4907  const CERT_AUTHORITY_INFO_ACCESS *expected,
4908  const CERT_AUTHORITY_INFO_ACCESS *got)
4909 {
4910     DWORD i;
4911
4912     ok(expected->cAccDescr == got->cAccDescr,
4913      "%s: expected %d access descriptions, got %d\n", header,
4914      expected->cAccDescr, got->cAccDescr);
4915     for (i = 0; i < expected->cAccDescr; i++)
4916     {
4917         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4918          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4919          header, i, expected->rgAccDescr[i].pszAccessMethod,
4920          got->rgAccDescr[i].pszAccessMethod);
4921         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4922          &got->rgAccDescr[i].AccessLocation);
4923     }
4924 }
4925
4926 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4927 {
4928     static char oid1[] = "1.2.3";
4929     static char oid2[] = "1.5.6";
4930     BOOL ret;
4931     LPBYTE buf = NULL;
4932     DWORD size = 0;
4933
4934     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4935      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4936      (BYTE *)&buf, &size);
4937     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4938     if (buf)
4939     {
4940         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4941
4942         compareAuthorityInfoAccess("empty AIA", &aia,
4943          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4944         LocalFree(buf);
4945         buf = NULL;
4946     }
4947     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4948      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4949      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4950     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4951     if (buf)
4952     {
4953         CERT_ACCESS_DESCRIPTION accessDescription;
4954         CERT_AUTHORITY_INFO_ACCESS aia;
4955
4956         accessDescription.pszAccessMethod = oid1;
4957         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4958         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
4959         aia.cAccDescr = 1;
4960         aia.rgAccDescr = &accessDescription;
4961         compareAuthorityInfoAccess("AIA with URL", &aia,
4962          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4963         LocalFree(buf);
4964         buf = NULL;
4965     }
4966     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4967      authorityInfoAccessWithUrlAndIPAddr,
4968      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
4969      NULL, (BYTE *)&buf, &size);
4970     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4971     if (buf)
4972     {
4973         CERT_ACCESS_DESCRIPTION accessDescription[2];
4974         CERT_AUTHORITY_INFO_ACCESS aia;
4975
4976         accessDescription[0].pszAccessMethod = oid1;
4977         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4978         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4979         accessDescription[1].pszAccessMethod = oid2;
4980         accessDescription[1].AccessLocation.dwAltNameChoice =
4981          CERT_ALT_NAME_IP_ADDRESS;
4982         U(accessDescription[1].AccessLocation).IPAddress.cbData =
4983          sizeof(encodedIPAddr);
4984         U(accessDescription[1].AccessLocation).IPAddress.pbData =
4985          (LPBYTE)encodedIPAddr;
4986         aia.cAccDescr = 2;
4987         aia.rgAccDescr = accessDescription;
4988         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
4989          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4990         LocalFree(buf);
4991         buf = NULL;
4992     }
4993 }
4994
4995 static const BYTE emptyCTL[] = {
4996 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4997 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4998 static const BYTE emptyCTLWithVersion1[] = {
4999 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5000 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5001 static const BYTE ctlWithUsageIdentifier[] = {
5002 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5003 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5004 static const BYTE ctlWithListIdentifier[] = {
5005 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5006 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5007 static const BYTE ctlWithSequenceNumber[] = {
5008 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5009 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5010 static const BYTE ctlWithThisUpdate[] = {
5011 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5012 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5013 static const BYTE ctlWithThisAndNextUpdate[] = {
5014 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5015 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5016 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5017 static const BYTE ctlWithAlgId[] = {
5018 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5019 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5020 static const BYTE ctlWithBogusEntry[] = {
5021 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5022 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5023 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5024 static const BYTE ctlWithOneEntry[] = {
5025 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5026 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5027 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5028 static const BYTE ctlWithTwoEntries[] = {
5029 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5030 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5031 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5032 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5033 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5034
5035 static void test_encodeCTL(DWORD dwEncoding)
5036 {
5037     static char oid1[] = "1.2.3";
5038     static char oid2[] = "1.5.6";
5039     char *pOid1 = oid1;
5040     BOOL ret;
5041     BYTE *buf = NULL;
5042     DWORD size = 0;
5043     CTL_INFO info;
5044     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5045     CTL_ENTRY ctlEntry[2];
5046     CRYPT_ATTRIBUTE attr1, attr2;
5047     CRYPT_ATTR_BLOB value1, value2;
5048
5049     memset(&info, 0, sizeof(info));
5050     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5051      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5052     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5053     if (buf)
5054     {
5055         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5056         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5057         LocalFree(buf);
5058         buf = NULL;
5059     }
5060     info.dwVersion = 1;
5061     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5062      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5063     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5064     if (buf)
5065     {
5066         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5067         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5068         LocalFree(buf);
5069         buf = NULL;
5070     }
5071     info.dwVersion = 0;
5072     info.SubjectUsage.cUsageIdentifier = 1;
5073     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5074     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5075      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5076     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5077     if (buf)
5078     {
5079         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5080          size);
5081         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5082         LocalFree(buf);
5083         buf = NULL;
5084     }
5085     info.SubjectUsage.cUsageIdentifier = 0;
5086     info.ListIdentifier.cbData = sizeof(serialNum);
5087     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5088     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5089      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5090     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5091     if (buf)
5092     {
5093         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5094         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5095         LocalFree(buf);
5096         buf = NULL;
5097     }
5098     info.ListIdentifier.cbData = 0;
5099     info.SequenceNumber.cbData = sizeof(serialNum);
5100     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5101     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5102      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5103     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5104     if (buf)
5105     {
5106         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5107          size);
5108         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5109         LocalFree(buf);
5110         buf = NULL;
5111     }
5112     info.SequenceNumber.cbData = 0;
5113     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5114     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5115      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5116     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5117     if (buf)
5118     {
5119         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5120         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5121         LocalFree(buf);
5122         buf = NULL;
5123     }
5124     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5125     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5126      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5127     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5128     if (buf)
5129     {
5130         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5131          size);
5132         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5133         LocalFree(buf);
5134         buf = NULL;
5135     }
5136     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5137     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5138     info.SubjectAlgorithm.pszObjId = oid2;
5139     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5140      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5141     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5142     if (buf)
5143     {
5144         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5145         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5146         LocalFree(buf);
5147         buf = NULL;
5148     }
5149     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5150      * (see tests below) but it'll encode fine.
5151      */
5152     info.SubjectAlgorithm.pszObjId = NULL;
5153     value1.cbData = sizeof(serialNum);
5154     value1.pbData = (LPBYTE)serialNum;
5155     attr1.pszObjId = oid1;
5156     attr1.cValue = 1;
5157     attr1.rgValue = &value1;
5158     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5159     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5160     ctlEntry[0].cAttribute = 1;
5161     ctlEntry[0].rgAttribute = &attr1;
5162     info.cCTLEntry = 1;
5163     info.rgCTLEntry = ctlEntry;
5164     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5165      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5166     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5167     if (buf)
5168     {
5169         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5170         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5171         LocalFree(buf);
5172         buf = NULL;
5173     }
5174     value1.cbData = sizeof(emptySequence);
5175     value1.pbData = (LPBYTE)emptySequence;
5176     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5177      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5178     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5179     if (buf)
5180     {
5181         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5182         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5183         LocalFree(buf);
5184         buf = NULL;
5185     }
5186     value2.cbData = sizeof(encodedIPAddr);
5187     value2.pbData = (LPBYTE)encodedIPAddr;
5188     attr2.pszObjId = oid2;
5189     attr2.cValue = 1;
5190     attr2.rgValue = &value2;
5191     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5192     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5193     ctlEntry[1].cAttribute = 1;
5194     ctlEntry[1].rgAttribute = &attr2;
5195     info.cCTLEntry = 2;
5196     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5197      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5198     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5199     if (buf)
5200     {
5201         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5202         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5203         LocalFree(buf);
5204         buf = NULL;
5205     }
5206 }
5207
5208 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5209  const CTL_INFO *got)
5210 {
5211     DWORD i, j, k;
5212
5213     ok(expected->dwVersion == got->dwVersion,
5214      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5215      got->dwVersion);
5216     ok(expected->SubjectUsage.cUsageIdentifier ==
5217      got->SubjectUsage.cUsageIdentifier,
5218      "%s: expected %d usage identifiers, got %d\n", header,
5219      expected->SubjectUsage.cUsageIdentifier,
5220      got->SubjectUsage.cUsageIdentifier);
5221     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5222         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5223          got->SubjectUsage.rgpszUsageIdentifier[i]),
5224          "%s[%d]: expected %s, got %s\n", header, i,
5225          expected->SubjectUsage.rgpszUsageIdentifier[i],
5226          got->SubjectUsage.rgpszUsageIdentifier[i]);
5227     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5228      "%s: expected list identifier of %d bytes, got %d\n", header,
5229      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5230     if (expected->ListIdentifier.cbData)
5231         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5232          expected->ListIdentifier.cbData),
5233          "%s: unexpected list identifier value\n", header);
5234     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5235      "%s: expected sequence number of %d bytes, got %d\n", header,
5236      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5237     if (expected->SequenceNumber.cbData)
5238         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5239          expected->SequenceNumber.cbData),
5240          "%s: unexpected sequence number value\n", header);
5241     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5242      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5243      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5244      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5245     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5246      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5247      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5248      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5249     if (expected->SubjectAlgorithm.pszObjId &&
5250      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5251         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5252          expected->SubjectAlgorithm.pszObjId);
5253     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5254         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5255          got->SubjectAlgorithm.pszObjId),
5256          "%s: expected subject algorithm %s, got %s\n", header,
5257          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5258     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5259      got->SubjectAlgorithm.Parameters.cbData,
5260      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5261      expected->SubjectAlgorithm.Parameters.cbData,
5262      got->SubjectAlgorithm.Parameters.cbData);
5263     if (expected->SubjectAlgorithm.Parameters.cbData)
5264         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5265          got->SubjectAlgorithm.Parameters.pbData,
5266          expected->SubjectAlgorithm.Parameters.cbData),
5267          "%s: unexpected subject algorithm parameter value\n", header);
5268     ok(expected->cCTLEntry == got->cCTLEntry,
5269      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5270      got->cCTLEntry);
5271     for (i = 0; i < expected->cCTLEntry; i++)
5272     {
5273         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5274          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5275          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5276          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5277          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5278         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5279             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5280              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5281              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5282              "%s[%d]: unexpected subject identifier value\n",
5283              header, i);
5284         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5285         {
5286             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5287              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5288              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5289              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5290              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5291             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5292             {
5293                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5294                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5295                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5296                  header, i, j, k,
5297                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5298                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5299                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5300                     ok(!memcmp(
5301                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5302                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5303                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5304                      "%s[%d][%d][%d]: unexpected value\n",
5305                      header, i, j, k);
5306             }
5307         }
5308     }
5309     ok(expected->cExtension == got->cExtension,
5310      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5311      got->cExtension);
5312     for (i = 0; i < expected->cExtension; i++)
5313     {
5314         ok(!strcmp(expected->rgExtension[i].pszObjId,
5315          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5316          header, i, expected->rgExtension[i].pszObjId,
5317          got->rgExtension[i].pszObjId);
5318         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5319          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5320          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5321         ok(expected->rgExtension[i].Value.cbData ==
5322          got->rgExtension[i].Value.cbData,
5323          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5324          header, i, expected->rgExtension[i].Value.cbData,
5325          got->rgExtension[i].Value.cbData);
5326         if (expected->rgExtension[i].Value.cbData)
5327             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5328              got->rgExtension[i].Value.pbData,
5329              expected->rgExtension[i].Value.cbData),
5330              "%s[%d]: unexpected extension value\n", header, i);
5331     }
5332 }
5333
5334 static const BYTE signedCTL[] = {
5335 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5336 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5337 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5338 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5339 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5340 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5341 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5342 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5343 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5344 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5345 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5346 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5347 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5348 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5349 static const BYTE signedCTLWithCTLInnerContent[] = {
5350 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5351 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5352 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5353 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5354 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5355 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5356 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5357 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5358 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5359 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5360 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5361 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5362 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5363 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5364 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5365 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5366 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5367 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5368 0x57,0x6c,0x0b,0x47,0xb8 };
5369
5370 static void test_decodeCTL(DWORD dwEncoding)
5371 {
5372     static char oid1[] = "1.2.3";
5373     static char oid2[] = "1.5.6";
5374     static BYTE nullData[] = { 5,0 };
5375     char *pOid1 = oid1;
5376     BOOL ret;
5377     BYTE *buf = NULL;
5378     DWORD size = 0;
5379     CTL_INFO info;
5380     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5381     CTL_ENTRY ctlEntry[2];
5382     CRYPT_ATTRIBUTE attr1, attr2;
5383     CRYPT_ATTR_BLOB value1, value2;
5384
5385     memset(&info, 0, sizeof(info));
5386     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5387      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5388     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5389     if (buf)
5390     {
5391         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5392         LocalFree(buf);
5393         buf = NULL;
5394     }
5395     info.dwVersion = 1;
5396     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5397      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
5398      &size);
5399     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5400     if (buf)
5401     {
5402         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5403         LocalFree(buf);
5404         buf = NULL;
5405     }
5406     info.dwVersion = 0;
5407     info.SubjectUsage.cUsageIdentifier = 1;
5408     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5409     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5410      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5411      (BYTE *)&buf, &size);
5412     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5413     if (buf)
5414     {
5415         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5416         LocalFree(buf);
5417         buf = NULL;
5418     }
5419     info.SubjectUsage.cUsageIdentifier = 0;
5420     info.ListIdentifier.cbData = sizeof(serialNum);
5421     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5422     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5423      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5424      (BYTE *)&buf, &size);
5425     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5426     if (buf)
5427     {
5428         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5429         LocalFree(buf);
5430         buf = NULL;
5431     }
5432     info.ListIdentifier.cbData = 0;
5433     info.SequenceNumber.cbData = sizeof(serialNum);
5434     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5435     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5436      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL,
5437      (BYTE *)&buf, &size);
5438     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5439     if (buf)
5440     {
5441         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5442         LocalFree(buf);
5443         buf = NULL;
5444     }
5445     info.SequenceNumber.cbData = 0;
5446     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5447     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5448      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5449      (BYTE *)&buf, &size);
5450     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5451     if (buf)
5452     {
5453         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5454         LocalFree(buf);
5455         buf = NULL;
5456     }
5457     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5458     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5459      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5460      (BYTE *)&buf, &size);
5461     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5462     if (buf)
5463     {
5464         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5465         LocalFree(buf);
5466         buf = NULL;
5467     }
5468     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5469     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5470     info.SubjectAlgorithm.pszObjId = oid2;
5471     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5472     info.SubjectAlgorithm.Parameters.pbData = nullData;
5473     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5474      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL,
5475      (BYTE *)&buf, &size);
5476     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5477     if (buf)
5478     {
5479         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5480         LocalFree(buf);
5481         buf = NULL;
5482     }
5483     SetLastError(0xdeadbeef);
5484     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5485      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5486      (BYTE *)&buf, &size);
5487     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT),
5488      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5489      GetLastError());
5490     info.SubjectAlgorithm.Parameters.cbData = 0;
5491     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5492     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5493     info.SubjectAlgorithm.pszObjId = oid2;
5494     info.SubjectAlgorithm.pszObjId = NULL;
5495     value1.cbData = sizeof(emptySequence);
5496     value1.pbData = (LPBYTE)emptySequence;
5497     attr1.pszObjId = oid1;
5498     attr1.cValue = 1;
5499     attr1.rgValue = &value1;
5500     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5501     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5502     ctlEntry[0].cAttribute = 1;
5503     ctlEntry[0].rgAttribute = &attr1;
5504     info.cCTLEntry = 1;
5505     info.rgCTLEntry = ctlEntry;
5506     SetLastError(0xdeadbeef);
5507     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5508      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5509      (BYTE *)&buf, &size);
5510     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5511     if (buf)
5512     {
5513         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5514         LocalFree(buf);
5515         buf = NULL;
5516     }
5517     value2.cbData = sizeof(encodedIPAddr);
5518     value2.pbData = (LPBYTE)encodedIPAddr;
5519     attr2.pszObjId = oid2;
5520     attr2.cValue = 1;
5521     attr2.rgValue = &value2;
5522     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5523     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5524     ctlEntry[1].cAttribute = 1;
5525     ctlEntry[1].rgAttribute = &attr2;
5526     info.cCTLEntry = 2;
5527     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5528      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL,
5529      (BYTE *)&buf, &size);
5530     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5531     if (buf)
5532     {
5533         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5534         LocalFree(buf);
5535         buf = NULL;
5536     }
5537     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5538     SetLastError(0xdeadbeef);
5539     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5540      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5541     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
5542      "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
5543     SetLastError(0xdeadbeef);
5544     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5545      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5546      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5547     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
5548      "expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
5549 }
5550
5551 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5552 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5553  0x03,0,0,0,0,0,0 };
5554 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5555  0xa0,0x01,0x01 };
5556 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5557  0x03,0x02,0x01,0x01 };
5558 static BYTE bogusDER[] = { 1 };
5559
5560 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5561 {
5562     BOOL ret;
5563     BYTE *buf = NULL;
5564     DWORD size = 0;
5565     CRYPT_CONTENT_INFO info = { 0 };
5566     char oid1[] = "1.2.3";
5567
5568     if (0)
5569     {
5570         /* Crashes on win9x */
5571         SetLastError(0xdeadbeef);
5572         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5573          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5574         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5575          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5576     }
5577     SetLastError(0xdeadbeef);
5578     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5579      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5580     ok(!ret && GetLastError() == E_INVALIDARG,
5581      "Expected E_INVALIDARG, got %x\n", GetLastError());
5582     info.pszObjId = oid1;
5583     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5584      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5585     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5586     if (buf)
5587     {
5588         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5589         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5590         LocalFree(buf);
5591     }
5592     info.Content.pbData = bogusDER;
5593     info.Content.cbData = sizeof(bogusDER);
5594     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5595      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5596     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5597     if (buf)
5598     {
5599         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5600         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5601         LocalFree(buf);
5602     }
5603     info.Content.pbData = (BYTE *)ints[0].encoded;
5604     info.Content.cbData = ints[0].encoded[1] + 2;
5605     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5606      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5607     if (buf)
5608     {
5609         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5610         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5611         LocalFree(buf);
5612     }
5613 }
5614
5615 static const BYTE indefiniteSignedPKCSContent[] = {
5616 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5617 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5618 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5619 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5620 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5621 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5622 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5623 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5624 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5625 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5626 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5627 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5628 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5629 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5630 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5631 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5632 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5633 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5634 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5635 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5636 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5637 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5638 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5639 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5640 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5641 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5642 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5643 0x00,0x00,0x00,0x00,0x00,0x00 };
5644
5645 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5646 {
5647     BOOL ret;
5648     LPBYTE buf = NULL;
5649     DWORD size = 0;
5650     CRYPT_CONTENT_INFO *info;
5651
5652     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5653      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5654      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5655     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5656     if (buf)
5657     {
5658         info = (CRYPT_CONTENT_INFO *)buf;
5659
5660         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5661          info->pszObjId);
5662         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5663          info->Content.cbData);
5664         LocalFree(buf);
5665     }
5666     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5667      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5668      0, NULL, NULL, &size);
5669     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5670     SetLastError(0xdeadbeef);
5671     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5672      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5673      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5674     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5675      * I doubt an app depends on that.
5676      */
5677     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5678      GetLastError() == CRYPT_E_ASN1_CORRUPT),
5679      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5680      GetLastError());
5681     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5682      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5683      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5684     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5685     if (buf)
5686     {
5687         info = (CRYPT_CONTENT_INFO *)buf;
5688
5689         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5690          info->pszObjId);
5691         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5692          "Unexpected size %d\n", info->Content.cbData);
5693         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5694          info->Content.cbData), "Unexpected value\n");
5695         LocalFree(buf);
5696     }
5697     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5698      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5699      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5700     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5701     if (buf)
5702     {
5703         info = (CRYPT_CONTENT_INFO *)buf;
5704
5705         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5706          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5707         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5708          info->Content.cbData);
5709         LocalFree(buf);
5710     }
5711 }
5712
5713 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5714  0x00 };
5715 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5716  0x01 };
5717 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5718  0x02,0x01,0x01 };
5719
5720 static void test_encodePKCSAttribute(DWORD dwEncoding)
5721 {
5722     CRYPT_ATTRIBUTE attr = { 0 };
5723     BOOL ret;
5724     LPBYTE buf = NULL;
5725     DWORD size = 0;
5726     CRYPT_ATTR_BLOB blob;
5727     char oid[] = "1.2.3";
5728
5729     if (0)
5730     {
5731         /* Crashes on win9x */
5732         SetLastError(0xdeadbeef);
5733         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5734          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5735         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5736          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5737     }
5738     SetLastError(0xdeadbeef);
5739     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5740      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5741     ok(!ret && GetLastError() == E_INVALIDARG,
5742      "Expected E_INVALIDARG, got %x\n", GetLastError());
5743     attr.pszObjId = oid;
5744     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5745      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5746     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5747     if (buf)
5748     {
5749         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5750         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5751         LocalFree(buf);
5752     }
5753     blob.cbData = sizeof(bogusDER);
5754     blob.pbData = bogusDER;
5755     attr.cValue = 1;
5756     attr.rgValue = &blob;
5757     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5758      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5759     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5760     if (buf)
5761     {
5762         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5763         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5764         LocalFree(buf);
5765     }
5766     blob.pbData = (BYTE *)ints[0].encoded;
5767     blob.cbData = ints[0].encoded[1] + 2;
5768     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5769      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5770     if (buf)
5771     {
5772         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5773         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5774         LocalFree(buf);
5775     }
5776 }
5777
5778 static void test_decodePKCSAttribute(DWORD dwEncoding)
5779 {
5780     BOOL ret;
5781     LPBYTE buf = NULL;
5782     DWORD size = 0;
5783     CRYPT_ATTRIBUTE *attr;
5784
5785     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5786      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5787      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5788     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5789     if (buf)
5790     {
5791         attr = (CRYPT_ATTRIBUTE *)buf;
5792
5793         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5794          attr->pszObjId);
5795         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5796         LocalFree(buf);
5797     }
5798     SetLastError(0xdeadbeef);
5799     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5800      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5801      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5802     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5803      * I doubt an app depends on that.
5804      */
5805     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5806      GetLastError() == CRYPT_E_ASN1_CORRUPT),
5807      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5808      GetLastError());
5809     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5810      intPKCSAttr, sizeof(intPKCSAttr),
5811      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5812     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5813     if (buf)
5814     {
5815         attr = (CRYPT_ATTRIBUTE *)buf;
5816
5817         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5818          attr->pszObjId);
5819         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5820         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5821          "Unexpected size %d\n", attr->rgValue[0].cbData);
5822         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5823          attr->rgValue[0].cbData), "Unexpected value\n");
5824         LocalFree(buf);
5825     }
5826 }
5827
5828 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5829 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5830  0x2a,0x03,0x31,0x00 };
5831 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5832  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5833
5834 static void test_encodePKCSAttributes(DWORD dwEncoding)
5835 {
5836     CRYPT_ATTRIBUTES attributes = { 0 };
5837     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5838     CRYPT_ATTR_BLOB blob;
5839     BOOL ret;
5840     LPBYTE buf = NULL;
5841     DWORD size = 0;
5842     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5843
5844     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5845      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5846     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5847     if (buf)
5848     {
5849         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5850         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5851         LocalFree(buf);
5852     }
5853     attributes.cAttr = 1;
5854     attributes.rgAttr = attr;
5855     SetLastError(0xdeadbeef);
5856     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5857      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5858     ok(!ret && GetLastError() == E_INVALIDARG,
5859      "Expected E_INVALIDARG, got %x\n", GetLastError());
5860     attr[0].pszObjId = oid1;
5861     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5862      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5863     if (buf)
5864     {
5865         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5866         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5867         LocalFree(buf);
5868     }
5869     attr[1].pszObjId = oid2;
5870     attr[1].cValue = 1;
5871     attr[1].rgValue = &blob;
5872     blob.pbData = (BYTE *)ints[0].encoded;
5873     blob.cbData = ints[0].encoded[1] + 2;
5874     attributes.cAttr = 2;
5875     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5876      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5877     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5878     if (buf)
5879     {
5880         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5881         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5882         LocalFree(buf);
5883     }
5884 }
5885
5886 static void test_decodePKCSAttributes(DWORD dwEncoding)
5887 {
5888     BOOL ret;
5889     LPBYTE buf = NULL;
5890     DWORD size = 0;
5891     CRYPT_ATTRIBUTES *attributes;
5892
5893     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5894      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5895      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5896     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5897     if (buf)
5898     {
5899         attributes = (CRYPT_ATTRIBUTES *)buf;
5900         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5901          attributes->cAttr);
5902         LocalFree(buf);
5903     }
5904     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5905      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5906      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5907     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5908     if (buf)
5909     {
5910         attributes = (CRYPT_ATTRIBUTES *)buf;
5911         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5912          attributes->cAttr);
5913         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5914          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5915         ok(attributes->rgAttr[0].cValue == 0,
5916          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5917         LocalFree(buf);
5918     }
5919     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5920      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5921      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5922     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5923     if (buf)
5924     {
5925         attributes = (CRYPT_ATTRIBUTES *)buf;
5926         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5927          attributes->cAttr);
5928         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5929          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5930         ok(attributes->rgAttr[0].cValue == 0,
5931          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5932         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5933          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5934         ok(attributes->rgAttr[1].cValue == 1,
5935          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5936         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5937          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5938         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5939          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5940         LocalFree(buf);
5941     }
5942 }
5943
5944 static const BYTE singleCapability[] = {
5945 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5946 static const BYTE twoCapabilities[] = {
5947 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5948 static const BYTE singleCapabilitywithNULL[] = {
5949 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5950
5951 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
5952 {
5953     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5954     BOOL ret;
5955     LPBYTE buf = NULL;
5956     DWORD size = 0;
5957     CRYPT_SMIME_CAPABILITY capability[2];
5958     CRYPT_SMIME_CAPABILITIES capabilities;
5959
5960     /* An empty capabilities is allowed */
5961     capabilities.cCapability = 0;
5962     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5963      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5964     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5965     if (buf)
5966     {
5967         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5968         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5969         LocalFree(buf);
5970     }
5971     /* A non-empty capabilities with an empty capability (lacking an OID) is
5972      * not allowed
5973      */
5974     capability[0].pszObjId = NULL;
5975     capability[0].Parameters.cbData = 0;
5976     capabilities.cCapability = 1;
5977     capabilities.rgCapability = capability;
5978     SetLastError(0xdeadbeef);
5979     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5980      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5981     ok(!ret && GetLastError() == E_INVALIDARG,
5982      "expected E_INVALIDARG, got %08x\n", GetLastError());
5983     capability[0].pszObjId = oid1;
5984     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5985      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5986     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5987     if (buf)
5988     {
5989         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
5990         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
5991         LocalFree(buf);
5992     }
5993     capability[1].pszObjId = oid2;
5994     capability[1].Parameters.cbData = 0;
5995     capabilities.cCapability = 2;
5996     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5997      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5998     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5999     if (buf)
6000     {
6001         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6002         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6003         LocalFree(buf);
6004     }
6005 }
6006
6007 static void compareSMimeCapabilities(LPCSTR header,
6008  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6009 {
6010     DWORD i;
6011
6012     ok(got->cCapability == expected->cCapability,
6013      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6014      got->cCapability);
6015     for (i = 0; i < expected->cCapability; i++)
6016     {
6017         ok(!strcmp(expected->rgCapability[i].pszObjId,
6018          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6019          header, i, expected->rgCapability[i].pszObjId,
6020          got->rgCapability[i].pszObjId);
6021         ok(expected->rgCapability[i].Parameters.cbData ==
6022          got->rgCapability[i].Parameters.cbData,
6023          "%s[%d]: expected %d bytes, got %d\n", header, i,
6024          expected->rgCapability[i].Parameters.cbData,
6025          got->rgCapability[i].Parameters.cbData);
6026         if (expected->rgCapability[i].Parameters.cbData)
6027             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6028              got->rgCapability[i].Parameters.pbData,
6029              expected->rgCapability[i].Parameters.cbData),
6030              "%s[%d]: unexpected value\n", header, i);
6031     }
6032 }
6033
6034 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6035 {
6036     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6037     BOOL ret;
6038     DWORD size = 0;
6039     CRYPT_SMIME_CAPABILITY capability[2];
6040     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6041
6042     SetLastError(0xdeadbeef);
6043     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6044      emptySequence, sizeof(emptySequence),
6045      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6046     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6047     if (ret)
6048     {
6049         capabilities.cCapability = 0;
6050         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6051         LocalFree(ptr);
6052     }
6053     SetLastError(0xdeadbeef);
6054     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6055      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6056      (BYTE *)&ptr, &size);
6057     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6058     if (ret)
6059     {
6060         capability[0].pszObjId = oid1;
6061         capability[0].Parameters.cbData = 0;
6062         capabilities.cCapability = 1;
6063         capabilities.rgCapability = capability;
6064         compareSMimeCapabilities("single capability", &capabilities, ptr);
6065         LocalFree(ptr);
6066     }
6067     SetLastError(0xdeadbeef);
6068     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6069      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6070      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6071     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6072     if (ret)
6073     {
6074         BYTE NULLparam[] = {0x05, 0x00};
6075         capability[0].pszObjId = oid1;
6076         capability[0].Parameters.cbData = 2;
6077         capability[0].Parameters.pbData = NULLparam;
6078         capabilities.cCapability = 1;
6079         capabilities.rgCapability = capability;
6080         compareSMimeCapabilities("single capability with NULL", &capabilities,
6081          ptr);
6082         LocalFree(ptr);
6083     }
6084     SetLastError(0xdeadbeef);
6085     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6086     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6087     (BYTE *)&ptr, &size);
6088     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6089     if (ret)
6090     {
6091         capability[0].Parameters.cbData = 0;
6092         capability[1].pszObjId = oid2;
6093         capability[1].Parameters.cbData = 0;
6094         capabilities.cCapability = 2;
6095         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6096         LocalFree(ptr);
6097     }
6098 }
6099
6100 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6101  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6102  0x67 };
6103 static const BYTE minimalPKCSSigner[] = {
6104  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6105  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6106  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6107 static const BYTE PKCSSignerWithSerial[] = {
6108  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6109  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6110  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6111  0x00 };
6112 static const BYTE PKCSSignerWithHashAlgo[] = {
6113  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6114  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6115  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6116  0x00,0x04,0x00 };
6117 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6118  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6119  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6120  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6121  0x06,0x05,0x00,0x04,0x00 };
6122 static const BYTE PKCSSignerWithHash[] = {
6123  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6124  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6125  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6126  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6127  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6128 static const BYTE PKCSSignerWithAuthAttr[] = {
6129 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6130 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6131 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6132 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6133 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6134 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6135 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6136
6137 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6138 {
6139     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6140     BOOL ret;
6141     LPBYTE buf = NULL;
6142     DWORD size = 0;
6143     CMSG_SIGNER_INFO info = { 0 };
6144     char oid_common_name[] = szOID_COMMON_NAME;
6145     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6146      (LPBYTE)encodedCommonName };
6147     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6148
6149     SetLastError(0xdeadbeef);
6150     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6151      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6152     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6153     {
6154         skip("no PKCS7_SIGNER_INFO encode support\n");
6155         return;
6156     }
6157     ok(!ret && GetLastError() == E_INVALIDARG,
6158      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6159     /* To be encoded, a signer must have an issuer at least, and the encoding
6160      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6161      * see decoding tests.)
6162      */
6163     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6164     info.Issuer.pbData = encodedCommonNameNoNull;
6165     SetLastError(0xdeadbeef);
6166     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6167      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6168     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6169         ok(!ret && GetLastError() == E_INVALIDARG,
6170          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6171     else
6172     {
6173         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6174         if (buf)
6175         {
6176             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6177             if (size == sizeof(minimalPKCSSigner))
6178                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6179             else
6180                 ok(0, "Unexpected value\n");
6181             LocalFree(buf);
6182         }
6183     }
6184     info.SerialNumber.cbData = sizeof(serialNum);
6185     info.SerialNumber.pbData = (BYTE *)serialNum;
6186     SetLastError(0xdeadbeef);
6187     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6188      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6189     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6190         ok(!ret && GetLastError() == E_INVALIDARG,
6191          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6192     else
6193     {
6194         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6195         if (buf)
6196         {
6197             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6198              size);
6199             if (size == sizeof(PKCSSignerWithSerial))
6200                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6201                  "Unexpected value\n");
6202             else
6203                 ok(0, "Unexpected value\n");
6204             LocalFree(buf);
6205         }
6206     }
6207     info.HashAlgorithm.pszObjId = oid1;
6208     SetLastError(0xdeadbeef);
6209     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6210      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6211     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6212         ok(!ret && GetLastError() == E_INVALIDARG,
6213          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6214     else
6215     {
6216         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6217         if (buf)
6218         {
6219             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6220              size);
6221             if (size == sizeof(PKCSSignerWithHashAlgo))
6222                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6223                  "Unexpected value\n");
6224             else
6225                 ok(0, "Unexpected value\n");
6226             LocalFree(buf);
6227         }
6228     }
6229     info.HashEncryptionAlgorithm.pszObjId = oid2;
6230     SetLastError(0xdeadbeef);
6231     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6232      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6233     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6234         ok(!ret && GetLastError() == E_INVALIDARG,
6235          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6236     else
6237     {
6238         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6239         if (buf)
6240         {
6241             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6242              "Unexpected size %d\n", size);
6243             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6244                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6245                  "Unexpected value\n");
6246             else
6247                 ok(0, "Unexpected value\n");
6248             LocalFree(buf);
6249         }
6250     }
6251     info.EncryptedHash.cbData = sizeof(hash);
6252     info.EncryptedHash.pbData = (BYTE *)hash;
6253     SetLastError(0xdeadbeef);
6254     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6255      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6256     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6257         ok(!ret && GetLastError() == E_INVALIDARG,
6258          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6259     else
6260     {
6261         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6262         if (buf)
6263         {
6264             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6265              size);
6266             if (size == sizeof(PKCSSignerWithHash))
6267                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6268                  "Unexpected value\n");
6269             else
6270                 ok(0, "Unexpected value\n");
6271             LocalFree(buf);
6272         }
6273     }
6274     info.AuthAttrs.cAttr = 1;
6275     info.AuthAttrs.rgAttr = &attr;
6276     SetLastError(0xdeadbeef);
6277     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6278      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6279     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6280         ok(!ret && GetLastError() == E_INVALIDARG,
6281          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6282     else
6283     {
6284         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6285         if (buf)
6286         {
6287             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6288              size);
6289             if (size == sizeof(PKCSSignerWithAuthAttr))
6290                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6291                  "Unexpected value\n");
6292             else
6293                 ok(0, "Unexpected value\n");
6294             LocalFree(buf);
6295         }
6296     }
6297 }
6298
6299 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6300 {
6301     BOOL ret;
6302     LPBYTE buf = NULL;
6303     DWORD size = 0;
6304     CMSG_SIGNER_INFO *info;
6305
6306     /* A PKCS signer can't be decoded without a serial number. */
6307     SetLastError(0xdeadbeef);
6308     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6309      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6310      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6311     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
6312      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6313     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6314      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6315      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6316     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6317     if (buf)
6318     {
6319         info = (CMSG_SIGNER_INFO *)buf;
6320         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6321          info->dwVersion);
6322         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6323          "Unexpected size %d\n", info->Issuer.cbData);
6324         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6325          info->Issuer.cbData), "Unexpected value\n");
6326         ok(info->SerialNumber.cbData == sizeof(serialNum),
6327          "Unexpected size %d\n", info->SerialNumber.cbData);
6328         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6329          "Unexpected value\n");
6330         LocalFree(buf);
6331     }
6332     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6333      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6334      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6335     if (buf)
6336     {
6337         info = (CMSG_SIGNER_INFO *)buf;
6338         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6339          info->dwVersion);
6340         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6341          "Unexpected size %d\n", info->Issuer.cbData);
6342         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6343          info->Issuer.cbData), "Unexpected value\n");
6344         ok(info->SerialNumber.cbData == sizeof(serialNum),
6345          "Unexpected size %d\n", info->SerialNumber.cbData);
6346         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6347          "Unexpected value\n");
6348         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6349          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6350         LocalFree(buf);
6351     }
6352     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6353      PKCSSignerWithHashAndEncryptionAlgo,
6354      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6355      NULL, (BYTE *)&buf, &size);
6356     if (buf)
6357     {
6358         info = (CMSG_SIGNER_INFO *)buf;
6359         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6360          info->dwVersion);
6361         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6362          "Unexpected size %d\n", info->Issuer.cbData);
6363         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6364          info->Issuer.cbData), "Unexpected value\n");
6365         ok(info->SerialNumber.cbData == sizeof(serialNum),
6366          "Unexpected size %d\n", info->SerialNumber.cbData);
6367         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6368          "Unexpected value\n");
6369         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6370          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6371         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6372          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6373         LocalFree(buf);
6374     }
6375     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6376      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6377      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6378     if (buf)
6379     {
6380         info = (CMSG_SIGNER_INFO *)buf;
6381         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6382          info->dwVersion);
6383         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6384          "Unexpected size %d\n", info->Issuer.cbData);
6385         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6386          info->Issuer.cbData), "Unexpected value\n");
6387         ok(info->SerialNumber.cbData == sizeof(serialNum),
6388          "Unexpected size %d\n", info->SerialNumber.cbData);
6389         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6390          "Unexpected value\n");
6391         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6392          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6393         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6394          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6395         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6396          info->EncryptedHash.cbData);
6397         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6398          "Unexpected value\n");
6399         LocalFree(buf);
6400     }
6401     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6402      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6403      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6404     if (buf)
6405     {
6406         info = (CMSG_SIGNER_INFO *)buf;
6407         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6408          info->AuthAttrs.cAttr);
6409         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6410          "Expected %s, got %s\n", szOID_COMMON_NAME,
6411          info->AuthAttrs.rgAttr[0].pszObjId);
6412         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6413          info->AuthAttrs.rgAttr[0].cValue);
6414         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6415          sizeof(encodedCommonName), "Unexpected size %d\n",
6416          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6417         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6418          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6419         LocalFree(buf);
6420     }
6421 }
6422
6423 static const BYTE CMSSignerWithKeyId[] = {
6424 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6425 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6426
6427 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6428 {
6429     BOOL ret;
6430     LPBYTE buf = NULL;
6431     DWORD size = 0;
6432     CMSG_CMS_SIGNER_INFO info = { 0 };
6433     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6434
6435     SetLastError(0xdeadbeef);
6436     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6437      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6438     ok(!ret && GetLastError() == E_INVALIDARG,
6439      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6440     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6441     SetLastError(0xdeadbeef);
6442     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6443      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6444     ok(!ret, "Expected failure, got %d\n", ret);
6445     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6446     {
6447         skip("no CMS_SIGNER_INFO encode support\n");
6448         return;
6449     }
6450     ok(GetLastError() == E_INVALIDARG,
6451        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6452     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6453      * be a key id or a issuer serial number with at least the issuer set, and
6454      * the encoding must include PKCS_7_ASN_ENCODING.
6455      * (That isn't enough to be decoded, see decoding tests.)
6456      */
6457     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6458      sizeof(encodedCommonNameNoNull);
6459     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6460     SetLastError(0xdeadbeef);
6461     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6462      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6463     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6464         ok(!ret && GetLastError() == E_INVALIDARG,
6465          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6466     else
6467     {
6468         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6469         if (buf)
6470         {
6471             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6472             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6473             LocalFree(buf);
6474         }
6475     }
6476     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6477     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6478     SetLastError(0xdeadbeef);
6479     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6480      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6481     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6482         ok(!ret && GetLastError() == E_INVALIDARG,
6483          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6484     else
6485     {
6486         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6487         if (buf)
6488         {
6489             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6490              size);
6491             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6492             LocalFree(buf);
6493         }
6494     }
6495     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6496     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6497     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6498     SetLastError(0xdeadbeef);
6499     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6500      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6501     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6502         ok(!ret && GetLastError() == E_INVALIDARG,
6503          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6504     else
6505     {
6506         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6507         if (buf)
6508         {
6509             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6510              size);
6511             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6512             LocalFree(buf);
6513         }
6514     }
6515     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6516      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6517      * (see RFC 3852, section 5.3.)
6518      */
6519     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6520     U(info.SignerId).HashId.cbData = sizeof(hash);
6521     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6522     SetLastError(0xdeadbeef);
6523     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6524      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6525     ok(!ret && GetLastError() == E_INVALIDARG,
6526      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6527     /* Now with a hash algo */
6528     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6529     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6530      sizeof(encodedCommonNameNoNull);
6531     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6532     info.HashAlgorithm.pszObjId = oid1;
6533     SetLastError(0xdeadbeef);
6534     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6535      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6536     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6537         ok(!ret && GetLastError() == E_INVALIDARG,
6538          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6539     else
6540     {
6541         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6542         if (buf)
6543         {
6544             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6545              size);
6546             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6547              "Unexpected value\n");
6548             LocalFree(buf);
6549         }
6550     }
6551     info.HashEncryptionAlgorithm.pszObjId = oid2;
6552     SetLastError(0xdeadbeef);
6553     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6554      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&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(PKCSSignerWithHashAndEncryptionAlgo),
6564              "Unexpected size %d\n", size);
6565             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6566              "Unexpected value\n");
6567             LocalFree(buf);
6568         }
6569     }
6570     info.EncryptedHash.cbData = sizeof(hash);
6571     info.EncryptedHash.pbData = (BYTE *)hash;
6572     SetLastError(0xdeadbeef);
6573     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6574      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6575     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6576         ok(!ret && GetLastError() == E_INVALIDARG,
6577          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6578     else
6579     {
6580         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6581         if (buf)
6582         {
6583             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6584              size);
6585             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6586             LocalFree(buf);
6587         }
6588     }
6589 }
6590
6591 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6592 {
6593     BOOL ret;
6594     LPBYTE buf = NULL;
6595     DWORD size = 0;
6596     CMSG_CMS_SIGNER_INFO *info;
6597     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6598
6599     /* A CMS signer can't be decoded without a serial number. */
6600     SetLastError(0xdeadbeef);
6601     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6602      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6603      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6604     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
6605      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6606     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6607      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6608      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6609     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6610     if (buf)
6611     {
6612         info = (CMSG_CMS_SIGNER_INFO *)buf;
6613         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6614          info->dwVersion);
6615         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6616          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6617          info->SignerId.dwIdChoice);
6618         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6619          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6620          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6621         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6622          encodedCommonNameNoNull,
6623          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6624          "Unexpected value\n");
6625         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6626          sizeof(serialNum), "Unexpected size %d\n",
6627          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6628         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6629          serialNum, sizeof(serialNum)), "Unexpected value\n");
6630         LocalFree(buf);
6631     }
6632     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6633      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6634      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6635     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6636     if (buf)
6637     {
6638         info = (CMSG_CMS_SIGNER_INFO *)buf;
6639         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6640          info->dwVersion);
6641         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6642          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6643          info->SignerId.dwIdChoice);
6644         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6645          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6646          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6647         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6648          encodedCommonNameNoNull,
6649          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6650          "Unexpected value\n");
6651         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6652          sizeof(serialNum), "Unexpected size %d\n",
6653          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6654         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6655          serialNum, sizeof(serialNum)), "Unexpected value\n");
6656         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6657          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6658         LocalFree(buf);
6659     }
6660     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6661      PKCSSignerWithHashAndEncryptionAlgo,
6662      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6663      NULL, (BYTE *)&buf, &size);
6664     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6665     if (buf)
6666     {
6667         info = (CMSG_CMS_SIGNER_INFO *)buf;
6668         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6669          info->dwVersion);
6670         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6671          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6672          info->SignerId.dwIdChoice);
6673         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6674          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6675          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6676         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6677          encodedCommonNameNoNull,
6678          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6679          "Unexpected value\n");
6680         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6681          sizeof(serialNum), "Unexpected size %d\n",
6682          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6683         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6684          serialNum, sizeof(serialNum)), "Unexpected value\n");
6685         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6686          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6687         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6688          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6689         LocalFree(buf);
6690     }
6691     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6692      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6693      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6694     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6695     if (buf)
6696     {
6697         info = (CMSG_CMS_SIGNER_INFO *)buf;
6698         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6699          info->dwVersion);
6700         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6701          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6702          info->SignerId.dwIdChoice);
6703         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6704          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6705          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6706         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6707          encodedCommonNameNoNull,
6708          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6709          "Unexpected value\n");
6710         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6711          sizeof(serialNum), "Unexpected size %d\n",
6712          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6713         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6714          serialNum, sizeof(serialNum)), "Unexpected value\n");
6715         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6716          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6717         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6718          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6719         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6720          info->EncryptedHash.cbData);
6721         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6722          "Unexpected value\n");
6723         LocalFree(buf);
6724     }
6725     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6726      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6727      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6728     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6729     if (buf)
6730     {
6731         info = (CMSG_CMS_SIGNER_INFO *)buf;
6732         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6733          info->dwVersion);
6734         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6735          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6736          info->SignerId.dwIdChoice);
6737         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6738          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6739         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6740          "Unexpected value\n");
6741         LocalFree(buf);
6742     }
6743 }
6744
6745 static BYTE emptyDNSPermittedConstraints[] = {
6746 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6747 static BYTE emptyDNSExcludedConstraints[] = {
6748 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6749 static BYTE DNSExcludedConstraints[] = {
6750 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6751 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6752 static BYTE permittedAndExcludedConstraints[] = {
6753 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6754 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6755 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6756 static BYTE permittedAndExcludedWithMinConstraints[] = {
6757 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6758 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6759 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6760 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6761 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6762 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6763 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6764
6765 static void test_encodeNameConstraints(DWORD dwEncoding)
6766 {
6767     BOOL ret;
6768     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6769     CERT_GENERAL_SUBTREE permitted = { { 0 } };
6770     CERT_GENERAL_SUBTREE excluded = { { 0 } };
6771     LPBYTE buf;
6772     DWORD size;
6773
6774     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6775      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6776     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6777     {
6778         skip("no X509_NAME_CONSTRAINTS encode support\n");
6779         return;
6780     }
6781     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6782     if (ret)
6783     {
6784         ok(size == sizeof(emptySequence), "Unexpected size\n");
6785         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6786         LocalFree(buf);
6787     }
6788     constraints.cPermittedSubtree = 1;
6789     constraints.rgPermittedSubtree = &permitted;
6790     SetLastError(0xdeadbeef);
6791     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6792      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6793     ok(!ret && GetLastError() == E_INVALIDARG,
6794      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6795     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6796     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6797      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6798     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6799     if (ret)
6800     {
6801         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6802         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6803          "Unexpected value\n");
6804         LocalFree(buf);
6805     }
6806     constraints.cPermittedSubtree = 0;
6807     constraints.cExcludedSubtree = 1;
6808     constraints.rgExcludedSubtree = &excluded;
6809     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6810     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6811      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6812     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6813     if (ret)
6814     {
6815         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6816         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6817          "Unexpected value\n");
6818         LocalFree(buf);
6819     }
6820     U(excluded.Base).pwszURL = (LPWSTR)url;
6821     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6822      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6823     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6824     if (ret)
6825     {
6826         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6827         ok(!memcmp(buf, DNSExcludedConstraints, size),
6828          "Unexpected value\n");
6829         LocalFree(buf);
6830     }
6831     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6832     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6833     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6834     constraints.cPermittedSubtree = 1;
6835     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6836      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6837     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6838     if (ret)
6839     {
6840         ok(size == sizeof(permittedAndExcludedConstraints),
6841          "Unexpected size\n");
6842         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6843          "Unexpected value\n");
6844         LocalFree(buf);
6845     }
6846     permitted.dwMinimum = 5;
6847     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6848      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6849     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6850     if (ret)
6851     {
6852         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6853          "Unexpected size\n");
6854         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6855          "Unexpected value\n");
6856         LocalFree(buf);
6857     }
6858     permitted.fMaximum = TRUE;
6859     permitted.dwMaximum = 3;
6860     SetLastError(0xdeadbeef);
6861     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6862      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6863     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6864     if (ret)
6865     {
6866         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6867          "Unexpected size\n");
6868         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6869          "Unexpected value\n");
6870         LocalFree(buf);
6871     }
6872 }
6873
6874 struct EncodedNameConstraints
6875 {
6876     CRYPT_DATA_BLOB            encoded;
6877     CERT_NAME_CONSTRAINTS_INFO constraints;
6878 };
6879
6880 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6881  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6882 static CERT_GENERAL_SUBTREE DNSSubtree = {
6883  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6884 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6885  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6886 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6887  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6888 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6889  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6890
6891 struct EncodedNameConstraints encodedNameConstraints[] = {
6892  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6893  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6894    { 1, &emptyDNSSubtree, 0, NULL } },
6895  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6896    { 0, NULL, 1, &emptyDNSSubtree } },
6897  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6898    { 0, NULL, 1, &DNSSubtree } },
6899  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6900    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6901  { { sizeof(permittedAndExcludedWithMinConstraints),
6902      permittedAndExcludedWithMinConstraints },
6903    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6904  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6905      permittedAndExcludedWithMinMaxConstraints },
6906    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6907 };
6908
6909 static void test_decodeNameConstraints(DWORD dwEncoding)
6910 {
6911     BOOL ret;
6912     DWORD i;
6913     CERT_NAME_CONSTRAINTS_INFO *constraints;
6914
6915     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6916     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6917     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6918     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6919     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6920     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6921     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6922     for (i = 0;
6923      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6924      i++)
6925     {
6926         DWORD size;
6927
6928         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6929          encodedNameConstraints[i].encoded.pbData,
6930          encodedNameConstraints[i].encoded.cbData,
6931          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
6932         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6933         {
6934             skip("no X509_NAME_CONSTRAINTS decode support\n");
6935             return;
6936         }
6937         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
6938         if (ret)
6939         {
6940             DWORD j;
6941
6942             if (constraints->cPermittedSubtree !=
6943              encodedNameConstraints[i].constraints.cPermittedSubtree)
6944                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
6945                  encodedNameConstraints[i].constraints.cPermittedSubtree,
6946                  constraints->cPermittedSubtree);
6947             if (constraints->cPermittedSubtree ==
6948              encodedNameConstraints[i].constraints.cPermittedSubtree)
6949             {
6950                 for (j = 0; j < constraints->cPermittedSubtree; j++)
6951                 {
6952                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
6953                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
6954                 }
6955             }
6956             if (constraints->cExcludedSubtree !=
6957              encodedNameConstraints[i].constraints.cExcludedSubtree)
6958                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
6959                  encodedNameConstraints[i].constraints.cExcludedSubtree,
6960                  constraints->cExcludedSubtree);
6961             if (constraints->cExcludedSubtree ==
6962              encodedNameConstraints[i].constraints.cExcludedSubtree)
6963             {
6964                 for (j = 0; j < constraints->cExcludedSubtree; j++)
6965                 {
6966                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
6967                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
6968                 }
6969             }
6970             LocalFree(constraints);
6971         }
6972     }
6973 }
6974
6975 /* Free *pInfo with HeapFree */
6976 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
6977 {
6978     BOOL ret;
6979     DWORD size = 0;
6980     HCRYPTKEY key;
6981
6982     /* This crashes
6983     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
6984      */
6985     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
6986     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6987      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6988     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
6989      &size);
6990     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6991      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6992     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
6993      NULL, &size);
6994     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6995      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6996     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
6997      0, NULL, NULL, &size);
6998     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6999      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7000     /* Test with no key */
7001     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7002      0, NULL, NULL, &size);
7003     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7004      GetLastError());
7005     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7006     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7007     if (ret)
7008     {
7009         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7010          NULL, 0, NULL, NULL, &size);
7011         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7012         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7013         if (*pInfo)
7014         {
7015             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7016              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7017             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7018              GetLastError());
7019             if (ret)
7020             {
7021                 /* By default (we passed NULL as the OID) the OID is
7022                  * szOID_RSA_RSA.
7023                  */
7024                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7025                  "Expected %s, got %s\n", szOID_RSA_RSA,
7026                  (*pInfo)->Algorithm.pszObjId);
7027             }
7028         }
7029     }
7030     CryptDestroyKey(key);
7031 }
7032
7033 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7034  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7035  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7036  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7037  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7038  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7039  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7040  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7041  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7042  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7043  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7044  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7045  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7046  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7047  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7048  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7049  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7050  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7051  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7052  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7053  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7054  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7055  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7056  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7057  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7058
7059 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7060 {
7061     BOOL ret;
7062     HCRYPTKEY key;
7063     PCCERT_CONTEXT context;
7064     DWORD dwSize;
7065     ALG_ID ai;
7066
7067     /* These crash
7068     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7069     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7070     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7071     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7072      NULL);
7073      */
7074     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7075     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7076      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7077     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7078     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7079      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7080     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7081      &key);
7082     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7083      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7084
7085     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7086     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7087      &key);
7088     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7089
7090     dwSize = sizeof(ai);
7091     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7092     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7093     if(ret)
7094     {
7095       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7096       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7097     }
7098
7099     CryptDestroyKey(key);
7100
7101     /* Repeat with forced algorithm */
7102     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7103      &key);
7104     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7105
7106     dwSize = sizeof(ai);
7107     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7108     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7109     if(ret)
7110     {
7111       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7112       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7113     }
7114
7115     CryptDestroyKey(key);
7116
7117     /* Test importing a public key from a certificate context */
7118     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7119      sizeof(expiredCert));
7120     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7121      GetLastError());
7122     if (context)
7123     {
7124         ok(!strcmp(szOID_RSA_RSA,
7125          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7126          "Expected %s, got %s\n", szOID_RSA_RSA,
7127          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7128         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7129          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7130         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7131         CryptDestroyKey(key);
7132         CertFreeCertificateContext(context);
7133     }
7134 }
7135
7136 static const char cspName[] = "WineCryptTemp";
7137
7138 static void testPortPublicKeyInfo(void)
7139 {
7140     HCRYPTPROV csp;
7141     BOOL ret;
7142     PCERT_PUBLIC_KEY_INFO info = NULL;
7143
7144     /* Just in case a previous run failed, delete this thing */
7145     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7146      CRYPT_DELETEKEYSET);
7147     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7148      CRYPT_NEWKEYSET);
7149
7150     testExportPublicKey(csp, &info);
7151     testImportPublicKey(csp, info);
7152
7153     HeapFree(GetProcessHeap(), 0, info);
7154     CryptReleaseContext(csp, 0);
7155     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7156      CRYPT_DELETEKEYSET);
7157 }
7158
7159 START_TEST(encode)
7160 {
7161     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7162      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7163     HMODULE hCrypt32;
7164     DWORD i;
7165
7166     hCrypt32 = GetModuleHandleA("crypt32.dll");
7167     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7168     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7169     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7170     {
7171         skip("CryptDecodeObjectEx() is not available\n");
7172         return;
7173     }
7174
7175     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7176     {
7177         test_encodeInt(encodings[i]);
7178         test_decodeInt(encodings[i]);
7179         test_encodeEnumerated(encodings[i]);
7180         test_decodeEnumerated(encodings[i]);
7181         test_encodeFiletime(encodings[i]);
7182         test_decodeFiletime(encodings[i]);
7183         test_encodeName(encodings[i]);
7184         test_decodeName(encodings[i]);
7185         test_encodeUnicodeName(encodings[i]);
7186         test_decodeUnicodeName(encodings[i]);
7187         test_encodeNameValue(encodings[i]);
7188         test_decodeNameValue(encodings[i]);
7189         test_encodeUnicodeNameValue(encodings[i]);
7190         test_decodeUnicodeNameValue(encodings[i]);
7191         test_encodeAltName(encodings[i]);
7192         test_decodeAltName(encodings[i]);
7193         test_encodeOctets(encodings[i]);
7194         test_decodeOctets(encodings[i]);
7195         test_encodeBits(encodings[i]);
7196         test_decodeBits(encodings[i]);
7197         test_encodeBasicConstraints(encodings[i]);
7198         test_decodeBasicConstraints(encodings[i]);
7199         test_encodeRsaPublicKey(encodings[i]);
7200         test_decodeRsaPublicKey(encodings[i]);
7201         test_encodeSequenceOfAny(encodings[i]);
7202         test_decodeSequenceOfAny(encodings[i]);
7203         test_encodeExtensions(encodings[i]);
7204         test_decodeExtensions(encodings[i]);
7205         test_encodePublicKeyInfo(encodings[i]);
7206         test_decodePublicKeyInfo(encodings[i]);
7207         test_encodeCertToBeSigned(encodings[i]);
7208         test_decodeCertToBeSigned(encodings[i]);
7209         test_encodeCert(encodings[i]);
7210         test_decodeCert(encodings[i]);
7211         test_encodeCRLDistPoints(encodings[i]);
7212         test_decodeCRLDistPoints(encodings[i]);
7213         test_encodeCRLIssuingDistPoint(encodings[i]);
7214         test_decodeCRLIssuingDistPoint(encodings[i]);
7215         test_encodeCRLToBeSigned(encodings[i]);
7216         test_decodeCRLToBeSigned(encodings[i]);
7217         test_encodeEnhancedKeyUsage(encodings[i]);
7218         test_decodeEnhancedKeyUsage(encodings[i]);
7219         test_encodeAuthorityKeyId(encodings[i]);
7220         test_decodeAuthorityKeyId(encodings[i]);
7221         test_encodeAuthorityKeyId2(encodings[i]);
7222         test_decodeAuthorityKeyId2(encodings[i]);
7223         test_encodeAuthorityInfoAccess(encodings[i]);
7224         test_decodeAuthorityInfoAccess(encodings[i]);
7225         test_encodeCTL(encodings[i]);
7226         test_decodeCTL(encodings[i]);
7227         test_encodePKCSContentInfo(encodings[i]);
7228         test_decodePKCSContentInfo(encodings[i]);
7229         test_encodePKCSAttribute(encodings[i]);
7230         test_decodePKCSAttribute(encodings[i]);
7231         test_encodePKCSAttributes(encodings[i]);
7232         test_decodePKCSAttributes(encodings[i]);
7233         test_encodePKCSSMimeCapabilities(encodings[i]);
7234         test_decodePKCSSMimeCapabilities(encodings[i]);
7235         test_encodePKCSSignerInfo(encodings[i]);
7236         test_decodePKCSSignerInfo(encodings[i]);
7237         test_encodeCMSSignerInfo(encodings[i]);
7238         test_decodeCMSSignerInfo(encodings[i]);
7239         test_encodeNameConstraints(encodings[i]);
7240         test_decodeNameConstraints(encodings[i]);
7241     }
7242     testPortPublicKeyInfo();
7243 }