quartz: Remove superfluous pointer casts.
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
32
33 struct encodedInt
34 {
35     int val;
36     const BYTE *encoded;
37 };
38
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
46
47 static const struct encodedInt ints[] = {
48  { 1,          bin1 },
49  { 127,        bin2 },
50  { 128,        bin3 },
51  { 256,        bin4 },
52  { -128,       bin5 },
53  { -129,       bin6 },
54  { 0xbaddf00d, bin7 },
55 };
56
57 struct encodedBigInt
58 {
59     const BYTE *val;
60     const BYTE *encoded;
61     const BYTE *decoded;
62 };
63
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
67
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
71
72 static const struct encodedBigInt bigInts[] = {
73  { bin8, bin9, bin10 },
74  { bin11, bin12, bin13 },
75 };
76
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
81
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84  { bin14, bin15, NULL },
85  { bin16, bin17, NULL },
86 };
87
88 static void test_encodeInt(DWORD dwEncoding)
89 {
90     DWORD bufSize = 0;
91     int i;
92     BOOL ret;
93     CRYPT_INTEGER_BLOB blob;
94     BYTE *buf = NULL;
95
96     /* CryptEncodeObjectEx with NULL bufSize crashes..
97     ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98      NULL);
99      */
100     /* check bogus encoding */
101     ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102      &bufSize);
103     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105     if (0)
106     {
107         /* check with NULL integer buffer.  Windows XP incorrectly returns an
108          * NTSTATUS (crashes on win9x).
109          */
110         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111          &bufSize);
112         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
114     }
115     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
116     {
117         /* encode as normal integer */
118         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119          NULL, NULL, &bufSize);
120         ok(ret, "Expected success, got %d\n", GetLastError());
121         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124         if (buf)
125         {
126             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127              buf[0]);
128             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129              buf[1], ints[i].encoded[1]);
130             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132             LocalFree(buf);
133         }
134         /* encode as multibyte integer */
135         blob.cbData = sizeof(ints[i].val);
136         blob.pbData = (BYTE *)&ints[i].val;
137         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138          0, NULL, NULL, &bufSize);
139         ok(ret, "Expected success, got %d\n", GetLastError());
140         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143         if (buf)
144         {
145             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146              buf[0]);
147             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148              buf[1], ints[i].encoded[1]);
149             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151             LocalFree(buf);
152         }
153     }
154     /* encode a couple bigger ints, just to show it's little-endian and leading
155      * sign bytes are dropped
156      */
157     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158     {
159         blob.cbData = strlen((const char*)bigInts[i].val);
160         blob.pbData = (BYTE *)bigInts[i].val;
161         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162          0, NULL, NULL, &bufSize);
163         ok(ret, "Expected success, got %d\n", GetLastError());
164         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167         if (buf)
168         {
169             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170              buf[0]);
171             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172              buf[1], bigInts[i].encoded[1]);
173             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174              bigInts[i].encoded[1] + 1),
175              "Encoded value didn't match expected\n");
176             LocalFree(buf);
177         }
178     }
179     /* and, encode some uints */
180     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181     {
182         blob.cbData = strlen((const char*)bigUInts[i].val);
183         blob.pbData = (BYTE*)bigUInts[i].val;
184         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185          0, NULL, NULL, &bufSize);
186         ok(ret, "Expected success, got %d\n", GetLastError());
187         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190         if (buf)
191         {
192             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193              buf[0]);
194             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195              buf[1], bigUInts[i].encoded[1]);
196             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197              bigUInts[i].encoded[1] + 1),
198              "Encoded value didn't match expected\n");
199             LocalFree(buf);
200         }
201     }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211     BYTE *buf = NULL;
212     DWORD bufSize = 0;
213     int i;
214     BOOL ret;
215
216     /* CryptDecodeObjectEx with NULL bufSize crashes..
217     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219      */
220     /* check bogus encoding */
221     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225     /* check with NULL integer buffer */
226     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227      &bufSize);
228     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229      GetLastError() == OSS_BAD_ARG /* Win9x */),
230      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231     /* check with a valid, but too large, integer */
232     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
234     ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
235      broken(ret) /* Win9x */,
236      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
237     /* check with a DER-encoded string */
238     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
239      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
240     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
241      GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
242      "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
243      GetLastError());
244     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
245     {
246         /* When the output buffer is NULL, this always succeeds */
247         SetLastError(0xdeadbeef);
248         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250          &bufSize);
251         ok(ret && GetLastError() == NOERROR,
252          "Expected success and NOERROR, got %d\n", GetLastError());
253         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254          ints[i].encoded, ints[i].encoded[1] + 2,
255          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
256         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
257         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
258         ok(buf != NULL, "Expected allocated buffer\n");
259         if (buf)
260         {
261             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262              ints[i].val, *(int *)buf);
263             LocalFree(buf);
264         }
265     }
266     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
267     {
268         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270          &bufSize);
271         ok(ret && GetLastError() == NOERROR,
272          "Expected success and NOERROR, got %d\n", GetLastError());
273         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
276         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278         ok(buf != NULL, "Expected allocated buffer\n");
279         if (buf)
280         {
281             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
282
283             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285              blob->cbData);
286             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287              "Unexpected value\n");
288             LocalFree(buf);
289         }
290     }
291     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
292     {
293         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295          &bufSize);
296         ok(ret && GetLastError() == NOERROR,
297          "Expected success and NOERROR, got %d\n", GetLastError());
298         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
301         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303         ok(buf != NULL, "Expected allocated buffer\n");
304         if (buf)
305         {
306             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
307
308             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310              blob->cbData);
311             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312              "Unexpected value\n");
313             LocalFree(buf);
314         }
315     }
316     /* Decode the value 1 with long-form length */
317     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
319     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320     if (buf)
321     {
322         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323         LocalFree(buf);
324     }
325     /* check with extra bytes at the end */
326     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
328     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329     if (buf)
330     {
331         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332         LocalFree(buf);
333     }
334     /* Try to decode some bogus large items */
335     /* The buffer size is smaller than the encoded length, so this should fail
336      * with CRYPT_E_ASN1_EOD if it's being decoded.
337      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339      * So this test unfortunately isn't useful.
340     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
342     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
344      */
345     /* This will try to decode the buffer and overflow it, check that it's
346      * caught.
347      */
348     if (0)
349     {
350     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
353     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
355     }
356 }
357
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
360
361 /* These are always encoded unsigned, and aren't constrained to be any
362  * particular value
363  */
364 static const struct encodedInt enums[] = {
365  { 1,    bin18 },
366  { -128, bin19 },
367 };
368
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370  * X509_ENUMERATED.
371  */
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373  szOID_CRL_REASON_CODE };
374
375 static void test_encodeEnumerated(DWORD dwEncoding)
376 {
377     DWORD i, j;
378
379     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
380     {
381         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
382         {
383             BOOL ret;
384             BYTE *buf = NULL;
385             DWORD bufSize = 0;
386
387             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
389              &bufSize);
390             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391             if (buf)
392             {
393                 ok(buf[0] == 0xa,
394                  "Got unexpected type %d for enumerated (expected 0xa)\n",
395                  buf[0]);
396                 ok(buf[1] == enums[j].encoded[1],
397                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399                  enums[j].encoded[1] + 1),
400                  "Encoded value of 0x%08x didn't match expected\n",
401                  enums[j].val);
402                 LocalFree(buf);
403             }
404         }
405     }
406 }
407
408 static void test_decodeEnumerated(DWORD dwEncoding)
409 {
410     DWORD i, j;
411
412     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
413     {
414         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
415         {
416             BOOL ret;
417             DWORD bufSize = sizeof(int);
418             int val;
419
420             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422              &val, &bufSize);
423             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424             ok(bufSize == sizeof(int),
425              "Got unexpected size %d for enumerated\n", bufSize);
426             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427              val, enums[j].val);
428         }
429     }
430 }
431
432 struct encodedFiletime
433 {
434     SYSTEMTIME sysTime;
435     const BYTE *encodedTime;
436 };
437
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439  const struct encodedFiletime *time)
440 {
441     FILETIME ft = { 0 };
442     BYTE *buf = NULL;
443     DWORD bufSize = 0;
444     BOOL ret;
445
446     ret = SystemTimeToFileTime(&time->sysTime, &ft);
447     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
450     /* years other than 1950-2050 are not allowed for encodings other than
451      * X509_CHOICE_OF_TIME.
452      */
453     if (structType == X509_CHOICE_OF_TIME ||
454      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
455     {
456         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457          GetLastError());
458         ok(buf != NULL, "Expected an allocated buffer\n");
459         if (buf)
460         {
461             ok(buf[0] == time->encodedTime[0],
462              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463              buf[0]);
464             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465              time->encodedTime[1], bufSize);
466             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467              "Got unexpected value for time encoding\n");
468             LocalFree(buf);
469         }
470     }
471     else
472         ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473          broken(GetLastError() == ERROR_SUCCESS),
474          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
475 }
476
477 static const char *printSystemTime(const SYSTEMTIME *st)
478 {
479     static char buf[25];
480
481     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483     return buf;
484 }
485
486 static const char *printFileTime(const FILETIME *ft)
487 {
488     static char buf[25];
489     SYSTEMTIME st;
490
491     FileTimeToSystemTime(ft, &st);
492     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494     return buf;
495 }
496
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
498 {
499     SYSTEMTIME st;
500
501     FileTimeToSystemTime(got, &st);
502     ok((expected->wYear == st.wYear &&
503      expected->wMonth == st.wMonth &&
504      expected->wDay == st.wDay &&
505      expected->wHour == st.wHour &&
506      expected->wMinute == st.wMinute &&
507      expected->wSecond == st.wSecond &&
508      abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509      /* Some Windows systems only seem to be accurate in their time decoding to
510       * within about an hour.
511       */
512      broken(expected->wYear == st.wYear &&
513      expected->wMonth == st.wMonth &&
514      expected->wDay == st.wDay &&
515      abs(expected->wHour - st.wHour) <= 1),
516      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517      printSystemTime(expected), printFileTime(got));
518 }
519
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521  const struct encodedFiletime *time)
522 {
523     FILETIME ft = { 0 };
524     DWORD size = sizeof(ft);
525     BOOL ret;
526
527     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529     /* years other than 1950-2050 are not allowed for encodings other than
530      * X509_CHOICE_OF_TIME.
531      */
532     if (structType == X509_CHOICE_OF_TIME ||
533      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
534     {
535         ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536          "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537          GetLastError());
538         if (ret)
539             compareTime(&time->sysTime, &ft);
540     }
541     else
542         ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543          GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544          "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545          GetLastError());
546 }
547
548 static const BYTE bin20[] = {
549     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
554
555 static const struct encodedFiletime times[] = {
556  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
559 };
560
561 static void test_encodeFiletime(DWORD dwEncoding)
562 {
563     DWORD i;
564
565     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
566     {
567         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
570     }
571 }
572
573 static const BYTE bin23[] = {
574     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598     0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602     0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604     0x18,0x08, '2','1','4','5','0','6','0','6'};
605
606 static void test_decodeFiletime(DWORD dwEncoding)
607 {
608     static const struct encodedFiletime otherTimes[] = {
609      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
610      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
612      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
613      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
614      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
615      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
616      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
617      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
618      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
619      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
620      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
621     };
622     /* An oddball case that succeeds in Windows, but doesn't seem correct
623      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
624      */
625     static const unsigned char *bogusTimes[] = {
626      /* oddly, this succeeds on Windows, with year 2765
627      "\x18" "\x0f" "21r50606161000Z",
628       */
629      bin35,
630      bin36,
631      bin37,
632      bin38,
633     };
634     DWORD i, size;
635     FILETIME ft1 = { 0 }, ft2 = { 0 };
636     BOOL ret;
637
638     /* Check bogus length with non-NULL buffer */
639     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641     size = 1;
642     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644     ok(!ret && GetLastError() == ERROR_MORE_DATA,
645      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646     /* Normal tests */
647     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
648     {
649         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
652     }
653     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
654     {
655         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
658     }
659     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
660     {
661         size = sizeof(ft1);
662         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664         ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665                      GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666            broken(ret), /* Win9x and NT4 for bin38 */
667          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668          GetLastError());
669     }
670 }
671
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
674
675 static const BYTE emptySequence[] = { 0x30, 0 };
676 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
677 static const BYTE twoRDNs[] = {
678     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
679     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
680     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
681 static const BYTE encodedTwoRDNs[] = {
682 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
683 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
684 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
685 0x6e,0x67,0x00,
686 };
687
688 static const BYTE us[] = { 0x55, 0x53 };
689 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
690  0x74, 0x61 };
691 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
692  0x6f, 0x6c, 0x69, 0x73 };
693 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
694  0x76, 0x65, 0x72, 0x73 };
695 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
696  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
697 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
698  0x73, 0x74 };
699 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
700  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
701
702 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
703 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
704
705 static CHAR oid_us[]            = "2.5.4.6",
706             oid_minnesota[]     = "2.5.4.8",
707             oid_minneapolis[]   = "2.5.4.7",
708             oid_codeweavers[]   = "2.5.4.10",
709             oid_wine[]          = "2.5.4.11",
710             oid_localhostAttr[] = "2.5.4.3",
711             oid_aric[]          = "1.2.840.113549.1.9.1";
712 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
713                                     { RDNA(minnesota) },
714                                     { RDNA(minneapolis) },
715                                     { RDNA(codeweavers) },
716                                     { RDNA(wine) },
717                                     { RDNA(localhostAttr) },
718                                     { RDNIA5(aric) } };
719 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
720                                            { RDNA(localhostAttr) },
721                                            { RDNA(minnesota) },
722                                            { RDNA(minneapolis) },
723                                            { RDNA(codeweavers) },
724                                            { RDNA(wine) },
725                                            { RDNIA5(aric) } };
726
727 #undef RDNIA5
728 #undef RDNA
729
730 static const BYTE encodedRDNAttrs[] = {
731 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
732 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
733 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
734 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
735 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
736 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
737 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
738 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
739 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
740 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
741 };
742
743 static void test_encodeName(DWORD dwEncoding)
744 {
745     CERT_RDN_ATTR attrs[2];
746     CERT_RDN rdn;
747     CERT_NAME_INFO info;
748     static CHAR oid_common_name[] = szOID_COMMON_NAME,
749                 oid_sur_name[]    = szOID_SUR_NAME;
750     BYTE *buf = NULL;
751     DWORD size = 0;
752     BOOL ret;
753
754     if (0)
755     {
756         /* Test with NULL pvStructInfo (crashes on win9x) */
757         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
758          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
759         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
760          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
761     }
762     /* Test with empty CERT_NAME_INFO */
763     info.cRDN = 0;
764     info.rgRDN = NULL;
765     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
767     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
768     if (buf)
769     {
770         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771          "Got unexpected encoding for empty name\n");
772         LocalFree(buf);
773     }
774     if (0)
775     {
776         /* Test with bogus CERT_RDN (crashes on win9x) */
777         info.cRDN = 1;
778         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
780         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
781          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
782     }
783     /* Test with empty CERT_RDN */
784     rdn.cRDNAttr = 0;
785     rdn.rgRDNAttr = NULL;
786     info.cRDN = 1;
787     info.rgRDN = &rdn;
788     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
789      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
790     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
791     if (buf)
792     {
793         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794          "Got unexpected encoding for empty RDN array\n");
795         LocalFree(buf);
796     }
797     if (0)
798     {
799         /* Test with bogus attr array (crashes on win9x) */
800         rdn.cRDNAttr = 1;
801         rdn.rgRDNAttr = NULL;
802         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
803          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
804         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
805          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
806     }
807     /* oddly, a bogus OID is accepted by Windows XP; not testing.
808     attrs[0].pszObjId = "bogus";
809     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
810     attrs[0].Value.cbData = sizeof(commonName);
811     attrs[0].Value.pbData = commonName;
812     rdn.cRDNAttr = 1;
813     rdn.rgRDNAttr = attrs;
814     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
815      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
816     ok(!ret, "Expected failure, got success\n");
817      */
818     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
819      * the encoded attributes to be swapped.
820      */
821     attrs[0].pszObjId = oid_common_name;
822     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
823     attrs[0].Value.cbData = sizeof(commonName);
824     attrs[0].Value.pbData = (BYTE *)commonName;
825     attrs[1].pszObjId = oid_sur_name;
826     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
827     attrs[1].Value.cbData = sizeof(surName);
828     attrs[1].Value.pbData = (BYTE *)surName;
829     rdn.cRDNAttr = 2;
830     rdn.rgRDNAttr = attrs;
831     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
832      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
833     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
834     if (buf)
835     {
836         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837          "Got unexpected encoding for two RDN array\n");
838         LocalFree(buf);
839     }
840     /* A name can be "encoded" with previously encoded RDN attrs. */
841     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
842     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
843     attrs[0].Value.cbData = sizeof(twoRDNs);
844     rdn.cRDNAttr = 1;
845     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
846      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
847     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
848     if (buf)
849     {
850         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851         ok(!memcmp(buf, encodedTwoRDNs, size),
852          "Unexpected value for re-endoded two RDN array\n");
853         LocalFree(buf);
854     }
855     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
856     rdn.cRDNAttr = 1;
857     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
858     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
859      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
860     ok(!ret && GetLastError() == E_INVALIDARG,
861      "Expected E_INVALIDARG, got %08x\n", GetLastError());
862     /* Test a more complex name */
863     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
864     rdn.rgRDNAttr = rdnAttrs;
865     info.cRDN = 1;
866     info.rgRDN = &rdn;
867     buf = NULL;
868     size = 0;
869     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
870      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
871     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
872     if (ret)
873     {
874         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
875         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
876         LocalFree(buf);
877     }
878 }
879
880 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
881 static WCHAR surNameW[] = { 'L','a','n','g',0 };
882
883 static const BYTE twoRDNsNoNull[] = {
884  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
885  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
886  0x20,0x4c,0x61,0x6e,0x67 };
887 static const BYTE anyType[] = {
888  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
889  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
890  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
891  0x61,0x4c,0x67,0x6e };
892
893 static void test_encodeUnicodeName(DWORD dwEncoding)
894 {
895     CERT_RDN_ATTR attrs[2];
896     CERT_RDN rdn;
897     CERT_NAME_INFO info;
898     static CHAR oid_common_name[] = szOID_COMMON_NAME,
899                 oid_sur_name[]    = szOID_SUR_NAME;
900     BYTE *buf = NULL;
901     DWORD size = 0;
902     BOOL ret;
903
904     if (0)
905     {
906         /* Test with NULL pvStructInfo (crashes on win9x) */
907         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
908          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
909         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
910          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
911     }
912     /* Test with empty CERT_NAME_INFO */
913     info.cRDN = 0;
914     info.rgRDN = NULL;
915     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
916      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
917     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
918     if (buf)
919     {
920         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921          "Got unexpected encoding for empty name\n");
922         LocalFree(buf);
923     }
924     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925      * encoding (the NULL).
926      */
927     attrs[0].pszObjId = oid_common_name;
928     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
929     attrs[0].Value.cbData = sizeof(commonNameW);
930     attrs[0].Value.pbData = (BYTE *)commonNameW;
931     rdn.cRDNAttr = 1;
932     rdn.rgRDNAttr = attrs;
933     info.cRDN = 1;
934     info.rgRDN = &rdn;
935     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
937     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
938      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
939     ok(size == 9, "Unexpected error index %08x\n", size);
940     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
941      * forces the order of the encoded attributes to be swapped.
942      */
943     attrs[0].pszObjId = oid_common_name;
944     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
945     attrs[0].Value.cbData = 0;
946     attrs[0].Value.pbData = (BYTE *)commonNameW;
947     attrs[1].pszObjId = oid_sur_name;
948     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
949     attrs[1].Value.cbData = 0;
950     attrs[1].Value.pbData = (BYTE *)surNameW;
951     rdn.cRDNAttr = 2;
952     rdn.rgRDNAttr = attrs;
953     info.cRDN = 1;
954     info.rgRDN = &rdn;
955     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
956      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
957     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
958     if (buf)
959     {
960         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961          "Got unexpected encoding for two RDN array\n");
962         LocalFree(buf);
963     }
964     /* A name can be "encoded" with previously encoded RDN attrs. */
965     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
966     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
967     attrs[0].Value.cbData = sizeof(twoRDNs);
968     rdn.cRDNAttr = 1;
969     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
970      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
971     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
972     if (buf)
973     {
974         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975         ok(!memcmp(buf, encodedTwoRDNs, size),
976          "Unexpected value for re-endoded two RDN array\n");
977         LocalFree(buf);
978     }
979     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980     rdn.cRDNAttr = 1;
981     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
984     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985     if (buf)
986     {
987         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989         LocalFree(buf);
990     }
991 }
992
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994  const CERT_NAME_VALUE *got)
995 {
996     if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
997         got->dwValueType == CERT_RDN_ENCODED_BLOB)
998     {
999         win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
1000         return;
1001     }
1002
1003     ok(got->dwValueType == expected->dwValueType,
1004      "Expected string type %d, got %d\n", expected->dwValueType,
1005      got->dwValueType);
1006     ok(got->Value.cbData == expected->Value.cbData,
1007      "String type %d: unexpected data size, got %d, expected %d\n",
1008      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1009     if (got->Value.cbData && got->Value.pbData)
1010         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1011          min(got->Value.cbData, expected->Value.cbData)),
1012          "String type %d: unexpected value\n", expected->dwValueType);
1013 }
1014
1015 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1016  const CERT_RDN_ATTR *got)
1017 {
1018     if (expected->pszObjId && strlen(expected->pszObjId))
1019     {
1020         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1021          expected->pszObjId);
1022         if (got->pszObjId)
1023         {
1024             ok(!strcmp(got->pszObjId, expected->pszObjId),
1025              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1026              expected->pszObjId);
1027         }
1028     }
1029     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1030      (const CERT_NAME_VALUE *)&got->dwValueType);
1031 }
1032
1033 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1034 {
1035     ok(got->cRDNAttr == expected->cRDNAttr,
1036      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1037     if (got->cRDNAttr)
1038     {
1039         DWORD i;
1040
1041         for (i = 0; i < got->cRDNAttr; i++)
1042             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1043     }
1044 }
1045
1046 static void compareNames(const CERT_NAME_INFO *expected,
1047  const CERT_NAME_INFO *got)
1048 {
1049     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1050      expected->cRDN, got->cRDN);
1051     if (got->cRDN)
1052     {
1053         DWORD i;
1054
1055         for (i = 0; i < got->cRDN; i++)
1056             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1057     }
1058 }
1059
1060 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1061 static const BYTE twoRDNsExtraBytes[] = {
1062     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1063     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1064     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1065
1066 static void test_decodeName(DWORD dwEncoding)
1067 {
1068     BYTE *buf = NULL;
1069     DWORD bufSize = 0;
1070     BOOL ret;
1071     CERT_RDN rdn;
1072     CERT_NAME_INFO info = { 1, &rdn };
1073
1074     /* test empty name */
1075     bufSize = 0;
1076     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1077      emptySequence[1] + 2,
1078      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1079      &buf, &bufSize);
1080     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1081     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1082      * decoder works the same way, so only test the count.
1083      */
1084     if (buf)
1085     {
1086         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1087         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1088          "Expected 0 RDNs in empty info, got %d\n",
1089          ((CERT_NAME_INFO *)buf)->cRDN);
1090         LocalFree(buf);
1091     }
1092     /* test empty name with indefinite-length encoding */
1093     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1094      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1095      &buf, &bufSize);
1096     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1097     if (ret)
1098     {
1099         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1100         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1101          "Expected 0 RDNs in empty info, got %d\n",
1102          ((CERT_NAME_INFO *)buf)->cRDN);
1103         LocalFree(buf);
1104     }
1105     /* test empty RDN */
1106     bufSize = 0;
1107     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1108      emptyRDNs[1] + 2,
1109      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1110      &buf, &bufSize);
1111     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1112     if (buf)
1113     {
1114         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1115
1116         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1117          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1118          "Got unexpected value for empty RDN\n");
1119         LocalFree(buf);
1120     }
1121     /* test two RDN attrs */
1122     bufSize = 0;
1123     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1124      twoRDNs[1] + 2,
1125      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1126      &buf, &bufSize);
1127     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1128     if (buf)
1129     {
1130         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1131                     oid_common_name[] = szOID_COMMON_NAME;
1132
1133         CERT_RDN_ATTR attrs[] = {
1134          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1135           (BYTE *)surName } },
1136          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1137           (BYTE *)commonName } },
1138         };
1139
1140         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1141         rdn.rgRDNAttr = attrs;
1142         compareNames(&info, (CERT_NAME_INFO *)buf);
1143         LocalFree(buf);
1144     }
1145     /* test that two RDN attrs with extra bytes succeeds */
1146     bufSize = 0;
1147     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1148      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1149     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1150     /* And, a slightly more complicated name */
1151     buf = NULL;
1152     bufSize = 0;
1153     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1154      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1155     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1156     if (ret)
1157     {
1158         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1159         rdn.rgRDNAttr = decodedRdnAttrs;
1160         compareNames(&info, (CERT_NAME_INFO *)buf);
1161         LocalFree(buf);
1162     }
1163 }
1164
1165 static void test_decodeUnicodeName(DWORD dwEncoding)
1166 {
1167     BYTE *buf = NULL;
1168     DWORD bufSize = 0;
1169     BOOL ret;
1170     CERT_RDN rdn;
1171     CERT_NAME_INFO info = { 1, &rdn };
1172
1173     /* test empty name */
1174     bufSize = 0;
1175     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1176      emptySequence[1] + 2,
1177      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1178      &buf, &bufSize);
1179     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1180     if (buf)
1181     {
1182         ok(bufSize == sizeof(CERT_NAME_INFO),
1183          "Got wrong bufSize %d\n", bufSize);
1184         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1185          "Expected 0 RDNs in empty info, got %d\n",
1186          ((CERT_NAME_INFO *)buf)->cRDN);
1187         LocalFree(buf);
1188     }
1189     /* test empty RDN */
1190     bufSize = 0;
1191     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1192      emptyRDNs[1] + 2,
1193      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1194      &buf, &bufSize);
1195     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1196     if (buf)
1197     {
1198         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1199
1200         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1201          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1202          "Got unexpected value for empty RDN\n");
1203         LocalFree(buf);
1204     }
1205     /* test two RDN attrs */
1206     bufSize = 0;
1207     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1208      sizeof(twoRDNsNoNull),
1209      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1210      &buf, &bufSize);
1211     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1212     if (buf)
1213     {
1214         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1215                     oid_common_name[] = szOID_COMMON_NAME;
1216
1217         CERT_RDN_ATTR attrs[] = {
1218          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1219          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1220          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1221          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1222         };
1223
1224         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1225         rdn.rgRDNAttr = attrs;
1226         compareNames(&info, (CERT_NAME_INFO *)buf);
1227         LocalFree(buf);
1228     }
1229 }
1230
1231 struct EncodedNameValue
1232 {
1233     CERT_NAME_VALUE value;
1234     const BYTE *encoded;
1235     DWORD encodedSize;
1236 };
1237
1238 static const char bogusIA5[] = "\x80";
1239 static const char bogusPrintable[] = "~";
1240 static const char bogusNumeric[] = "A";
1241 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1242 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1243 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1244 static BYTE octetCommonNameValue[] = {
1245  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1246 static BYTE numericCommonNameValue[] = {
1247  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1248 static BYTE printableCommonNameValue[] = {
1249  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250 static BYTE t61CommonNameValue[] = {
1251  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1252 static BYTE videotexCommonNameValue[] = {
1253  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1254 static BYTE ia5CommonNameValue[] = {
1255  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1256 static BYTE graphicCommonNameValue[] = {
1257  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1258 static BYTE visibleCommonNameValue[] = {
1259  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1260 static BYTE generalCommonNameValue[] = {
1261  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1262 static BYTE bmpCommonNameValue[] = {
1263  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1264  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1265 static BYTE utf8CommonNameValue[] = {
1266  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1267
1268 static struct EncodedNameValue nameValues[] = {
1269  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1270      octetCommonNameValue, sizeof(octetCommonNameValue) },
1271  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1272      numericCommonNameValue, sizeof(numericCommonNameValue) },
1273  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1274      printableCommonNameValue, sizeof(printableCommonNameValue) },
1275  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1276      t61CommonNameValue, sizeof(t61CommonNameValue) },
1277  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1278      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1279  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1280      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1281  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1282      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1283  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1284      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1285  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1286      generalCommonNameValue, sizeof(generalCommonNameValue) },
1287  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1288      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1289  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1290      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1291  /* The following tests succeed under Windows, but really should fail,
1292   * they contain characters that are illegal for the encoding.  I'm
1293   * including them to justify my lazy encoding.
1294   */
1295  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1296      sizeof(bin42) },
1297  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1298      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1299  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1300      bin44, sizeof(bin44) },
1301 };
1302
1303 static void test_encodeNameValue(DWORD dwEncoding)
1304 {
1305     BYTE *buf = NULL;
1306     DWORD size = 0, i;
1307     BOOL ret;
1308     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1309
1310     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1311     value.Value.pbData = printableCommonNameValue;
1312     value.Value.cbData = sizeof(printableCommonNameValue);
1313     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1314      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1315     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1316     if (buf)
1317     {
1318         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1319          size);
1320         ok(!memcmp(buf, printableCommonNameValue, size),
1321          "Unexpected encoding\n");
1322         LocalFree(buf);
1323     }
1324     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1325     {
1326         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1327          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1328         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1329          "Type %d: CryptEncodeObjectEx failed: %08x\n",
1330          nameValues[i].value.dwValueType, GetLastError());
1331         if (ret)
1332         {
1333             ok(size == nameValues[i].encodedSize,
1334              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1335             ok(!memcmp(buf, nameValues[i].encoded, size),
1336              "Got unexpected encoding\n");
1337             LocalFree(buf);
1338         }
1339     }
1340 }
1341
1342 static void test_decodeNameValue(DWORD dwEncoding)
1343 {
1344     int i;
1345     BYTE *buf = NULL;
1346     DWORD bufSize = 0;
1347     BOOL ret;
1348
1349     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1350     {
1351         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1352          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1353          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1354          &buf, &bufSize);
1355         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1356          nameValues[i].value.dwValueType, GetLastError());
1357         if (ret)
1358         {
1359             compareNameValues(&nameValues[i].value,
1360              (const CERT_NAME_VALUE *)buf);
1361             LocalFree(buf);
1362         }
1363     }
1364 }
1365
1366 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1367 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1368 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1369  'h','q','.','o','r','g',0 };
1370 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1371  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1372  0x6f, 0x72, 0x67 };
1373 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1374  0x575b, 0 };
1375 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1376 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1377  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1378 static const BYTE localhost[] = { 127, 0, 0, 1 };
1379 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1380  0x01 };
1381 static const unsigned char encodedCommonName[] = {
1382     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1383 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1384 static const BYTE encodedDirectoryName[] = {
1385 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1386 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1387
1388 static void test_encodeAltName(DWORD dwEncoding)
1389 {
1390     CERT_ALT_NAME_INFO info = { 0 };
1391     CERT_ALT_NAME_ENTRY entry = { 0 };
1392     BYTE *buf = NULL;
1393     DWORD size = 0;
1394     BOOL ret;
1395     char oid[] = "1.2.3";
1396
1397     /* Test with empty info */
1398     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1399      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1400     if (buf)
1401     {
1402         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1403         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1404         LocalFree(buf);
1405     }
1406     /* Test with an empty entry */
1407     info.cAltEntry = 1;
1408     info.rgAltEntry = &entry;
1409     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1410      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1411     ok(!ret && GetLastError() == E_INVALIDARG,
1412      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1413     /* Test with an empty pointer */
1414     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1415     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1416      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1417     if (buf)
1418     {
1419         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1420         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1421         LocalFree(buf);
1422     }
1423     /* Test with a real URL */
1424     U(entry).pwszURL = (LPWSTR)url;
1425     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1426      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1427     if (buf)
1428     {
1429         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1430         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1431         LocalFree(buf);
1432     }
1433     /* Now with the URL containing an invalid IA5 char */
1434     U(entry).pwszURL = (LPWSTR)nihongoURL;
1435     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1436      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1437     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1438      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1439     /* The first invalid character is at index 7 */
1440     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1441      "Expected invalid char at index 7, got %d\n",
1442      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1443     /* Now with the URL missing a scheme */
1444     U(entry).pwszURL = (LPWSTR)dnsName;
1445     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1446      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1447     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1448     if (buf)
1449     {
1450         /* This succeeds, but it shouldn't, so don't worry about conforming */
1451         LocalFree(buf);
1452     }
1453     /* Now with a DNS name */
1454     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1455     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1456      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1457     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1458     if (buf)
1459     {
1460         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1461         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1462         LocalFree(buf);
1463     }
1464     /* Test with an IP address */
1465     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1466     U(entry).IPAddress.cbData = sizeof(localhost);
1467     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1468     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1469      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1470     if (buf)
1471     {
1472         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1473         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1474         LocalFree(buf);
1475     }
1476     /* Test with OID */
1477     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1478     U(entry).pszRegisteredID = oid;
1479     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1480      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1481     if (buf)
1482     {
1483         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1484         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1485         LocalFree(buf);
1486     }
1487     /* Test with directory name */
1488     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1489     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1490     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1491     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1492      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1493     if (buf)
1494     {
1495         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1496         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1497         LocalFree(buf);
1498     }
1499 }
1500
1501 static void test_decodeAltName(DWORD dwEncoding)
1502 {
1503     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1504      0x00, 0x00, 0x01 };
1505     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1506      0x01 };
1507     BOOL ret;
1508     BYTE *buf = NULL;
1509     DWORD bufSize = 0;
1510     CERT_ALT_NAME_INFO *info;
1511
1512     /* Test some bogus ones first */
1513     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1514      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1515      NULL, &buf, &bufSize);
1516     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1517      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1518      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1519      GetLastError());
1520     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1521      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1522      &bufSize);
1523     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1524      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1525      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1526      GetLastError());
1527     /* Now expected cases */
1528     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1529      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1530     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1531     if (buf)
1532     {
1533         info = (CERT_ALT_NAME_INFO *)buf;
1534
1535         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1536          info->cAltEntry);
1537         LocalFree(buf);
1538     }
1539     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1540      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1541     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1542     if (buf)
1543     {
1544         info = (CERT_ALT_NAME_INFO *)buf;
1545
1546         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1547          info->cAltEntry);
1548         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1549          "Expected CERT_ALT_NAME_URL, got %d\n",
1550          info->rgAltEntry[0].dwAltNameChoice);
1551         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1552          "Expected empty URL\n");
1553         LocalFree(buf);
1554     }
1555     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1556      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1557     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1558     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1559      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1560     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1561     if (buf)
1562     {
1563         info = (CERT_ALT_NAME_INFO *)buf;
1564
1565         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1566          info->cAltEntry);
1567         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1568          "Expected CERT_ALT_NAME_URL, got %d\n",
1569          info->rgAltEntry[0].dwAltNameChoice);
1570         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1571         LocalFree(buf);
1572     }
1573     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1574      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1575     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1576     if (buf)
1577     {
1578         info = (CERT_ALT_NAME_INFO *)buf;
1579
1580         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1581          info->cAltEntry);
1582         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1583          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1584          info->rgAltEntry[0].dwAltNameChoice);
1585         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1586          "Unexpected DNS name\n");
1587         LocalFree(buf);
1588     }
1589     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1590      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1591     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1592     if (buf)
1593     {
1594         info = (CERT_ALT_NAME_INFO *)buf;
1595
1596         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1597          info->cAltEntry);
1598         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1599          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1600          info->rgAltEntry[0].dwAltNameChoice);
1601         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1602          "Unexpected IP address length %d\n",
1603           U(info->rgAltEntry[0]).IPAddress.cbData);
1604         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1605          sizeof(localhost)), "Unexpected IP address value\n");
1606         LocalFree(buf);
1607     }
1608     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1609      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1610     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1611     if (buf)
1612     {
1613         info = (CERT_ALT_NAME_INFO *)buf;
1614
1615         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1616          info->cAltEntry);
1617         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1618          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1619          info->rgAltEntry[0].dwAltNameChoice);
1620         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1621            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1622         LocalFree(buf);
1623     }
1624     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1625      encodedDirectoryName, sizeof(encodedDirectoryName),
1626      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1627     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1628     if (buf)
1629     {
1630         info = (CERT_ALT_NAME_INFO *)buf;
1631
1632         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1633          info->cAltEntry);
1634         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1635          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1636          info->rgAltEntry[0].dwAltNameChoice);
1637         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1638          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1639           U(info->rgAltEntry[0]).DirectoryName.cbData);
1640         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1641          encodedCommonName, sizeof(encodedCommonName)),
1642          "Unexpected directory name value\n");
1643         LocalFree(buf);
1644     }
1645 }
1646
1647 struct UnicodeExpectedError
1648 {
1649     DWORD   valueType;
1650     LPCWSTR str;
1651     DWORD   errorIndex;
1652     DWORD   error;
1653 };
1654
1655 static const WCHAR oneW[] = { '1',0 };
1656 static const WCHAR aW[] = { 'a',0 };
1657 static const WCHAR quoteW[] = { '"', 0 };
1658
1659 static struct UnicodeExpectedError unicodeErrors[] = {
1660  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1661  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1662  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1663  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1664  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1665  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1666 };
1667
1668 struct UnicodeExpectedResult
1669 {
1670     DWORD           valueType;
1671     LPCWSTR         str;
1672     CRYPT_DATA_BLOB encoded;
1673 };
1674
1675 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1676 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1677 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1678 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1679 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1680 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1681 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1682 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1683 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1684 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1685 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1686 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1687  0x5b };
1688 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1689  0x6f,0x5b };
1690 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1691  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1692 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1693  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1694
1695 static struct UnicodeExpectedResult unicodeResults[] = {
1696  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1697  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1698  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1699  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1700  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1701  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1702  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1703  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1704  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1705  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1706  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1707  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1708  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1709 };
1710
1711 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1712  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1713  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1714 };
1715
1716 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1717 {
1718     BYTE *buf = NULL;
1719     DWORD size = 0, i;
1720     BOOL ret;
1721     CERT_NAME_VALUE value;
1722
1723     if (0)
1724     {
1725         /* Crashes on win9x */
1726         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1727          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1728         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1729          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1730     }
1731     /* Have to have a string of some sort */
1732     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1733     value.Value.pbData = NULL;
1734     value.Value.cbData = 0;
1735     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1736      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1737     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1738      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1739     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1740     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1741      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1742     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1743      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1744     value.dwValueType = CERT_RDN_ANY_TYPE;
1745     value.Value.pbData = (LPBYTE)oneW;
1746     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1747      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1748     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1749      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1750     value.Value.cbData = sizeof(oneW);
1751     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1752      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1753     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1754      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1755     /* An encoded string with specified length isn't good enough either */
1756     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1757     value.Value.pbData = oneUniversal;
1758     value.Value.cbData = sizeof(oneUniversal);
1759     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1760      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1761     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1762      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1763     /* More failure checking */
1764     value.Value.cbData = 0;
1765     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1766     {
1767         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1768         value.dwValueType = unicodeErrors[i].valueType;
1769         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1770          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1771         ok(!ret && GetLastError() == unicodeErrors[i].error,
1772          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1773          unicodeErrors[i].error, GetLastError());
1774         ok(size == unicodeErrors[i].errorIndex,
1775          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1776          size);
1777     }
1778     /* cbData can be zero if the string is NULL-terminated */
1779     value.Value.cbData = 0;
1780     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1781     {
1782         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1783         value.dwValueType = unicodeResults[i].valueType;
1784         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1785          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1786         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1787          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1788         if (buf)
1789         {
1790             ok(size == unicodeResults[i].encoded.cbData,
1791              "Value type %d: expected size %d, got %d\n",
1792              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1793             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1794              "Value type %d: unexpected value\n", value.dwValueType);
1795             LocalFree(buf);
1796         }
1797     }
1798     /* These "encode," but they do so by truncating each unicode character
1799      * rather than properly encoding it.  Kept separate from the proper results,
1800      * because the encoded forms won't decode to their original strings.
1801      */
1802     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1803     {
1804         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1805         value.dwValueType = unicodeWeirdness[i].valueType;
1806         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1807          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1808         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1809         if (buf)
1810         {
1811             ok(size == unicodeWeirdness[i].encoded.cbData,
1812              "Value type %d: expected size %d, got %d\n",
1813              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1814             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1815              "Value type %d: unexpected value\n", value.dwValueType);
1816             LocalFree(buf);
1817         }
1818     }
1819 }
1820
1821 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1822 {
1823     if (n <= 0) return 0;
1824     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1825     return *str1 - *str2;
1826 }
1827
1828 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1829 {
1830     DWORD i;
1831
1832     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1833     {
1834         BYTE *buf = NULL;
1835         BOOL ret;
1836         DWORD size = 0;
1837
1838         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1839          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1840          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1841         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1842          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1843         if (ret && buf)
1844         {
1845             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1846
1847             ok(value->dwValueType == unicodeResults[i].valueType,
1848              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1849              value->dwValueType);
1850             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1851              value->Value.cbData / sizeof(WCHAR)),
1852              "Unexpected decoded value for index %d (value type %d)\n", i,
1853              unicodeResults[i].valueType);
1854             LocalFree(buf);
1855         }
1856     }
1857 }
1858
1859 struct encodedOctets
1860 {
1861     const BYTE *val;
1862     const BYTE *encoded;
1863 };
1864
1865 static const unsigned char bin46[] = { 'h','i',0 };
1866 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1867 static const unsigned char bin48[] = {
1868      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1869 static const unsigned char bin49[] = {
1870      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1871 static const unsigned char bin50[] = { 0 };
1872 static const unsigned char bin51[] = { 0x04,0x00,0 };
1873
1874 static const struct encodedOctets octets[] = {
1875     { bin46, bin47 },
1876     { bin48, bin49 },
1877     { bin50, bin51 },
1878 };
1879
1880 static void test_encodeOctets(DWORD dwEncoding)
1881 {
1882     CRYPT_DATA_BLOB blob;
1883     DWORD i;
1884
1885     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1886     {
1887         BYTE *buf = NULL;
1888         BOOL ret;
1889         DWORD bufSize = 0;
1890
1891         blob.cbData = strlen((const char*)octets[i].val);
1892         blob.pbData = (BYTE*)octets[i].val;
1893         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1894          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1895         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1896         if (buf)
1897         {
1898             ok(buf[0] == 4,
1899              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1900             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1901              buf[1], octets[i].encoded[1]);
1902             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1903              octets[i].encoded[1] + 1), "Got unexpected value\n");
1904             LocalFree(buf);
1905         }
1906     }
1907 }
1908
1909 static void test_decodeOctets(DWORD dwEncoding)
1910 {
1911     DWORD i;
1912
1913     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1914     {
1915         BYTE *buf = NULL;
1916         BOOL ret;
1917         DWORD bufSize = 0;
1918
1919         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1920          octets[i].encoded, octets[i].encoded[1] + 2,
1921          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1922         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1923         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1924          "Expected size >= %d, got %d\n",
1925            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1926         ok(buf != NULL, "Expected allocated buffer\n");
1927         if (buf)
1928         {
1929             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1930
1931             if (blob->cbData)
1932                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1933                  "Unexpected value\n");
1934             LocalFree(buf);
1935         }
1936     }
1937 }
1938
1939 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1940
1941 struct encodedBits
1942 {
1943     DWORD cUnusedBits;
1944     const BYTE *encoded;
1945     DWORD cbDecoded;
1946     const BYTE *decoded;
1947 };
1948
1949 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1950 static const unsigned char bin53[] = { 0xff,0xff };
1951 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1952 static const unsigned char bin55[] = { 0xff,0xfe };
1953 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1954 static const unsigned char bin57[] = { 0xfe };
1955 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1956
1957 static const struct encodedBits bits[] = {
1958     /* normal test cases */
1959     { 0, bin52, 2, bin53 },
1960     { 1, bin54, 2, bin55 },
1961     /* strange test case, showing cUnusedBits >= 8 is allowed */
1962     { 9, bin56, 1, bin57 },
1963     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1964     { 17, bin58, 0, NULL },
1965 };
1966
1967 static void test_encodeBits(DWORD dwEncoding)
1968 {
1969     DWORD i;
1970
1971     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1972     {
1973         CRYPT_BIT_BLOB blob;
1974         BOOL ret;
1975         BYTE *buf = NULL;
1976         DWORD bufSize = 0;
1977
1978         blob.cbData = sizeof(bytesToEncode);
1979         blob.pbData = (BYTE *)bytesToEncode;
1980         blob.cUnusedBits = bits[i].cUnusedBits;
1981         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1982          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1983         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1984         if (buf)
1985         {
1986             ok(bufSize == bits[i].encoded[1] + 2,
1987              "Got unexpected size %d, expected %d\n", bufSize,
1988              bits[i].encoded[1] + 2);
1989             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1990              "Unexpected value\n");
1991             LocalFree(buf);
1992         }
1993     }
1994 }
1995
1996 static void test_decodeBits(DWORD dwEncoding)
1997 {
1998     static const BYTE ber[] = "\x03\x02\x01\xff";
1999     static const BYTE berDecoded = 0xfe;
2000     DWORD i;
2001     BOOL ret;
2002     BYTE *buf = NULL;
2003     DWORD bufSize = 0;
2004
2005     /* normal cases */
2006     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2007     {
2008         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2009          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2010          &bufSize);
2011         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2012         if (buf)
2013         {
2014             CRYPT_BIT_BLOB *blob;
2015
2016             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2017                "Got unexpected size %d\n", bufSize);
2018             blob = (CRYPT_BIT_BLOB *)buf;
2019             ok(blob->cbData == bits[i].cbDecoded,
2020              "Got unexpected length %d, expected %d\n", blob->cbData,
2021              bits[i].cbDecoded);
2022             if (blob->cbData && bits[i].cbDecoded)
2023                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2024                  "Unexpected value\n");
2025             LocalFree(buf);
2026         }
2027     }
2028     /* special case: check that something that's valid in BER but not in DER
2029      * decodes successfully
2030      */
2031     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2032      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2033     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2034     if (buf)
2035     {
2036         CRYPT_BIT_BLOB *blob;
2037
2038         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2039            "Got unexpected size %d\n", bufSize);
2040         blob = (CRYPT_BIT_BLOB *)buf;
2041         ok(blob->cbData == sizeof(berDecoded),
2042            "Got unexpected length %d\n", blob->cbData);
2043         if (blob->cbData)
2044             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2045         LocalFree(buf);
2046     }
2047 }
2048
2049 struct Constraints2
2050 {
2051     CERT_BASIC_CONSTRAINTS2_INFO info;
2052     const BYTE *encoded;
2053 };
2054
2055 static const unsigned char bin59[] = { 0x30,0x00 };
2056 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2057 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2058 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2059 static const struct Constraints2 constraints2[] = {
2060  /* empty constraints */
2061  { { FALSE, FALSE, 0}, bin59 },
2062  /* can be a CA */
2063  { { TRUE,  FALSE, 0}, bin60 },
2064  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2065   * but that's not the case
2066   */
2067  { { FALSE, TRUE,  0}, bin61 },
2068  /* can be a CA and has path length constraints set */
2069  { { TRUE,  TRUE,  1}, bin62 },
2070 };
2071
2072 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2073 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2074  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2075  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2076  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2077 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2078  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2079  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2080  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2081  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2082
2083 static void test_encodeBasicConstraints(DWORD dwEncoding)
2084 {
2085     DWORD i, bufSize = 0;
2086     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2087     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2088      (LPBYTE)encodedDomainName };
2089     BOOL ret;
2090     BYTE *buf = NULL;
2091
2092     /* First test with the simpler info2 */
2093     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2094     {
2095         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2096          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2097          &bufSize);
2098         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2099         if (buf)
2100         {
2101             ok(bufSize == constraints2[i].encoded[1] + 2,
2102              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2103              bufSize);
2104             ok(!memcmp(buf, constraints2[i].encoded,
2105              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2106             LocalFree(buf);
2107         }
2108     }
2109     /* Now test with more complex basic constraints */
2110     info.SubjectType.cbData = 0;
2111     info.fPathLenConstraint = FALSE;
2112     info.cSubtreesConstraint = 0;
2113     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2114      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2115     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2116      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2117     if (buf)
2118     {
2119         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2120         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2121          "Unexpected value\n");
2122         LocalFree(buf);
2123     }
2124     /* None of the certs I examined had any subtree constraint, but I test one
2125      * anyway just in case.
2126      */
2127     info.cSubtreesConstraint = 1;
2128     info.rgSubtreesConstraint = &nameBlob;
2129     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2130      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2131     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2132      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2133     if (buf)
2134     {
2135         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2136         ok(!memcmp(buf, constraintWithDomainName,
2137          sizeof(constraintWithDomainName)), "Unexpected value\n");
2138         LocalFree(buf);
2139     }
2140     /* FIXME: test encoding with subject type. */
2141 }
2142
2143 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2144
2145 static void test_decodeBasicConstraints(DWORD dwEncoding)
2146 {
2147     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2148      0xff };
2149     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2150     DWORD i;
2151     BOOL ret;
2152     BYTE *buf = NULL;
2153     DWORD bufSize = 0;
2154
2155     /* First test with simpler info2 */
2156     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2157     {
2158         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2159          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2160          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2161         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2162          GetLastError());
2163         if (buf)
2164         {
2165             CERT_BASIC_CONSTRAINTS2_INFO *info =
2166              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2167
2168             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2169              "Unexpected value for item %d\n", i);
2170             LocalFree(buf);
2171         }
2172     }
2173     /* Check with the order of encoded elements inverted */
2174     buf = (PBYTE)1;
2175     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2176      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2177      &bufSize);
2178     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2179      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2180      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2181      GetLastError());
2182     ok(!buf, "Expected buf to be set to NULL\n");
2183     /* Check with a non-DER bool */
2184     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2185      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2186      &buf, &bufSize);
2187     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2188     if (buf)
2189     {
2190         CERT_BASIC_CONSTRAINTS2_INFO *info =
2191          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2192
2193         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2194         LocalFree(buf);
2195     }
2196     /* Check with a non-basic constraints value */
2197     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2198      encodedCommonName, encodedCommonName[1] + 2,
2199      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2200     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2201      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2202      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2203      GetLastError());
2204     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2205     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2206      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2207      &buf, &bufSize);
2208     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2209     if (buf)
2210     {
2211         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2212
2213         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2214         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2215         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2216         LocalFree(buf);
2217     }
2218     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2219      constraintWithDomainName, sizeof(constraintWithDomainName),
2220      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2221     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2222     if (buf)
2223     {
2224         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2225
2226         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2227         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2228         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2229         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2230         {
2231             ok(info->rgSubtreesConstraint[0].cbData ==
2232              sizeof(encodedDomainName), "Wrong size %d\n",
2233              info->rgSubtreesConstraint[0].cbData);
2234             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2235              sizeof(encodedDomainName)), "Unexpected value\n");
2236         }
2237         LocalFree(buf);
2238     }
2239 }
2240
2241 /* These are terrible public keys of course, I'm just testing encoding */
2242 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2243 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2244 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2245 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2246 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2247 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2248 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2249 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2250
2251 struct EncodedRSAPubKey
2252 {
2253     const BYTE *modulus;
2254     size_t modulusLen;
2255     const BYTE *encoded;
2256     size_t decodedModulusLen;
2257 };
2258
2259 struct EncodedRSAPubKey rsaPubKeys[] = {
2260     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2261     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2262     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2263     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2264 };
2265
2266 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2267 {
2268     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2269     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2270     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2271     BOOL ret;
2272     BYTE *buf = NULL;
2273     DWORD bufSize = 0, i;
2274
2275     /* Try with a bogus blob type */
2276     hdr->bType = 2;
2277     hdr->bVersion = CUR_BLOB_VERSION;
2278     hdr->reserved = 0;
2279     hdr->aiKeyAlg = CALG_RSA_KEYX;
2280     rsaPubKey->magic = 0x31415352;
2281     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2282     rsaPubKey->pubexp = 65537;
2283     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2284      sizeof(modulus1));
2285
2286     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2287      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2288     ok(!ret && GetLastError() == E_INVALIDARG,
2289      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2290     /* Now with a bogus reserved field */
2291     hdr->bType = PUBLICKEYBLOB;
2292     hdr->reserved = 1;
2293     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2294      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2295     if (buf)
2296     {
2297         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2298          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2299         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2300         LocalFree(buf);
2301     }
2302     /* Now with a bogus blob version */
2303     hdr->reserved = 0;
2304     hdr->bVersion = 0;
2305     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2306      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &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     /* And with a bogus alg ID */
2315     hdr->bVersion = CUR_BLOB_VERSION;
2316     hdr->aiKeyAlg = CALG_DES;
2317     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2318      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2319     if (buf)
2320     {
2321         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2322          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2323         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2324         LocalFree(buf);
2325     }
2326     /* Check a couple of RSA-related OIDs */
2327     hdr->aiKeyAlg = CALG_RSA_KEYX;
2328     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2329      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2330     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2331      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2332     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2333      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2334     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2335      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2336     /* Finally, all valid */
2337     hdr->aiKeyAlg = CALG_RSA_KEYX;
2338     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2339     {
2340         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2341          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2342         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2343          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2344         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2345         if (buf)
2346         {
2347             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2348              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2349              bufSize);
2350             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2351              "Unexpected value\n");
2352             LocalFree(buf);
2353         }
2354     }
2355 }
2356
2357 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2358 {
2359     DWORD i;
2360     LPBYTE buf = NULL;
2361     DWORD bufSize = 0;
2362     BOOL ret;
2363
2364     /* Try with a bad length */
2365     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2366      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2367      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2368     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2369      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2370      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2371      GetLastError());
2372     /* Try with a couple of RSA-related OIDs */
2373     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2374      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2375      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2376     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2377      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2378     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2379      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2380      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2381     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2382      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2383     /* Now try success cases */
2384     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2385     {
2386         bufSize = 0;
2387         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2388          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2389          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2390         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2391         if (buf)
2392         {
2393             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2394             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2395
2396             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2397              rsaPubKeys[i].decodedModulusLen,
2398              "Wrong size %d\n", bufSize);
2399             ok(hdr->bType == PUBLICKEYBLOB,
2400              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2401              hdr->bType);
2402             ok(hdr->bVersion == CUR_BLOB_VERSION,
2403              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2404              CUR_BLOB_VERSION, hdr->bVersion);
2405             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2406              hdr->reserved);
2407             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2408              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2409             ok(rsaPubKey->magic == 0x31415352,
2410              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2411             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2412              "Wrong bit len %d\n", rsaPubKey->bitlen);
2413             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2414              rsaPubKey->pubexp);
2415             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2416              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2417              "Unexpected modulus\n");
2418             LocalFree(buf);
2419         }
2420     }
2421 }
2422
2423 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2424  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2425  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2426
2427 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2428  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2429  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2430  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2431
2432 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2433 {
2434     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2435     CRYPT_SEQUENCE_OF_ANY seq;
2436     DWORD i;
2437     BOOL ret;
2438     BYTE *buf = NULL;
2439     DWORD bufSize = 0;
2440
2441     /* Encode a homogeneous sequence */
2442     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2443     {
2444         blobs[i].cbData = ints[i].encoded[1] + 2;
2445         blobs[i].pbData = (BYTE *)ints[i].encoded;
2446     }
2447     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2448     seq.rgValue = blobs;
2449
2450     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2451      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2452     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2453     if (buf)
2454     {
2455         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2456         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2457         LocalFree(buf);
2458     }
2459     /* Change the type of the first element in the sequence, and give it
2460      * another go
2461      */
2462     blobs[0].cbData = times[0].encodedTime[1] + 2;
2463     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2464     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2465      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2466     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2467     if (buf)
2468     {
2469         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2470         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2471          "Unexpected value\n");
2472         LocalFree(buf);
2473     }
2474 }
2475
2476 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2477 {
2478     BOOL ret;
2479     BYTE *buf = NULL;
2480     DWORD bufSize = 0;
2481
2482     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2483      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2484     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2485     if (buf)
2486     {
2487         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2488         DWORD i;
2489
2490         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2491          "Wrong elements %d\n", seq->cValue);
2492         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2493         {
2494             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2495              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2496              seq->rgValue[i].cbData);
2497             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2498              ints[i].encoded[1] + 2), "Unexpected value\n");
2499         }
2500         LocalFree(buf);
2501     }
2502     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2503      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2504      &bufSize);
2505     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2506     if (buf)
2507     {
2508         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2509
2510         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2511          "Wrong elements %d\n", seq->cValue);
2512         /* Just check the first element since it's all that changed */
2513         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2514          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2515          seq->rgValue[0].cbData);
2516         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2517          times[0].encodedTime[1] + 2), "Unexpected value\n");
2518         LocalFree(buf);
2519     }
2520 }
2521
2522 struct encodedExtensions
2523 {
2524     CERT_EXTENSIONS exts;
2525     const BYTE *encoded;
2526 };
2527
2528 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2529 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2530 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2531 static CERT_EXTENSION criticalExt =
2532  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2533 static CERT_EXTENSION nonCriticalExt =
2534  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2535 static CHAR oid_short[] = "1.1";
2536 static CERT_EXTENSION extWithShortOid =
2537  { oid_short, FALSE, { 0, NULL } };
2538
2539 static const BYTE ext0[] = { 0x30,0x00 };
2540 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2541                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2542 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2543                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2544 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2545
2546 static const struct encodedExtensions exts[] = {
2547  { { 0, NULL }, ext0 },
2548  { { 1, &criticalExt }, ext1 },
2549  { { 1, &nonCriticalExt }, ext2 },
2550  { { 1, &extWithShortOid }, ext3 }
2551 };
2552
2553 static void test_encodeExtensions(DWORD dwEncoding)
2554 {
2555     DWORD i;
2556
2557     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2558     {
2559         BOOL ret;
2560         BYTE *buf = NULL;
2561         DWORD bufSize = 0;
2562
2563         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2564          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2565         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2566         if (buf)
2567         {
2568             ok(bufSize == exts[i].encoded[1] + 2,
2569              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2570             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2571              "Unexpected value\n");
2572             LocalFree(buf);
2573         }
2574     }
2575 }
2576
2577 static void test_decodeExtensions(DWORD dwEncoding)
2578 {
2579     DWORD i;
2580
2581     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2582     {
2583         BOOL ret;
2584         BYTE *buf = NULL;
2585         DWORD bufSize = 0;
2586
2587         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2588          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2589          NULL, &buf, &bufSize);
2590         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2591         if (buf)
2592         {
2593             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2594             DWORD j;
2595
2596             ok(ext->cExtension == exts[i].exts.cExtension,
2597              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2598              ext->cExtension);
2599             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2600             {
2601                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2602                  exts[i].exts.rgExtension[j].pszObjId),
2603                  "Expected OID %s, got %s\n",
2604                  exts[i].exts.rgExtension[j].pszObjId,
2605                  ext->rgExtension[j].pszObjId);
2606                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2607                  exts[i].exts.rgExtension[j].Value.pbData,
2608                  exts[i].exts.rgExtension[j].Value.cbData),
2609                  "Unexpected value\n");
2610             }
2611             LocalFree(buf);
2612         }
2613     }
2614 }
2615
2616 /* MS encodes public key info with a NULL if the algorithm identifier's
2617  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2618  * it encodes them by omitting the algorithm parameters.  This latter approach
2619  * seems more correct, so accept either form.
2620  */
2621 struct encodedPublicKey
2622 {
2623     CERT_PUBLIC_KEY_INFO info;
2624     const BYTE *encoded;
2625     const BYTE *encodedNoNull;
2626     CERT_PUBLIC_KEY_INFO decoded;
2627 };
2628
2629 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2630  0xe, 0xf };
2631 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2632
2633 static const unsigned char bin64[] = {
2634     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2635 static const unsigned char bin65[] = {
2636     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2637 static const unsigned char bin66[] = {
2638     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2639 static const unsigned char bin67[] = {
2640     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2641 static const unsigned char bin68[] = {
2642     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2643     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2644 static const unsigned char bin69[] = {
2645     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2646     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2647 static const unsigned char bin70[] = {
2648     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2649     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2650     0x0f};
2651 static const unsigned char bin71[] = {
2652     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2653     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2654     0x0f};
2655 static unsigned char bin72[] = { 0x05,0x00};
2656
2657 static CHAR oid_bogus[] = "1.2.3",
2658             oid_rsa[]   = szOID_RSA;
2659
2660 static const struct encodedPublicKey pubKeys[] = {
2661  /* with a bogus OID */
2662  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2663   bin64, bin65,
2664   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2665  /* some normal keys */
2666  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2667   bin66, bin67,
2668   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2669  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2670   bin68, bin69,
2671   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2672  /* with add'l parameters--note they must be DER-encoded */
2673  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2674   (BYTE *)aKey, 0 } },
2675   bin70, bin71,
2676   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2677   (BYTE *)aKey, 0 } } },
2678 };
2679
2680 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2681 {
2682     DWORD i;
2683
2684     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2685     {
2686         BOOL ret;
2687         BYTE *buf = NULL;
2688         DWORD bufSize = 0;
2689
2690         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2691          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2692          &bufSize);
2693         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2694          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2695         if (buf)
2696         {
2697             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2698              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2699              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2700              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2701             if (bufSize == pubKeys[i].encoded[1] + 2)
2702                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2703                  "Unexpected value\n");
2704             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2705                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2706                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2707             LocalFree(buf);
2708         }
2709     }
2710 }
2711
2712 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2713  const CERT_PUBLIC_KEY_INFO *got)
2714 {
2715     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2716      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2717      got->Algorithm.pszObjId);
2718     ok(expected->Algorithm.Parameters.cbData ==
2719      got->Algorithm.Parameters.cbData,
2720      "Expected parameters of %d bytes, got %d\n",
2721      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2722     if (expected->Algorithm.Parameters.cbData)
2723         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2724          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2725          "Unexpected algorithm parameters\n");
2726     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2727      "Expected public key of %d bytes, got %d\n",
2728      expected->PublicKey.cbData, got->PublicKey.cbData);
2729     if (expected->PublicKey.cbData)
2730         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2731          got->PublicKey.cbData), "Unexpected public key value\n");
2732 }
2733
2734 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2735 {
2736     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2737      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2738      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2739      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2740     DWORD i;
2741     BOOL ret;
2742     BYTE *buf = NULL;
2743     DWORD bufSize = 0;
2744
2745     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2746     {
2747         /* The NULL form decodes to the decoded member */
2748         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2749          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2750          NULL, &buf, &bufSize);
2751         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2752         if (buf)
2753         {
2754             comparePublicKeyInfo(&pubKeys[i].decoded,
2755              (CERT_PUBLIC_KEY_INFO *)buf);
2756             LocalFree(buf);
2757         }
2758         /* The non-NULL form decodes to the original */
2759         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2760          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2761          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2762         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2763         if (buf)
2764         {
2765             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2766             LocalFree(buf);
2767         }
2768     }
2769     /* Test with bogus (not valid DER) parameters */
2770     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2771      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2772      NULL, &buf, &bufSize);
2773     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2774      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2775      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2776      GetLastError());
2777 }
2778
2779 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2780  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2781  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2782  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2783  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2784 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2785  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2786  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2787  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2788  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2789 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2790  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2791  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2792  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2793  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2794 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2795  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2796  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2797  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2798  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2799  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2800  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2801 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2802  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2803  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2804  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2805  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2806  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2807  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2808 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2809  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2810  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2811  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2812  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2813  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2814  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2815  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2816  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2817  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2818 static const BYTE v1CertWithPubKey[] = {
2819 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2820 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2821 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2822 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2823 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2824 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2825 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2826 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2827 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2828 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2829 0x01,0x01 };
2830 static const BYTE v1CertWithPubKeyNoNull[] = {
2831 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2832 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2833 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2834 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2835 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2836 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2837 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2838 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2839 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2840 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2841 static const BYTE v1CertWithSubjectKeyId[] = {
2842 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2843 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2844 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2845 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2846 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2847 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2848 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2849 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2850 0x4c,0x61,0x6e,0x67,0x00 };
2851
2852 static const BYTE serialNum[] = { 0x01 };
2853
2854 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2855 {
2856     BOOL ret;
2857     BYTE *buf = NULL;
2858     DWORD size = 0;
2859     CERT_INFO info = { 0 };
2860     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2861     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2862     CERT_EXTENSION ext;
2863
2864     if (0)
2865     {
2866         /* Test with NULL pvStructInfo (crashes on win9x) */
2867         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2868          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2869         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2870          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2871     }
2872     /* Test with a V1 cert */
2873     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2874      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2875     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2876      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2877     if (buf)
2878     {
2879         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2880          v1Cert[1] + 2, size);
2881         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2882         LocalFree(buf);
2883     }
2884     /* Test v2 cert */
2885     info.dwVersion = CERT_V2;
2886     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2887      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2888     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2889      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2890     if (buf)
2891     {
2892         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2893         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2894         LocalFree(buf);
2895     }
2896     /* Test v3 cert */
2897     info.dwVersion = CERT_V3;
2898     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2899      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2900     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2901      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2902     if (buf)
2903     {
2904         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2905         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2906         LocalFree(buf);
2907     }
2908     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2909      * API doesn't prevent it)
2910      */
2911     info.dwVersion = CERT_V1;
2912     info.cExtension = 1;
2913     info.rgExtension = &criticalExt;
2914     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2915      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2916     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2917      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2918     if (buf)
2919     {
2920         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2921         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2922         LocalFree(buf);
2923     }
2924     /* test v1 cert with a serial number */
2925     info.SerialNumber.cbData = sizeof(serialNum);
2926     info.SerialNumber.pbData = (BYTE *)serialNum;
2927     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2928      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2929     if (buf)
2930     {
2931         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2932         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2933         LocalFree(buf);
2934     }
2935     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2936     info.Issuer.cbData = sizeof(encodedCommonName);
2937     info.Issuer.pbData = (BYTE *)encodedCommonName;
2938     info.Subject.cbData = sizeof(encodedCommonName);
2939     info.Subject.pbData = (BYTE *)encodedCommonName;
2940     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2941      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2942     if (buf)
2943     {
2944         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2945         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2946         LocalFree(buf);
2947     }
2948     /* Add a public key */
2949     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2950     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2951     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2952     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2953      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2954     if (buf)
2955     {
2956         ok(size == sizeof(v1CertWithPubKey) ||
2957          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2958         if (size == sizeof(v1CertWithPubKey))
2959             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2960         else if (size == sizeof(v1CertWithPubKeyNoNull))
2961             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2962              "Got unexpected value\n");
2963         LocalFree(buf);
2964     }
2965     /* Remove the public key, and add a subject key identifier extension */
2966     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2967     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2968     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2969     ext.pszObjId = oid_subject_key_identifier;
2970     ext.fCritical = FALSE;
2971     ext.Value.cbData = sizeof(octetCommonNameValue);
2972     ext.Value.pbData = octetCommonNameValue;
2973     info.cExtension = 1;
2974     info.rgExtension = &ext;
2975     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2976      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2977     if (buf)
2978     {
2979         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2980         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2981         LocalFree(buf);
2982     }
2983 }
2984
2985 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2986 {
2987     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2988      v1CertWithConstraints, v1CertWithSerial };
2989     BOOL ret;
2990     BYTE *buf = NULL;
2991     DWORD size = 0, i;
2992
2993     /* Test with NULL pbEncoded */
2994     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2995      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
2996     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2997      GetLastError() == OSS_BAD_ARG /* Win9x */),
2998      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
2999     if (0)
3000     {
3001         /* Crashes on win9x */
3002         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3003          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3004         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3005          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3006     }
3007     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
3008      * minimum a cert must have a non-zero serial number, an issuer, and a
3009      * subject.
3010      */
3011     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3012     {
3013         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3014          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3015          &buf, &size);
3016         ok(!ret, "Expected failure\n");
3017     }
3018     /* Now check with serial number, subject and issuer specified */
3019     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3020      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3021     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3022     if (buf)
3023     {
3024         CERT_INFO *info = (CERT_INFO *)buf;
3025
3026         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3027         ok(info->SerialNumber.cbData == 1,
3028          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3029         ok(*info->SerialNumber.pbData == *serialNum,
3030          "Expected serial number %d, got %d\n", *serialNum,
3031          *info->SerialNumber.pbData);
3032         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3033          "Wrong size %d\n", info->Issuer.cbData);
3034         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3035          "Unexpected issuer\n");
3036         ok(info->Subject.cbData == sizeof(encodedCommonName),
3037          "Wrong size %d\n", info->Subject.cbData);
3038         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3039          info->Subject.cbData), "Unexpected subject\n");
3040         LocalFree(buf);
3041     }
3042     /* Check again with pub key specified */
3043     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3044      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3045      &buf, &size);
3046     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3047     if (buf)
3048     {
3049         CERT_INFO *info = (CERT_INFO *)buf;
3050
3051         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3052         ok(info->SerialNumber.cbData == 1,
3053          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3054         ok(*info->SerialNumber.pbData == *serialNum,
3055          "Expected serial number %d, got %d\n", *serialNum,
3056          *info->SerialNumber.pbData);
3057         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3058          "Wrong size %d\n", info->Issuer.cbData);
3059         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3060          "Unexpected issuer\n");
3061         ok(info->Subject.cbData == sizeof(encodedCommonName),
3062          "Wrong size %d\n", info->Subject.cbData);
3063         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3064          info->Subject.cbData), "Unexpected subject\n");
3065         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3066          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3067          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3068         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3069          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3070         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3071          sizeof(aKey)), "Unexpected public key\n");
3072         LocalFree(buf);
3073     }
3074 }
3075
3076 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3077  0xe, 0xf };
3078
3079 static const BYTE signedBigCert[] = {
3080  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3081  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3082  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3083  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3084  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3085  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3086  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3087  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3088  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3089  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3090  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3091  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3092
3093 static void test_encodeCert(DWORD dwEncoding)
3094 {
3095     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3096      * also that bigCert is a NULL-terminated string, so don't count its
3097      * last byte (otherwise the signed cert won't decode.)
3098      */
3099     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3100      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3101     BOOL ret;
3102     BYTE *buf = NULL;
3103     DWORD bufSize = 0;
3104
3105     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3106      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3107     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3108     if (buf)
3109     {
3110         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3111         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3112         LocalFree(buf);
3113     }
3114 }
3115
3116 static void test_decodeCert(DWORD dwEncoding)
3117 {
3118     BOOL ret;
3119     BYTE *buf = NULL;
3120     DWORD size = 0;
3121
3122     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3123      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3124     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3125     if (buf)
3126     {
3127         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3128
3129         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3130          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3131         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3132          "Unexpected cert\n");
3133         ok(info->Signature.cbData == sizeof(hash),
3134          "Wrong signature size %d\n", info->Signature.cbData);
3135         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3136          "Unexpected signature\n");
3137         LocalFree(buf);
3138     }
3139     /* A signed cert decodes as a CERT_INFO too */
3140     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3141      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3142     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3143     if (buf)
3144     {
3145         CERT_INFO *info = (CERT_INFO *)buf;
3146
3147         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3148         ok(info->SerialNumber.cbData == 1,
3149          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3150         ok(*info->SerialNumber.pbData == *serialNum,
3151          "Expected serial number %d, got %d\n", *serialNum,
3152          *info->SerialNumber.pbData);
3153         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3154          "Wrong size %d\n", info->Issuer.cbData);
3155         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3156          "Unexpected issuer\n");
3157         ok(info->Subject.cbData == sizeof(encodedCommonName),
3158          "Wrong size %d\n", info->Subject.cbData);
3159         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3160          info->Subject.cbData), "Unexpected subject\n");
3161         LocalFree(buf);
3162     }
3163 }
3164
3165 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3166 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3167  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3168  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3169 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3170  0x00, 0x03 };
3171 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3172  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3173  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3174 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3175  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3176  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3177  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3178  0x2e, 0x6f, 0x72, 0x67 };
3179 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3180  CRL_REASON_AFFILIATION_CHANGED;
3181
3182 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3183 {
3184     CRL_DIST_POINTS_INFO info = { 0 };
3185     CRL_DIST_POINT point = { { 0 } };
3186     CERT_ALT_NAME_ENTRY entry = { 0 };
3187     BOOL ret;
3188     BYTE *buf = NULL;
3189     DWORD size = 0;
3190
3191     /* Test with an empty info */
3192     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3193      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3194     ok(!ret && GetLastError() == E_INVALIDARG,
3195      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3196     /* Test with one empty dist point */
3197     info.cDistPoint = 1;
3198     info.rgDistPoint = &point;
3199     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3200      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3201     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3202     if (buf)
3203     {
3204         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3205         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3206         LocalFree(buf);
3207     }
3208     /* A dist point with an invalid name */
3209     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3210     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3211     U(entry).pwszURL = (LPWSTR)nihongoURL;
3212     U(point.DistPointName).FullName.cAltEntry = 1;
3213     U(point.DistPointName).FullName.rgAltEntry = &entry;
3214     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3215      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3216     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3217      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3218     /* The first invalid character is at index 7 */
3219     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3220      "Expected invalid char at index 7, got %d\n",
3221      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3222     /* A dist point with (just) a valid name */
3223     U(entry).pwszURL = (LPWSTR)url;
3224     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3225      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3226     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3227     if (buf)
3228     {
3229         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3230         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3231         LocalFree(buf);
3232     }
3233     /* A dist point with (just) reason flags */
3234     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3235     point.ReasonFlags.cbData = sizeof(crlReason);
3236     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3237     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3238      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3239     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3240     if (buf)
3241     {
3242         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3243         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3244         LocalFree(buf);
3245     }
3246     /* A dist point with just an issuer */
3247     point.ReasonFlags.cbData = 0;
3248     point.CRLIssuer.cAltEntry = 1;
3249     point.CRLIssuer.rgAltEntry = &entry;
3250     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3251      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3252     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3253     if (buf)
3254     {
3255         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3256         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3257         LocalFree(buf);
3258     }
3259     /* A dist point with both a name and an issuer */
3260     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3261     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3262      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3263     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3264     if (buf)
3265     {
3266         ok(size == sizeof(distPointWithUrlAndIssuer),
3267          "Wrong size %d\n", size);
3268         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3269         LocalFree(buf);
3270     }
3271 }
3272
3273 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3274 {
3275     BOOL ret;
3276     BYTE *buf = NULL;
3277     DWORD size = 0;
3278     PCRL_DIST_POINTS_INFO info;
3279     PCRL_DIST_POINT point;
3280     PCERT_ALT_NAME_ENTRY entry;
3281
3282     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3283      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3284      &buf, &size);
3285     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3286     if (ret)
3287     {
3288         info = (PCRL_DIST_POINTS_INFO)buf;
3289         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3290          "Wrong size %d\n", size);
3291         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3292          info->cDistPoint);
3293         point = info->rgDistPoint;
3294         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3295          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3296          point->DistPointName.dwDistPointNameChoice);
3297         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3298         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3299         LocalFree(buf);
3300     }
3301     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3302      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3303      &buf, &size);
3304     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3305     if (ret)
3306     {
3307         info = (PCRL_DIST_POINTS_INFO)buf;
3308         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3309          "Wrong size %d\n", size);
3310         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3311          info->cDistPoint);
3312         point = info->rgDistPoint;
3313         ok(point->DistPointName.dwDistPointNameChoice ==
3314          CRL_DIST_POINT_FULL_NAME,
3315          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3316          point->DistPointName.dwDistPointNameChoice);
3317         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3318          "Expected 1 name entry, got %d\n",
3319          U(point->DistPointName).FullName.cAltEntry);
3320         entry = U(point->DistPointName).FullName.rgAltEntry;
3321         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3322          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3323         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3324         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3325         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3326         LocalFree(buf);
3327     }
3328     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3329      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3330      NULL, &buf, &size);
3331     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3332     if (ret)
3333     {
3334         info = (PCRL_DIST_POINTS_INFO)buf;
3335         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3336          "Wrong size %d\n", size);
3337         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3338          info->cDistPoint);
3339         point = info->rgDistPoint;
3340         ok(point->DistPointName.dwDistPointNameChoice ==
3341          CRL_DIST_POINT_NO_NAME,
3342          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3343          point->DistPointName.dwDistPointNameChoice);
3344         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3345          "Expected reason length\n");
3346         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3347          "Unexpected reason\n");
3348         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3349         LocalFree(buf);
3350     }
3351     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3352      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3353      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3354     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3355     if (ret)
3356     {
3357         info = (PCRL_DIST_POINTS_INFO)buf;
3358         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3359          "Wrong size %d\n", size);
3360         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3361          info->cDistPoint);
3362         point = info->rgDistPoint;
3363         ok(point->DistPointName.dwDistPointNameChoice ==
3364          CRL_DIST_POINT_FULL_NAME,
3365          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3366          point->DistPointName.dwDistPointNameChoice);
3367         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3368          "Expected 1 name entry, got %d\n",
3369          U(point->DistPointName).FullName.cAltEntry);
3370         entry = U(point->DistPointName).FullName.rgAltEntry;
3371         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3372          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3373         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3374         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3375         ok(point->CRLIssuer.cAltEntry == 1,
3376          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3377         entry = point->CRLIssuer.rgAltEntry;
3378         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3379          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3380         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3381         LocalFree(buf);
3382     }
3383 }
3384
3385 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3386 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3387 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3388  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3389  0x67 };
3390
3391 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3392 {
3393     BOOL ret;
3394     BYTE *buf = NULL;
3395     DWORD size = 0;
3396     CRL_ISSUING_DIST_POINT point = { { 0 } };
3397     CERT_ALT_NAME_ENTRY entry;
3398
3399     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3400      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3401     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3402     {
3403         skip("no X509_ISSUING_DIST_POINT encode support\n");
3404         return;
3405     }
3406     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3407      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3408     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3409      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3410     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3411     if (buf)
3412     {
3413         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3414         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3415         LocalFree(buf);
3416     }
3417     /* nonsensical flags */
3418     point.fOnlyContainsUserCerts = TRUE;
3419     point.fOnlyContainsCACerts = TRUE;
3420     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3421      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3422     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3423     if (buf)
3424     {
3425         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3426         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3427         LocalFree(buf);
3428     }
3429     /* unimplemented name type */
3430     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3431     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3432     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3433      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3434     ok(!ret && GetLastError() == E_INVALIDARG,
3435      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3436     /* empty name */
3437     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3438     U(point.DistPointName).FullName.cAltEntry = 0;
3439     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3440      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3441     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3442     if (buf)
3443     {
3444         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3445         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3446         LocalFree(buf);
3447     }
3448     /* name with URL entry */
3449     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3450     U(entry).pwszURL = (LPWSTR)url;
3451     U(point.DistPointName).FullName.cAltEntry = 1;
3452     U(point.DistPointName).FullName.rgAltEntry = &entry;
3453     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3454      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3455     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3456     if (buf)
3457     {
3458         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3459         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3460         LocalFree(buf);
3461     }
3462 }
3463
3464 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3465  const CERT_ALT_NAME_ENTRY *got)
3466 {
3467     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3468      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3469      got->dwAltNameChoice);
3470     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3471     {
3472         switch (got->dwAltNameChoice)
3473         {
3474         case CERT_ALT_NAME_RFC822_NAME:
3475         case CERT_ALT_NAME_DNS_NAME:
3476         case CERT_ALT_NAME_EDI_PARTY_NAME:
3477         case CERT_ALT_NAME_URL:
3478         case CERT_ALT_NAME_REGISTERED_ID:
3479             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3480              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3481              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3482              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3483              "Unexpected name\n");
3484             break;
3485         case CERT_ALT_NAME_X400_ADDRESS:
3486         case CERT_ALT_NAME_DIRECTORY_NAME:
3487         case CERT_ALT_NAME_IP_ADDRESS:
3488             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3489                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3490             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3491                        U(*got).IPAddress.cbData), "Unexpected value\n");
3492             break;
3493         }
3494     }
3495 }
3496
3497 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3498  const CERT_ALT_NAME_INFO *got)
3499 {
3500     DWORD i;
3501
3502     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3503      expected->cAltEntry, got->cAltEntry);
3504     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3505         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3506 }
3507
3508 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3509  const CRL_DIST_POINT_NAME *got)
3510 {
3511     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3512      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3513     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3514         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3515 }
3516
3517 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3518  const CRL_ISSUING_DIST_POINT *got)
3519 {
3520     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3521     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3522      "Unexpected fOnlyContainsUserCerts\n");
3523     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3524      "Unexpected fOnlyContainsCACerts\n");
3525     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3526      "Unexpected reason flags\n");
3527     ok(got->fIndirectCRL == expected->fIndirectCRL,
3528      "Unexpected fIndirectCRL\n");
3529 }
3530
3531 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3532 {
3533     BOOL ret;
3534     BYTE *buf = NULL;
3535     DWORD size = 0;
3536     CRL_ISSUING_DIST_POINT point = { { 0 } };
3537
3538     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3539      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3540      &buf, &size);
3541     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3542     {
3543         skip("no X509_ISSUING_DIST_POINT decode support\n");
3544         return;
3545     }
3546     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3547     if (ret)
3548     {
3549         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3550         LocalFree(buf);
3551     }
3552     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3553      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3554      &buf, &size);
3555     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3556     if (ret)
3557     {
3558         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3559         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3560         LocalFree(buf);
3561     }
3562     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3563      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3564      &buf, &size);
3565     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3566     if (ret)
3567     {
3568         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3569         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3570         U(point.DistPointName).FullName.cAltEntry = 0;
3571         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3572         LocalFree(buf);
3573     }
3574     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3575      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3576     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3577     if (ret)
3578     {
3579         CERT_ALT_NAME_ENTRY entry;
3580
3581         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3582         U(entry).pwszURL = (LPWSTR)url;
3583         U(point.DistPointName).FullName.cAltEntry = 1;
3584         U(point.DistPointName).FullName.rgAltEntry = &entry;
3585         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3586         LocalFree(buf);
3587     }
3588 }
3589
3590 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3591  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3592  0x30, 0x5a };
3593 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3594  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3595  0x30, 0x30, 0x30, 0x30, 0x5a };
3596 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3597  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3598  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3599  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3600  0x5a };
3601 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3602  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3603  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3604  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3605  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3606  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3607 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3608  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3609  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3610  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3611  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3612  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3613 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3614  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3615  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3616  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3617  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3618  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3619  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3620 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3621  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3622  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3623  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3624  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3625  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3626  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3627 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3628  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3629  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3630  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3631  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3632  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3633  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3634 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3635  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3636  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3637  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3638  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3639  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3640  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3641
3642 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3643 {
3644     BOOL ret;
3645     BYTE *buf = NULL;
3646     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3647     DWORD size = 0;
3648     CRL_INFO info = { 0 };
3649     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3650     CERT_EXTENSION ext;
3651
3652     /* Test with a V1 CRL */
3653     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3654      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3655     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3656      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3657     if (buf)
3658     {
3659         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3660         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3661         LocalFree(buf);
3662     }
3663     /* Test v2 CRL */
3664     info.dwVersion = CRL_V2;
3665     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3666      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3667     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3668      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3669     if (buf)
3670     {
3671         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3672          v2CRL[1] + 2, size);
3673         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3674         LocalFree(buf);
3675     }
3676     /* v1 CRL with a name */
3677     info.dwVersion = CRL_V1;
3678     info.Issuer.cbData = sizeof(encodedCommonName);
3679     info.Issuer.pbData = (BYTE *)encodedCommonName;
3680     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3681      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3682     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3683     if (buf)
3684     {
3685         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3686         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3687         LocalFree(buf);
3688     }
3689     if (0)
3690     {
3691         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3692         info.cCRLEntry = 1;
3693         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3694          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3695         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3696          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3697     }
3698     /* now set an empty entry */
3699     info.cCRLEntry = 1;
3700     info.rgCRLEntry = &entry;
3701     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3702      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3703     if (buf)
3704     {
3705         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3706          "Wrong size %d\n", size);
3707         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3708          "Got unexpected value\n");
3709         LocalFree(buf);
3710     }
3711     /* an entry with a serial number */
3712     entry.SerialNumber.cbData = sizeof(serialNum);
3713     entry.SerialNumber.pbData = (BYTE *)serialNum;
3714     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3715      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3716     if (buf)
3717     {
3718         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3719          "Wrong size %d\n", size);
3720         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3721          "Got unexpected value\n");
3722         LocalFree(buf);
3723     }
3724     /* an entry with an extension */
3725     entry.cExtension = 1;
3726     entry.rgExtension = &criticalExt;
3727     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3728      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3729     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3730     if (buf)
3731     {
3732         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3733         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3734         LocalFree(buf);
3735     }
3736     /* a CRL with an extension */
3737     entry.cExtension = 0;
3738     info.cExtension = 1;
3739     info.rgExtension = &criticalExt;
3740     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3741      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3742     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3743     if (buf)
3744     {
3745         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3746         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3747         LocalFree(buf);
3748     }
3749     /* a v2 CRL with an extension, this time non-critical */
3750     info.dwVersion = CRL_V2;
3751     info.rgExtension = &nonCriticalExt;
3752     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3753      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3754     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3755     if (buf)
3756     {
3757         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3758         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3759         LocalFree(buf);
3760     }
3761     /* a v2 CRL with an issuing dist point extension */
3762     ext.pszObjId = oid_issuing_dist_point;
3763     ext.fCritical = TRUE;
3764     ext.Value.cbData = sizeof(urlIDP);
3765     ext.Value.pbData = (LPBYTE)urlIDP;
3766     entry.rgExtension = &ext;
3767     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3768      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3769     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3770     if (buf)
3771     {
3772         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3773         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3774         LocalFree(buf);
3775     }
3776 }
3777
3778 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3779  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3780  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3781  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3782  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3783  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3784  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3785  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3786  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3787  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3788  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3789  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3790  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3791  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3792  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3793  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3794  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3795  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3796  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3797  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3798  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3799  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3800  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3801  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3802  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3803  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3804  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3805  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3806  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3807  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3808  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3809  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3810  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3811  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3812  0xcd };
3813 static const BYTE verisignCRLWithLotsOfEntries[] = {
3814 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3815 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3816 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3817 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3818 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3819 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3820 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3821 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3822 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3823 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3824 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3825 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3826 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3827 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3828 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3829 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3830 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3831 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3832 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3833 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3834 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3835 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3836 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3837 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3838 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3839 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3840 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3841 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3842 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3843 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3844 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3845 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3846 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3847 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3848 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3849 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3850 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3851 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3852 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3853 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3854 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3855 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3856 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3857 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3858 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3859 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3860 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3861 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3862 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3863 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3864 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3865 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3866 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3867 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3868 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3869 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3870 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3871 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3872 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3873 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3874 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3875 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3876 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3877 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3878 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3879 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3880 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3881 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3882 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3883 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3884 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3885 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3886 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3887 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3888 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3889 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3890 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3891 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3892 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3893 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3894 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3895 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3896 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3897 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3898 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3899 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3900 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3901 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3902 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3903 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3904 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3905 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3906 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3907 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3908 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3909 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3910 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3911 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3912 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3913 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3914 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3915 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3916 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3917 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3918 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3919 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3920 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3921 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3922 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3923 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3924 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3925 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3926 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3927 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3928 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3929 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3930 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3931 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3932 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3933 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3934 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3935 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3936 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3937 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3938 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3939 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3940 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3941 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3942 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3943 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3944 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3945 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3946 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3947 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3948 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3949 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3950 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3951 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3952 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3953 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3954 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3955 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3956 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3957 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3958 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3959 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3960 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3961 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3962 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3963 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3964 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3965 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3966 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3967 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3968 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3969 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3970 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3971 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3972 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3973 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3974 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3975 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3976 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3977 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3978 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3979 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3980 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3981 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3982 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3983 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3984 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3985 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3986 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3987 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3988 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3989 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3990 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3991 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3992 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3993 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3994 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3995 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3996 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3997 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3998 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3999 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4000 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4001 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4002 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4003 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4004 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4005 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4006 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4007 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4008 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4009 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4010 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4011 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4012 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4013 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4014 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4015 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4016 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4017 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4018 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4019 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4020 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4021 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4022 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4023 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4024 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4025 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4026 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4027 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4028 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4029 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4030 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4031 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4032 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4033 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4034 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4035 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4036 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4037 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4038 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4039 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4040 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4041 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4042 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4043 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4044 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4045 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4046 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4047 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4048 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4049 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4050 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4051 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4052 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4053 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4054 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4055 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4056 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4057 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4058 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4059 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4060 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4061 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4062 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4063 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4064 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4065 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4066 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4067 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4068 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4069 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4070 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4071 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4072 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4073 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4074 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4075 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4076 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4077 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4078 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4079 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4080 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4081 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4082 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4083 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4084 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4085 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4086 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4087 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4088 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4089 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4090 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4091 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4092 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4093 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4094 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4095 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4096 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4097 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4098 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4099 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4100 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4101 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4102 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4103 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4104 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4105 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4106 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4107 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4108 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4109 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4110 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4111 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4112 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4113 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4114 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4115 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4116 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4117 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4118 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4119 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4120 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4121 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4122 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4123 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4124 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4125 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4126 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4127 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4128 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4129 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4130 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4131 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4132 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4133 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4134 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4135 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4136 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4137 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4138 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4139 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4140 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4141 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4142 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4143 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4144 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4145 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4146 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4147 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4148 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4149 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4150 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4151 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4152 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4153 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4154 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4155 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4156 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4157 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4158 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4159 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4160 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4161 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4162 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4163 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4164 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4165 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4166 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4167 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4168 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4169 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4170 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4171 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4172 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4173 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4174 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4175 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4176 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4177 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4178 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4179 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4180 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4181 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4182 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4183 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4184 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4185 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4186 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4187 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4188 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4189 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4190 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4191 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4192 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4193 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4194 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4195 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4196 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4197 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4198 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4199 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4200 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4201 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4202 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4203 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4204 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4205 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4206 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4207 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4208 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4209 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4210 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4211 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4212 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4213 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4214 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4215 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4216 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4217 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4218 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4219 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4220 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4221 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4222 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4223 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4224 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4225 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4226 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4227 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4228 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4229 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4230 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4231 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4232 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4233 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4234 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4235 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4236 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4237 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4238 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4239 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4240 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4241 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4242 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4243 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4244 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4245 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4246 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4247 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4248 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4249 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4250 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4251 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4252 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4253 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4254 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4255 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4256 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4257 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4258 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4259 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4260 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4261 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4262 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4263 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4264 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4265 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4266 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4267 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4268 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4269 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4270 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4271 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4272 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4273 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4274 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4275 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4276 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4277 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4278 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4279 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4280 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4281 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4282 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4283 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4284 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4285 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4286 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4287 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4288 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4289 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4290 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4291 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4292 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4293 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4294 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4295 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4296 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4297 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4298 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4299 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4300 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4301 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4302 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4303 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4304 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4305 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4306 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4307 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4308 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4309 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4310 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4311 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4312 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4313 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4314 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4315 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4316 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4317 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4318 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4319 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4320 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4321 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4322
4323 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4324 {
4325     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4326     BOOL ret;
4327     BYTE *buf = NULL;
4328     DWORD size = 0, i;
4329
4330     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4331     {
4332         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4333          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4334          &buf, &size);
4335         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4336          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4337          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4338          GetLastError());
4339     }
4340     /* at a minimum, a CRL must contain an issuer: */
4341     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4342      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4343      &buf, &size);
4344     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4345     if (buf)
4346     {
4347         CRL_INFO *info = (CRL_INFO *)buf;
4348
4349         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4350         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4351          info->cCRLEntry);
4352         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4353          "Wrong issuer size %d\n", info->Issuer.cbData);
4354         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4355          "Unexpected issuer\n");
4356         LocalFree(buf);
4357     }
4358     /* check decoding with an empty CRL entry */
4359     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4360      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4361      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4362     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4363      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4364      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4365      GetLastError());
4366     /* with a real CRL entry */
4367     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4368      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4369      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4370     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4371     if (buf)
4372     {
4373         CRL_INFO *info = (CRL_INFO *)buf;
4374         CRL_ENTRY *entry;
4375
4376         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4377         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4378          info->cCRLEntry);
4379         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4380         entry = info->rgCRLEntry;
4381         ok(entry->SerialNumber.cbData == 1,
4382          "Expected serial number size 1, got %d\n",
4383          entry->SerialNumber.cbData);
4384         ok(*entry->SerialNumber.pbData == *serialNum,
4385          "Expected serial number %d, got %d\n", *serialNum,
4386          *entry->SerialNumber.pbData);
4387         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4388          "Wrong issuer size %d\n", info->Issuer.cbData);
4389         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4390          "Unexpected issuer\n");
4391         LocalFree(buf);
4392     }
4393     /* a real CRL from verisign that has extensions */
4394     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4395      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4396      NULL, &buf, &size);
4397     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4398     if (buf)
4399     {
4400         CRL_INFO *info = (CRL_INFO *)buf;
4401         CRL_ENTRY *entry;
4402
4403         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4404         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4405          info->cCRLEntry);
4406         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4407         entry = info->rgCRLEntry;
4408         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4409          info->cExtension);
4410         LocalFree(buf);
4411     }
4412     /* another real CRL from verisign that has lots of entries */
4413     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4414      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4415      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4416     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4417     if (buf)
4418     {
4419         CRL_INFO *info = (CRL_INFO *)buf;
4420
4421         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4422         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4423          info->cCRLEntry);
4424         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4425          info->cExtension);
4426         LocalFree(buf);
4427     }
4428     /* and finally, with an extension */
4429     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4430      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4431      NULL, &buf, &size);
4432     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4433     if (buf)
4434     {
4435         CRL_INFO *info = (CRL_INFO *)buf;
4436         CRL_ENTRY *entry;
4437
4438         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4439         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4440          info->cCRLEntry);
4441         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4442         entry = info->rgCRLEntry;
4443         ok(entry->SerialNumber.cbData == 1,
4444          "Expected serial number size 1, got %d\n",
4445          entry->SerialNumber.cbData);
4446         ok(*entry->SerialNumber.pbData == *serialNum,
4447          "Expected serial number %d, got %d\n", *serialNum,
4448          *entry->SerialNumber.pbData);
4449         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4450          "Wrong issuer size %d\n", info->Issuer.cbData);
4451         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4452          "Unexpected issuer\n");
4453         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4454          info->cExtension);
4455         LocalFree(buf);
4456     }
4457     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4458      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4459      NULL, &buf, &size);
4460     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4461     if (buf)
4462     {
4463         CRL_INFO *info = (CRL_INFO *)buf;
4464
4465         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4466          info->cExtension);
4467         LocalFree(buf);
4468     }
4469     /* And again, with an issuing dist point */
4470     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4471      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4472      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4473     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4474     if (buf)
4475     {
4476         CRL_INFO *info = (CRL_INFO *)buf;
4477
4478         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4479          info->cExtension);
4480         LocalFree(buf);
4481     }
4482 }
4483
4484 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4485  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4486 static const BYTE encodedUsage[] = {
4487  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4488  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4489  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4490
4491 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4492 {
4493     BOOL ret;
4494     BYTE *buf = NULL;
4495     DWORD size = 0;
4496     CERT_ENHKEY_USAGE usage;
4497
4498     /* Test with empty usage */
4499     usage.cUsageIdentifier = 0;
4500     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4501      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4502     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4503     if (buf)
4504     {
4505         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4506         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4507         LocalFree(buf);
4508     }
4509     /* Test with a few usages */
4510     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4511     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4512     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4513      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4514     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4515     if (buf)
4516     {
4517         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4518         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4519         LocalFree(buf);
4520     }
4521 }
4522
4523 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4524 {
4525     BOOL ret;
4526     LPBYTE buf = NULL;
4527     DWORD size = 0;
4528
4529     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4530      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4531      &buf, &size);
4532     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4533     if (buf)
4534     {
4535         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4536
4537         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4538          "Wrong size %d\n", size);
4539         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4540          usage->cUsageIdentifier);
4541         LocalFree(buf);
4542     }
4543     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4544      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4545      &buf, &size);
4546     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4547     if (buf)
4548     {
4549         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4550         DWORD i;
4551
4552         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4553          "Wrong size %d\n", size);
4554         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4555          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4556         for (i = 0; i < usage->cUsageIdentifier; i++)
4557             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4558              "Expected OID %s, got %s\n", keyUsages[i],
4559              usage->rgpszUsageIdentifier[i]);
4560         LocalFree(buf);
4561     }
4562 }
4563
4564 static BYTE keyId[] = { 1,2,3,4 };
4565 static const BYTE authorityKeyIdWithId[] = {
4566  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4567 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4568  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4569  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4570 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4571
4572 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4573 {
4574     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4575     BOOL ret;
4576     BYTE *buf = NULL;
4577     DWORD size = 0;
4578
4579     /* Test with empty id */
4580     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4581      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4582     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4583     if (buf)
4584     {
4585         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4586         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4587         LocalFree(buf);
4588     }
4589     /* With just a key id */
4590     info.KeyId.cbData = sizeof(keyId);
4591     info.KeyId.pbData = keyId;
4592     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4593      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4594     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4595     if (buf)
4596     {
4597         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4598         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4599         LocalFree(buf);
4600     }
4601     /* With just an issuer */
4602     info.KeyId.cbData = 0;
4603     info.CertIssuer.cbData = sizeof(encodedCommonName);
4604     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4605     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4606      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4607     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4608     if (buf)
4609     {
4610         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4611          size);
4612         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4613         LocalFree(buf);
4614     }
4615     /* With just a serial number */
4616     info.CertIssuer.cbData = 0;
4617     info.CertSerialNumber.cbData = sizeof(serialNum);
4618     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4619     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4620      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4621     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4622     if (buf)
4623     {
4624         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4625          size);
4626         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4627         LocalFree(buf);
4628     }
4629 }
4630
4631 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4632 {
4633     BOOL ret;
4634     LPBYTE buf = NULL;
4635     DWORD size = 0;
4636
4637     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4638      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4639      &buf, &size);
4640     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4641     if (buf)
4642     {
4643         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4644
4645         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4646          size);
4647         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4648         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4649         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4650         LocalFree(buf);
4651     }
4652     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4653      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4654      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4655     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4656     if (buf)
4657     {
4658         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4659
4660         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4661          size);
4662         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4663         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4664          "Unexpected key id\n");
4665         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4666         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4667         LocalFree(buf);
4668     }
4669     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4670      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4671      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4672     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4673     if (buf)
4674     {
4675         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4676
4677         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4678          size);
4679         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4680         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4681          "Unexpected issuer len\n");
4682         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4683          sizeof(encodedCommonName)), "Unexpected issuer\n");
4684         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4685         LocalFree(buf);
4686     }
4687     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4688      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4689      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4690     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4691     if (buf)
4692     {
4693         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4694
4695         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4696          size);
4697         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4698         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4699         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4700          "Unexpected serial number len\n");
4701         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4702          "Unexpected serial number\n");
4703         LocalFree(buf);
4704     }
4705 }
4706
4707 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4708  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4709  0x6f,0x72,0x67 };
4710
4711 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4712 {
4713     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4714     CERT_ALT_NAME_ENTRY entry = { 0 };
4715     BOOL ret;
4716     BYTE *buf = NULL;
4717     DWORD size = 0;
4718
4719     /* Test with empty id */
4720     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4721      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4722     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4723     if (buf)
4724     {
4725         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4726         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4727         LocalFree(buf);
4728     }
4729     /* With just a key id */
4730     info.KeyId.cbData = sizeof(keyId);
4731     info.KeyId.pbData = keyId;
4732     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4733      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4734     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4735     if (buf)
4736     {
4737         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4738          size);
4739         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4740         LocalFree(buf);
4741     }
4742     /* With a bogus issuer name */
4743     info.KeyId.cbData = 0;
4744     info.AuthorityCertIssuer.cAltEntry = 1;
4745     info.AuthorityCertIssuer.rgAltEntry = &entry;
4746     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4747      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4748     ok(!ret && GetLastError() == E_INVALIDARG,
4749      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4750     /* With an issuer name */
4751     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4752     U(entry).pwszURL = (LPWSTR)url;
4753     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4754      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4755     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4756     if (buf)
4757     {
4758         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4759          size);
4760         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4761          "Unexpected value\n");
4762         LocalFree(buf);
4763     }
4764     /* With just a serial number */
4765     info.AuthorityCertIssuer.cAltEntry = 0;
4766     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4767     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4768     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4769      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4770     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4771     if (buf)
4772     {
4773         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4774          size);
4775         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4776         LocalFree(buf);
4777     }
4778 }
4779
4780 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4781 {
4782     BOOL ret;
4783     LPBYTE buf = NULL;
4784     DWORD size = 0;
4785
4786     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4787      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4788      &buf, &size);
4789     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4790     if (buf)
4791     {
4792         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4793
4794         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4795          size);
4796         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4797         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4798          "Expected no issuer name entries\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      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4805      CRYPT_DECODE_ALLOC_FLAG, NULL, &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 == sizeof(keyId), "Unexpected key id len\n");
4814         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4815          "Unexpected key id\n");
4816         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4817          "Expected no issuer name entries\n");
4818         ok(info->AuthorityCertSerialNumber.cbData == 0,
4819          "Expected no serial number\n");
4820         LocalFree(buf);
4821     }
4822     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4823      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4824      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4825     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4826     if (buf)
4827     {
4828         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4829
4830         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4831          size);
4832         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4833         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4834          "Expected 1 issuer entry, got %d\n",
4835          info->AuthorityCertIssuer.cAltEntry);
4836         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4837          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4838          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4839         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4840          url), "Unexpected URL\n");
4841         ok(info->AuthorityCertSerialNumber.cbData == 0,
4842          "Expected no serial number\n");
4843         LocalFree(buf);
4844     }
4845     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4846      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4847      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4848     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4849     if (buf)
4850     {
4851         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4852
4853         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4854          size);
4855         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4856         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4857          "Expected no issuer name entries\n");
4858         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4859          "Unexpected serial number len\n");
4860         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4861          sizeof(serialNum)), "Unexpected serial number\n");
4862         LocalFree(buf);
4863     }
4864 }
4865
4866 static const BYTE authorityInfoAccessWithUrl[] = {
4867 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4868 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4869 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4870 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4871 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4872 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4873
4874 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4875 {
4876     static char oid1[] = "1.2.3";
4877     static char oid2[] = "1.5.6";
4878     BOOL ret;
4879     BYTE *buf = NULL;
4880     DWORD size = 0;
4881     CERT_ACCESS_DESCRIPTION accessDescription[2];
4882     CERT_AUTHORITY_INFO_ACCESS aia;
4883
4884     memset(accessDescription, 0, sizeof(accessDescription));
4885     aia.cAccDescr = 0;
4886     aia.rgAccDescr = NULL;
4887     /* Having no access descriptions is allowed */
4888     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4889      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4890     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4891     if (buf)
4892     {
4893         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4894         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4895         LocalFree(buf);
4896         buf = NULL;
4897     }
4898     /* It can't have an empty access method */
4899     aia.cAccDescr = 1;
4900     aia.rgAccDescr = accessDescription;
4901     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4902      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4903     ok(!ret && (GetLastError() == E_INVALIDARG ||
4904      GetLastError() == OSS_LIMITED /* Win9x */),
4905      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
4906     /* It can't have an empty location */
4907     accessDescription[0].pszAccessMethod = oid1;
4908     SetLastError(0xdeadbeef);
4909     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4910      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4911     ok(!ret && GetLastError() == E_INVALIDARG,
4912      "expected E_INVALIDARG, got %08x\n", GetLastError());
4913     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4914     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4915     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4916      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4917     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4918     if (buf)
4919     {
4920         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4921          size);
4922         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4923          "unexpected value\n");
4924         LocalFree(buf);
4925         buf = NULL;
4926     }
4927     accessDescription[1].pszAccessMethod = oid2;
4928     accessDescription[1].AccessLocation.dwAltNameChoice =
4929      CERT_ALT_NAME_IP_ADDRESS;
4930     U(accessDescription[1].AccessLocation).IPAddress.cbData =
4931      sizeof(encodedIPAddr);
4932     U(accessDescription[1].AccessLocation).IPAddress.pbData =
4933      (LPBYTE)encodedIPAddr;
4934     aia.cAccDescr = 2;
4935     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4936      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4937     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4938     if (buf)
4939     {
4940         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4941          "unexpected size %d\n", size);
4942         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4943          "unexpected value\n");
4944         LocalFree(buf);
4945         buf = NULL;
4946     }
4947 }
4948
4949 static void compareAuthorityInfoAccess(LPCSTR header,
4950  const CERT_AUTHORITY_INFO_ACCESS *expected,
4951  const CERT_AUTHORITY_INFO_ACCESS *got)
4952 {
4953     DWORD i;
4954
4955     ok(expected->cAccDescr == got->cAccDescr,
4956      "%s: expected %d access descriptions, got %d\n", header,
4957      expected->cAccDescr, got->cAccDescr);
4958     for (i = 0; i < expected->cAccDescr; i++)
4959     {
4960         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4961          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4962          header, i, expected->rgAccDescr[i].pszAccessMethod,
4963          got->rgAccDescr[i].pszAccessMethod);
4964         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4965          &got->rgAccDescr[i].AccessLocation);
4966     }
4967 }
4968
4969 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4970 {
4971     static char oid1[] = "1.2.3";
4972     static char oid2[] = "1.5.6";
4973     BOOL ret;
4974     LPBYTE buf = NULL;
4975     DWORD size = 0;
4976
4977     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4978      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4979      &buf, &size);
4980     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4981     if (buf)
4982     {
4983         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4984
4985         compareAuthorityInfoAccess("empty AIA", &aia,
4986          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4987         LocalFree(buf);
4988         buf = NULL;
4989     }
4990     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4991      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4992      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4993     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4994     if (buf)
4995     {
4996         CERT_ACCESS_DESCRIPTION accessDescription;
4997         CERT_AUTHORITY_INFO_ACCESS aia;
4998
4999         accessDescription.pszAccessMethod = oid1;
5000         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5001         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5002         aia.cAccDescr = 1;
5003         aia.rgAccDescr = &accessDescription;
5004         compareAuthorityInfoAccess("AIA with URL", &aia,
5005          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5006         LocalFree(buf);
5007         buf = NULL;
5008     }
5009     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5010      authorityInfoAccessWithUrlAndIPAddr,
5011      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5012      NULL, &buf, &size);
5013     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5014     if (buf)
5015     {
5016         CERT_ACCESS_DESCRIPTION accessDescription[2];
5017         CERT_AUTHORITY_INFO_ACCESS aia;
5018
5019         accessDescription[0].pszAccessMethod = oid1;
5020         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5021         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5022         accessDescription[1].pszAccessMethod = oid2;
5023         accessDescription[1].AccessLocation.dwAltNameChoice =
5024          CERT_ALT_NAME_IP_ADDRESS;
5025         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5026          sizeof(encodedIPAddr);
5027         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5028          (LPBYTE)encodedIPAddr;
5029         aia.cAccDescr = 2;
5030         aia.rgAccDescr = accessDescription;
5031         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5032          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5033         LocalFree(buf);
5034         buf = NULL;
5035     }
5036 }
5037
5038 static const BYTE emptyCTL[] = {
5039 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5040 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5041 static const BYTE emptyCTLWithVersion1[] = {
5042 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5043 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5044 static const BYTE ctlWithUsageIdentifier[] = {
5045 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5046 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5047 static const BYTE ctlWithListIdentifier[] = {
5048 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5049 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5050 static const BYTE ctlWithSequenceNumber[] = {
5051 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5052 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5053 static const BYTE ctlWithThisUpdate[] = {
5054 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5055 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5056 static const BYTE ctlWithThisAndNextUpdate[] = {
5057 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5058 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5059 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5060 static const BYTE ctlWithAlgId[] = {
5061 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5062 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5063 static const BYTE ctlWithBogusEntry[] = {
5064 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5065 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5066 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5067 static const BYTE ctlWithOneEntry[] = {
5068 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5069 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5070 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5071 static const BYTE ctlWithTwoEntries[] = {
5072 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5073 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5074 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5075 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5076 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5077
5078 static void test_encodeCTL(DWORD dwEncoding)
5079 {
5080     static char oid1[] = "1.2.3";
5081     static char oid2[] = "1.5.6";
5082     char *pOid1 = oid1;
5083     BOOL ret;
5084     BYTE *buf = NULL;
5085     DWORD size = 0;
5086     CTL_INFO info;
5087     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5088     CTL_ENTRY ctlEntry[2];
5089     CRYPT_ATTRIBUTE attr1, attr2;
5090     CRYPT_ATTR_BLOB value1, value2;
5091
5092     memset(&info, 0, sizeof(info));
5093     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5094      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5095     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5096     if (buf)
5097     {
5098         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5099         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5100         LocalFree(buf);
5101         buf = NULL;
5102     }
5103     info.dwVersion = 1;
5104     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5105      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5106     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5107     if (buf)
5108     {
5109         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5110         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5111         LocalFree(buf);
5112         buf = NULL;
5113     }
5114     info.dwVersion = 0;
5115     info.SubjectUsage.cUsageIdentifier = 1;
5116     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5117     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5118      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5119     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5120     if (buf)
5121     {
5122         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5123          size);
5124         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5125         LocalFree(buf);
5126         buf = NULL;
5127     }
5128     info.SubjectUsage.cUsageIdentifier = 0;
5129     info.ListIdentifier.cbData = sizeof(serialNum);
5130     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5131     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5132      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5133     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5134     if (buf)
5135     {
5136         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5137         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5138         LocalFree(buf);
5139         buf = NULL;
5140     }
5141     info.ListIdentifier.cbData = 0;
5142     info.SequenceNumber.cbData = sizeof(serialNum);
5143     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5144     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5145      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5146     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5147     if (buf)
5148     {
5149         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5150          size);
5151         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5152         LocalFree(buf);
5153         buf = NULL;
5154     }
5155     info.SequenceNumber.cbData = 0;
5156     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5157     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5158      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5159     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5160     if (buf)
5161     {
5162         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5163         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5164         LocalFree(buf);
5165         buf = NULL;
5166     }
5167     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5168     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5169      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5170     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5171     if (buf)
5172     {
5173         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5174          size);
5175         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5176         LocalFree(buf);
5177         buf = NULL;
5178     }
5179     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5180     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5181     info.SubjectAlgorithm.pszObjId = oid2;
5182     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5183      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5184     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5185     if (buf)
5186     {
5187         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5188         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5189         LocalFree(buf);
5190         buf = NULL;
5191     }
5192     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5193      * (see tests below) but it'll encode fine.
5194      */
5195     info.SubjectAlgorithm.pszObjId = NULL;
5196     value1.cbData = sizeof(serialNum);
5197     value1.pbData = (LPBYTE)serialNum;
5198     attr1.pszObjId = oid1;
5199     attr1.cValue = 1;
5200     attr1.rgValue = &value1;
5201     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5202     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5203     ctlEntry[0].cAttribute = 1;
5204     ctlEntry[0].rgAttribute = &attr1;
5205     info.cCTLEntry = 1;
5206     info.rgCTLEntry = ctlEntry;
5207     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5208      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5209     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5210     if (buf)
5211     {
5212         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5213         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5214         LocalFree(buf);
5215         buf = NULL;
5216     }
5217     value1.cbData = sizeof(emptySequence);
5218     value1.pbData = (LPBYTE)emptySequence;
5219     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5220      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5221     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5222     if (buf)
5223     {
5224         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5225         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5226         LocalFree(buf);
5227         buf = NULL;
5228     }
5229     value2.cbData = sizeof(encodedIPAddr);
5230     value2.pbData = (LPBYTE)encodedIPAddr;
5231     attr2.pszObjId = oid2;
5232     attr2.cValue = 1;
5233     attr2.rgValue = &value2;
5234     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5235     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5236     ctlEntry[1].cAttribute = 1;
5237     ctlEntry[1].rgAttribute = &attr2;
5238     info.cCTLEntry = 2;
5239     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5240      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5241     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5242     if (buf)
5243     {
5244         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5245         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5246         LocalFree(buf);
5247         buf = NULL;
5248     }
5249 }
5250
5251 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5252  const CTL_INFO *got)
5253 {
5254     DWORD i, j, k;
5255
5256     ok(expected->dwVersion == got->dwVersion,
5257      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5258      got->dwVersion);
5259     ok(expected->SubjectUsage.cUsageIdentifier ==
5260      got->SubjectUsage.cUsageIdentifier,
5261      "%s: expected %d usage identifiers, got %d\n", header,
5262      expected->SubjectUsage.cUsageIdentifier,
5263      got->SubjectUsage.cUsageIdentifier);
5264     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5265         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5266          got->SubjectUsage.rgpszUsageIdentifier[i]),
5267          "%s[%d]: expected %s, got %s\n", header, i,
5268          expected->SubjectUsage.rgpszUsageIdentifier[i],
5269          got->SubjectUsage.rgpszUsageIdentifier[i]);
5270     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5271      "%s: expected list identifier of %d bytes, got %d\n", header,
5272      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5273     if (expected->ListIdentifier.cbData)
5274         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5275          expected->ListIdentifier.cbData),
5276          "%s: unexpected list identifier value\n", header);
5277     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5278      "%s: expected sequence number of %d bytes, got %d\n", header,
5279      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5280     if (expected->SequenceNumber.cbData)
5281         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5282          expected->SequenceNumber.cbData),
5283          "%s: unexpected sequence number value\n", header);
5284     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5285      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5286      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5287      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5288     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5289      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5290      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5291      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5292     if (expected->SubjectAlgorithm.pszObjId &&
5293      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5294         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5295          expected->SubjectAlgorithm.pszObjId);
5296     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5297         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5298          got->SubjectAlgorithm.pszObjId),
5299          "%s: expected subject algorithm %s, got %s\n", header,
5300          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5301     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5302      got->SubjectAlgorithm.Parameters.cbData,
5303      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5304      expected->SubjectAlgorithm.Parameters.cbData,
5305      got->SubjectAlgorithm.Parameters.cbData);
5306     if (expected->SubjectAlgorithm.Parameters.cbData)
5307         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5308          got->SubjectAlgorithm.Parameters.pbData,
5309          expected->SubjectAlgorithm.Parameters.cbData),
5310          "%s: unexpected subject algorithm parameter value\n", header);
5311     ok(expected->cCTLEntry == got->cCTLEntry,
5312      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5313      got->cCTLEntry);
5314     for (i = 0; i < expected->cCTLEntry; i++)
5315     {
5316         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5317          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5318          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5319          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5320          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5321         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5322             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5323              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5324              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5325              "%s[%d]: unexpected subject identifier value\n",
5326              header, i);
5327         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5328         {
5329             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5330              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5331              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5332              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5333              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5334             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5335             {
5336                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5337                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5338                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5339                  header, i, j, k,
5340                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5341                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5342                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5343                     ok(!memcmp(
5344                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5345                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5346                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5347                      "%s[%d][%d][%d]: unexpected value\n",
5348                      header, i, j, k);
5349             }
5350         }
5351     }
5352     ok(expected->cExtension == got->cExtension,
5353      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5354      got->cExtension);
5355     for (i = 0; i < expected->cExtension; i++)
5356     {
5357         ok(!strcmp(expected->rgExtension[i].pszObjId,
5358          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5359          header, i, expected->rgExtension[i].pszObjId,
5360          got->rgExtension[i].pszObjId);
5361         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5362          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5363          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5364         ok(expected->rgExtension[i].Value.cbData ==
5365          got->rgExtension[i].Value.cbData,
5366          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5367          header, i, expected->rgExtension[i].Value.cbData,
5368          got->rgExtension[i].Value.cbData);
5369         if (expected->rgExtension[i].Value.cbData)
5370             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5371              got->rgExtension[i].Value.pbData,
5372              expected->rgExtension[i].Value.cbData),
5373              "%s[%d]: unexpected extension value\n", header, i);
5374     }
5375 }
5376
5377 static const BYTE signedCTL[] = {
5378 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5379 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5380 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5381 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5382 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5383 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5384 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5385 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5386 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5387 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5388 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5389 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5390 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5391 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5392 static const BYTE signedCTLWithCTLInnerContent[] = {
5393 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5394 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5395 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5396 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5397 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5398 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5399 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5400 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5401 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5402 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5403 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5404 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5405 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5406 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5407 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5408 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5409 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5410 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5411 0x57,0x6c,0x0b,0x47,0xb8 };
5412
5413 static void test_decodeCTL(DWORD dwEncoding)
5414 {
5415     static char oid1[] = "1.2.3";
5416     static char oid2[] = "1.5.6";
5417     static BYTE nullData[] = { 5,0 };
5418     char *pOid1 = oid1;
5419     BOOL ret;
5420     BYTE *buf = NULL;
5421     DWORD size = 0;
5422     CTL_INFO info;
5423     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5424     CTL_ENTRY ctlEntry[2];
5425     CRYPT_ATTRIBUTE attr1, attr2;
5426     CRYPT_ATTR_BLOB value1, value2;
5427
5428     memset(&info, 0, sizeof(info));
5429     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5430      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5431     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5432     if (buf)
5433     {
5434         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5435         LocalFree(buf);
5436         buf = NULL;
5437     }
5438     info.dwVersion = 1;
5439     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5440      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5441      &size);
5442     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5443     if (buf)
5444     {
5445         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5446         LocalFree(buf);
5447         buf = NULL;
5448     }
5449     info.dwVersion = 0;
5450     info.SubjectUsage.cUsageIdentifier = 1;
5451     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5452     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5453      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5454      &buf, &size);
5455     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5456     if (buf)
5457     {
5458         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5459         LocalFree(buf);
5460         buf = NULL;
5461     }
5462     info.SubjectUsage.cUsageIdentifier = 0;
5463     info.ListIdentifier.cbData = sizeof(serialNum);
5464     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5465     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5466      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5467     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5468     if (buf)
5469     {
5470         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5471         LocalFree(buf);
5472         buf = NULL;
5473     }
5474     info.ListIdentifier.cbData = 0;
5475     info.SequenceNumber.cbData = sizeof(serialNum);
5476     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5477     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5478      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5479     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5480     if (buf)
5481     {
5482         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5483         LocalFree(buf);
5484         buf = NULL;
5485     }
5486     info.SequenceNumber.cbData = 0;
5487     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5488     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5489      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5490     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5491     if (buf)
5492     {
5493         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5494         LocalFree(buf);
5495         buf = NULL;
5496     }
5497     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5498     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5499      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5500      &buf, &size);
5501     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5502     if (buf)
5503     {
5504         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5505         LocalFree(buf);
5506         buf = NULL;
5507     }
5508     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5509     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5510     info.SubjectAlgorithm.pszObjId = oid2;
5511     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5512     info.SubjectAlgorithm.Parameters.pbData = nullData;
5513     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5514      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5515     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5516     if (buf)
5517     {
5518         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5519         LocalFree(buf);
5520         buf = NULL;
5521     }
5522     SetLastError(0xdeadbeef);
5523     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5524      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5525     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT),
5526      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5527      GetLastError());
5528     info.SubjectAlgorithm.Parameters.cbData = 0;
5529     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5530     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5531     info.SubjectAlgorithm.pszObjId = oid2;
5532     info.SubjectAlgorithm.pszObjId = NULL;
5533     value1.cbData = sizeof(emptySequence);
5534     value1.pbData = (LPBYTE)emptySequence;
5535     attr1.pszObjId = oid1;
5536     attr1.cValue = 1;
5537     attr1.rgValue = &value1;
5538     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5539     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5540     ctlEntry[0].cAttribute = 1;
5541     ctlEntry[0].rgAttribute = &attr1;
5542     info.cCTLEntry = 1;
5543     info.rgCTLEntry = ctlEntry;
5544     SetLastError(0xdeadbeef);
5545     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5546      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5547     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5548     if (buf)
5549     {
5550         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5551         LocalFree(buf);
5552         buf = NULL;
5553     }
5554     value2.cbData = sizeof(encodedIPAddr);
5555     value2.pbData = (LPBYTE)encodedIPAddr;
5556     attr2.pszObjId = oid2;
5557     attr2.cValue = 1;
5558     attr2.rgValue = &value2;
5559     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5560     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5561     ctlEntry[1].cAttribute = 1;
5562     ctlEntry[1].rgAttribute = &attr2;
5563     info.cCTLEntry = 2;
5564     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5565      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5566     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5567     if (buf)
5568     {
5569         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5570         LocalFree(buf);
5571         buf = NULL;
5572     }
5573     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5574     SetLastError(0xdeadbeef);
5575     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5576      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5577     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5578      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5579      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5580      GetLastError());
5581     SetLastError(0xdeadbeef);
5582     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5583      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5584      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5585     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5586      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5587      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5588      GetLastError());
5589 }
5590
5591 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5592 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5593  0x03,0,0,0,0,0,0 };
5594 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5595  0xa0,0x01,0x01 };
5596 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5597  0x03,0x02,0x01,0x01 };
5598 static BYTE bogusDER[] = { 1 };
5599
5600 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5601 {
5602     BOOL ret;
5603     BYTE *buf = NULL;
5604     DWORD size = 0;
5605     CRYPT_CONTENT_INFO info = { 0 };
5606     char oid1[] = "1.2.3";
5607
5608     if (0)
5609     {
5610         /* Crashes on win9x */
5611         SetLastError(0xdeadbeef);
5612         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5613          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5614         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5615          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5616     }
5617     SetLastError(0xdeadbeef);
5618     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5619      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5620     ok(!ret && (GetLastError() == E_INVALIDARG ||
5621      GetLastError() == OSS_LIMITED /* Win9x */),
5622      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5623     info.pszObjId = oid1;
5624     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5625      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5626     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5627     if (buf)
5628     {
5629         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5630         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5631         LocalFree(buf);
5632     }
5633     info.Content.pbData = bogusDER;
5634     info.Content.cbData = sizeof(bogusDER);
5635     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5636      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5637     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5638     if (buf)
5639     {
5640         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5641         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5642         LocalFree(buf);
5643     }
5644     info.Content.pbData = (BYTE *)ints[0].encoded;
5645     info.Content.cbData = ints[0].encoded[1] + 2;
5646     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5647      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5648     if (buf)
5649     {
5650         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5651         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5652         LocalFree(buf);
5653     }
5654 }
5655
5656 static const BYTE indefiniteSignedPKCSContent[] = {
5657 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5658 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5659 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5660 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5661 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5662 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5663 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5664 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5665 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5666 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5667 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5668 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5669 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5670 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5671 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5672 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5673 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5674 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5675 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5676 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5677 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5678 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5679 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5680 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5681 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5682 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5683 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5684 0x00,0x00,0x00,0x00,0x00,0x00 };
5685
5686 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5687 {
5688     BOOL ret;
5689     LPBYTE buf = NULL;
5690     DWORD size = 0;
5691     CRYPT_CONTENT_INFO *info;
5692
5693     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5694      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5695      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5696     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5697     if (buf)
5698     {
5699         info = (CRYPT_CONTENT_INFO *)buf;
5700
5701         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5702          info->pszObjId);
5703         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5704          info->Content.cbData);
5705         LocalFree(buf);
5706     }
5707     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5708      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5709      0, NULL, NULL, &size);
5710     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5711     SetLastError(0xdeadbeef);
5712     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5713      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5714      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5715     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5716      * I doubt an app depends on that.
5717      */
5718     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5719      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5720      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5721      GetLastError());
5722     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5723      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5724      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5725     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5726     if (buf)
5727     {
5728         info = (CRYPT_CONTENT_INFO *)buf;
5729
5730         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5731          info->pszObjId);
5732         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5733          "Unexpected size %d\n", info->Content.cbData);
5734         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5735          info->Content.cbData), "Unexpected value\n");
5736         LocalFree(buf);
5737     }
5738     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5739      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5740      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5741     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5742     if (buf)
5743     {
5744         info = (CRYPT_CONTENT_INFO *)buf;
5745
5746         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5747          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5748         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5749          info->Content.cbData);
5750         LocalFree(buf);
5751     }
5752 }
5753
5754 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5755  0x00 };
5756 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5757  0x01 };
5758 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5759  0x02,0x01,0x01 };
5760
5761 static void test_encodePKCSAttribute(DWORD dwEncoding)
5762 {
5763     CRYPT_ATTRIBUTE attr = { 0 };
5764     BOOL ret;
5765     LPBYTE buf = NULL;
5766     DWORD size = 0;
5767     CRYPT_ATTR_BLOB blob;
5768     char oid[] = "1.2.3";
5769
5770     if (0)
5771     {
5772         /* Crashes on win9x */
5773         SetLastError(0xdeadbeef);
5774         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5775          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5776         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5777          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5778     }
5779     SetLastError(0xdeadbeef);
5780     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5781      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5782     ok(!ret && (GetLastError() == E_INVALIDARG ||
5783      GetLastError() == OSS_LIMITED /* Win9x */),
5784      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5785     attr.pszObjId = oid;
5786     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5787      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5788     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5789     if (buf)
5790     {
5791         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5792         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5793         LocalFree(buf);
5794     }
5795     blob.cbData = sizeof(bogusDER);
5796     blob.pbData = bogusDER;
5797     attr.cValue = 1;
5798     attr.rgValue = &blob;
5799     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5800      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5801     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5802     if (buf)
5803     {
5804         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5805         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5806         LocalFree(buf);
5807     }
5808     blob.pbData = (BYTE *)ints[0].encoded;
5809     blob.cbData = ints[0].encoded[1] + 2;
5810     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5811      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5812     if (buf)
5813     {
5814         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5815         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5816         LocalFree(buf);
5817     }
5818 }
5819
5820 static void test_decodePKCSAttribute(DWORD dwEncoding)
5821 {
5822     BOOL ret;
5823     LPBYTE buf = NULL;
5824     DWORD size = 0;
5825     CRYPT_ATTRIBUTE *attr;
5826
5827     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5828      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5829      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5830     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5831     if (buf)
5832     {
5833         attr = (CRYPT_ATTRIBUTE *)buf;
5834
5835         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5836          attr->pszObjId);
5837         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5838         LocalFree(buf);
5839     }
5840     SetLastError(0xdeadbeef);
5841     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5842      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5843      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5844     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5845      * I doubt an app depends on that.
5846      */
5847     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5848      GetLastError() == CRYPT_E_ASN1_CORRUPT || OSS_MORE_INPUT /* Win9x */),
5849      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
5850      GetLastError());
5851     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5852      intPKCSAttr, sizeof(intPKCSAttr),
5853      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5854     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5855     if (buf)
5856     {
5857         attr = (CRYPT_ATTRIBUTE *)buf;
5858
5859         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5860          attr->pszObjId);
5861         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5862         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5863          "Unexpected size %d\n", attr->rgValue[0].cbData);
5864         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5865          attr->rgValue[0].cbData), "Unexpected value\n");
5866         LocalFree(buf);
5867     }
5868 }
5869
5870 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5871 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5872  0x2a,0x03,0x31,0x00 };
5873 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5874  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5875
5876 static void test_encodePKCSAttributes(DWORD dwEncoding)
5877 {
5878     CRYPT_ATTRIBUTES attributes = { 0 };
5879     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5880     CRYPT_ATTR_BLOB blob;
5881     BOOL ret;
5882     LPBYTE buf = NULL;
5883     DWORD size = 0;
5884     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5885
5886     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5887      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5888     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5889     if (buf)
5890     {
5891         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5892         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5893         LocalFree(buf);
5894     }
5895     attributes.cAttr = 1;
5896     attributes.rgAttr = attr;
5897     SetLastError(0xdeadbeef);
5898     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5899      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5900     ok(!ret && (GetLastError() == E_INVALIDARG ||
5901      GetLastError() == OSS_LIMITED /* Win9x */),
5902      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5903     attr[0].pszObjId = oid1;
5904     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5905      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5906     if (buf)
5907     {
5908         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5909         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5910         LocalFree(buf);
5911     }
5912     attr[1].pszObjId = oid2;
5913     attr[1].cValue = 1;
5914     attr[1].rgValue = &blob;
5915     blob.pbData = (BYTE *)ints[0].encoded;
5916     blob.cbData = ints[0].encoded[1] + 2;
5917     attributes.cAttr = 2;
5918     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5919      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5920     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5921     if (buf)
5922     {
5923         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5924         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5925         LocalFree(buf);
5926     }
5927 }
5928
5929 static void test_decodePKCSAttributes(DWORD dwEncoding)
5930 {
5931     BOOL ret;
5932     LPBYTE buf = NULL;
5933     DWORD size = 0;
5934     CRYPT_ATTRIBUTES *attributes;
5935
5936     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5937      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5938      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5939     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5940     if (buf)
5941     {
5942         attributes = (CRYPT_ATTRIBUTES *)buf;
5943         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5944          attributes->cAttr);
5945         LocalFree(buf);
5946     }
5947     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5948      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5949      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5950     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5951     if (buf)
5952     {
5953         attributes = (CRYPT_ATTRIBUTES *)buf;
5954         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5955          attributes->cAttr);
5956         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5957          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5958         ok(attributes->rgAttr[0].cValue == 0,
5959          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5960         LocalFree(buf);
5961     }
5962     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5963      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5964      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5965     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5966     if (buf)
5967     {
5968         attributes = (CRYPT_ATTRIBUTES *)buf;
5969         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5970          attributes->cAttr);
5971         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5972          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5973         ok(attributes->rgAttr[0].cValue == 0,
5974          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5975         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5976          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5977         ok(attributes->rgAttr[1].cValue == 1,
5978          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5979         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5980          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5981         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5982          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5983         LocalFree(buf);
5984     }
5985 }
5986
5987 static const BYTE singleCapability[] = {
5988 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5989 static const BYTE twoCapabilities[] = {
5990 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5991 static const BYTE singleCapabilitywithNULL[] = {
5992 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5993
5994 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
5995 {
5996     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5997     BOOL ret;
5998     LPBYTE buf = NULL;
5999     DWORD size = 0;
6000     CRYPT_SMIME_CAPABILITY capability[2];
6001     CRYPT_SMIME_CAPABILITIES capabilities;
6002
6003     /* An empty capabilities is allowed */
6004     capabilities.cCapability = 0;
6005     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6006      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6007     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6008     if (buf)
6009     {
6010         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6011         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6012         LocalFree(buf);
6013     }
6014     /* A non-empty capabilities with an empty capability (lacking an OID) is
6015      * not allowed
6016      */
6017     capability[0].pszObjId = NULL;
6018     capability[0].Parameters.cbData = 0;
6019     capabilities.cCapability = 1;
6020     capabilities.rgCapability = capability;
6021     SetLastError(0xdeadbeef);
6022     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6023      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6024     ok(!ret && (GetLastError() == E_INVALIDARG ||
6025      GetLastError() == OSS_LIMITED /* Win9x */),
6026      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6027     capability[0].pszObjId = oid1;
6028     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6029      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6030     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6031     if (buf)
6032     {
6033         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6034         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6035         LocalFree(buf);
6036     }
6037     capability[1].pszObjId = oid2;
6038     capability[1].Parameters.cbData = 0;
6039     capabilities.cCapability = 2;
6040     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6041      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6042     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6043     if (buf)
6044     {
6045         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6046         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6047         LocalFree(buf);
6048     }
6049 }
6050
6051 static void compareSMimeCapabilities(LPCSTR header,
6052  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6053 {
6054     DWORD i;
6055
6056     ok(got->cCapability == expected->cCapability,
6057      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6058      got->cCapability);
6059     for (i = 0; i < expected->cCapability; i++)
6060     {
6061         ok(!strcmp(expected->rgCapability[i].pszObjId,
6062          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6063          header, i, expected->rgCapability[i].pszObjId,
6064          got->rgCapability[i].pszObjId);
6065         ok(expected->rgCapability[i].Parameters.cbData ==
6066          got->rgCapability[i].Parameters.cbData,
6067          "%s[%d]: expected %d bytes, got %d\n", header, i,
6068          expected->rgCapability[i].Parameters.cbData,
6069          got->rgCapability[i].Parameters.cbData);
6070         if (expected->rgCapability[i].Parameters.cbData)
6071             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6072              got->rgCapability[i].Parameters.pbData,
6073              expected->rgCapability[i].Parameters.cbData),
6074              "%s[%d]: unexpected value\n", header, i);
6075     }
6076 }
6077
6078 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6079 {
6080     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6081     BOOL ret;
6082     DWORD size = 0;
6083     CRYPT_SMIME_CAPABILITY capability[2];
6084     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6085
6086     SetLastError(0xdeadbeef);
6087     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6088      emptySequence, sizeof(emptySequence),
6089      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6090     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6091     if (ret)
6092     {
6093         capabilities.cCapability = 0;
6094         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6095         LocalFree(ptr);
6096     }
6097     SetLastError(0xdeadbeef);
6098     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6099      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6100      &ptr, &size);
6101     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6102     if (ret)
6103     {
6104         capability[0].pszObjId = oid1;
6105         capability[0].Parameters.cbData = 0;
6106         capabilities.cCapability = 1;
6107         capabilities.rgCapability = capability;
6108         compareSMimeCapabilities("single capability", &capabilities, ptr);
6109         LocalFree(ptr);
6110     }
6111     SetLastError(0xdeadbeef);
6112     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6113      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6114      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6115     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6116     if (ret)
6117     {
6118         BYTE NULLparam[] = {0x05, 0x00};
6119         capability[0].pszObjId = oid1;
6120         capability[0].Parameters.cbData = 2;
6121         capability[0].Parameters.pbData = NULLparam;
6122         capabilities.cCapability = 1;
6123         capabilities.rgCapability = capability;
6124         compareSMimeCapabilities("single capability with NULL", &capabilities,
6125          ptr);
6126         LocalFree(ptr);
6127     }
6128     SetLastError(0xdeadbeef);
6129     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6130     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6131     &ptr, &size);
6132     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6133     if (ret)
6134     {
6135         capability[0].Parameters.cbData = 0;
6136         capability[1].pszObjId = oid2;
6137         capability[1].Parameters.cbData = 0;
6138         capabilities.cCapability = 2;
6139         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6140         LocalFree(ptr);
6141     }
6142 }
6143
6144 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6145  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6146  0x67 };
6147 static const BYTE minimalPKCSSigner[] = {
6148  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6149  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6150  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6151 static const BYTE PKCSSignerWithSerial[] = {
6152  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6153  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6154  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6155  0x00 };
6156 static const BYTE PKCSSignerWithHashAlgo[] = {
6157  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6158  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6159  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6160  0x00,0x04,0x00 };
6161 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6162  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6163  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6164  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6165  0x06,0x05,0x00,0x04,0x00 };
6166 static const BYTE PKCSSignerWithHash[] = {
6167  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6168  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6169  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6170  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6171  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6172 static const BYTE PKCSSignerWithAuthAttr[] = {
6173 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6174 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6175 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6176 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6177 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6178 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6179 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6180
6181 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6182 {
6183     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6184     BOOL ret;
6185     LPBYTE buf = NULL;
6186     DWORD size = 0;
6187     CMSG_SIGNER_INFO info = { 0 };
6188     char oid_common_name[] = szOID_COMMON_NAME;
6189     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6190      (LPBYTE)encodedCommonName };
6191     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6192
6193     SetLastError(0xdeadbeef);
6194     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6195      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6196     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6197     {
6198         skip("no PKCS7_SIGNER_INFO encode support\n");
6199         return;
6200     }
6201     ok(!ret && (GetLastError() == E_INVALIDARG ||
6202      GetLastError() == OSS_LIMITED /* Win9x */),
6203      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6204     /* To be encoded, a signer must have an issuer at least, and the encoding
6205      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6206      * see decoding tests.)
6207      */
6208     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6209     info.Issuer.pbData = encodedCommonNameNoNull;
6210     SetLastError(0xdeadbeef);
6211     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6212      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6213     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6214         ok(!ret && GetLastError() == E_INVALIDARG,
6215          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6216     else
6217     {
6218         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6219          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6220         if (buf)
6221         {
6222             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6223             if (size == sizeof(minimalPKCSSigner))
6224                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6225             else
6226                 ok(0, "Unexpected value\n");
6227             LocalFree(buf);
6228         }
6229     }
6230     info.SerialNumber.cbData = sizeof(serialNum);
6231     info.SerialNumber.pbData = (BYTE *)serialNum;
6232     SetLastError(0xdeadbeef);
6233     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6234      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6235     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6236         ok(!ret && GetLastError() == E_INVALIDARG,
6237          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6238     else
6239     {
6240         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6241          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6242         if (buf)
6243         {
6244             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6245              size);
6246             if (size == sizeof(PKCSSignerWithSerial))
6247                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6248                  "Unexpected value\n");
6249             else
6250                 ok(0, "Unexpected value\n");
6251             LocalFree(buf);
6252         }
6253     }
6254     info.HashAlgorithm.pszObjId = oid1;
6255     SetLastError(0xdeadbeef);
6256     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6257      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6258     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6259         ok(!ret && GetLastError() == E_INVALIDARG,
6260          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6261     else
6262     {
6263         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6264          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6265         if (buf)
6266         {
6267             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6268              size);
6269             if (size == sizeof(PKCSSignerWithHashAlgo))
6270                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6271                  "Unexpected value\n");
6272             else
6273                 ok(0, "Unexpected value\n");
6274             LocalFree(buf);
6275         }
6276     }
6277     info.HashEncryptionAlgorithm.pszObjId = oid2;
6278     SetLastError(0xdeadbeef);
6279     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6280      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6281     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6282         ok(!ret && GetLastError() == E_INVALIDARG,
6283          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6284     else
6285     {
6286         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6287         if (buf)
6288         {
6289             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6290              "Unexpected size %d\n", size);
6291             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6292                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6293                  "Unexpected value\n");
6294             else
6295                 ok(0, "Unexpected value\n");
6296             LocalFree(buf);
6297         }
6298     }
6299     info.EncryptedHash.cbData = sizeof(hash);
6300     info.EncryptedHash.pbData = (BYTE *)hash;
6301     SetLastError(0xdeadbeef);
6302     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6303      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6304     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6305         ok(!ret && GetLastError() == E_INVALIDARG,
6306          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6307     else
6308     {
6309         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6310         if (buf)
6311         {
6312             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6313              size);
6314             if (size == sizeof(PKCSSignerWithHash))
6315                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6316                  "Unexpected value\n");
6317             else
6318                 ok(0, "Unexpected value\n");
6319             LocalFree(buf);
6320         }
6321     }
6322     info.AuthAttrs.cAttr = 1;
6323     info.AuthAttrs.rgAttr = &attr;
6324     SetLastError(0xdeadbeef);
6325     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6326      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6327     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6328         ok(!ret && GetLastError() == E_INVALIDARG,
6329          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6330     else
6331     {
6332         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6333         if (buf)
6334         {
6335             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6336              size);
6337             if (size == sizeof(PKCSSignerWithAuthAttr))
6338                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6339                  "Unexpected value\n");
6340             else
6341                 ok(0, "Unexpected value\n");
6342             LocalFree(buf);
6343         }
6344     }
6345 }
6346
6347 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6348 {
6349     BOOL ret;
6350     LPBYTE buf = NULL;
6351     DWORD size = 0;
6352     CMSG_SIGNER_INFO *info;
6353
6354     /* A PKCS signer can't be decoded without a serial number. */
6355     SetLastError(0xdeadbeef);
6356     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6357      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6358      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6359     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6360      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6361      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6362      GetLastError());
6363     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6364      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6365      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6366     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6367      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6368     if (buf)
6369     {
6370         info = (CMSG_SIGNER_INFO *)buf;
6371         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6372          info->dwVersion);
6373         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6374          "Unexpected size %d\n", info->Issuer.cbData);
6375         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6376          info->Issuer.cbData), "Unexpected value\n");
6377         ok(info->SerialNumber.cbData == sizeof(serialNum),
6378          "Unexpected size %d\n", info->SerialNumber.cbData);
6379         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6380          "Unexpected value\n");
6381         LocalFree(buf);
6382     }
6383     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6384      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6385      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6386     if (buf)
6387     {
6388         info = (CMSG_SIGNER_INFO *)buf;
6389         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6390          info->dwVersion);
6391         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6392          "Unexpected size %d\n", info->Issuer.cbData);
6393         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6394          info->Issuer.cbData), "Unexpected value\n");
6395         ok(info->SerialNumber.cbData == sizeof(serialNum),
6396          "Unexpected size %d\n", info->SerialNumber.cbData);
6397         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6398          "Unexpected value\n");
6399         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6400          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6401         LocalFree(buf);
6402     }
6403     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6404      PKCSSignerWithHashAndEncryptionAlgo,
6405      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6406      NULL, &buf, &size);
6407     if (buf)
6408     {
6409         info = (CMSG_SIGNER_INFO *)buf;
6410         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6411          info->dwVersion);
6412         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6413          "Unexpected size %d\n", info->Issuer.cbData);
6414         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6415          info->Issuer.cbData), "Unexpected value\n");
6416         ok(info->SerialNumber.cbData == sizeof(serialNum),
6417          "Unexpected size %d\n", info->SerialNumber.cbData);
6418         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6419          "Unexpected value\n");
6420         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6421          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6422         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6423          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6424         LocalFree(buf);
6425     }
6426     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6427      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6428      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6429     if (buf)
6430     {
6431         info = (CMSG_SIGNER_INFO *)buf;
6432         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6433          info->dwVersion);
6434         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6435          "Unexpected size %d\n", info->Issuer.cbData);
6436         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6437          info->Issuer.cbData), "Unexpected value\n");
6438         ok(info->SerialNumber.cbData == sizeof(serialNum),
6439          "Unexpected size %d\n", info->SerialNumber.cbData);
6440         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6441          "Unexpected value\n");
6442         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6443          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6444         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6445          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6446         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6447          info->EncryptedHash.cbData);
6448         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6449          "Unexpected value\n");
6450         LocalFree(buf);
6451     }
6452     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6453      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6454      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6455     if (buf)
6456     {
6457         info = (CMSG_SIGNER_INFO *)buf;
6458         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6459          info->AuthAttrs.cAttr);
6460         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6461          "Expected %s, got %s\n", szOID_COMMON_NAME,
6462          info->AuthAttrs.rgAttr[0].pszObjId);
6463         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6464          info->AuthAttrs.rgAttr[0].cValue);
6465         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6466          sizeof(encodedCommonName), "Unexpected size %d\n",
6467          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6468         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6469          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6470         LocalFree(buf);
6471     }
6472 }
6473
6474 static const BYTE CMSSignerWithKeyId[] = {
6475 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6476 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6477
6478 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6479 {
6480     BOOL ret;
6481     LPBYTE buf = NULL;
6482     DWORD size = 0;
6483     CMSG_CMS_SIGNER_INFO info = { 0 };
6484     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6485
6486     SetLastError(0xdeadbeef);
6487     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6488      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6489     ok(!ret, "Expected failure, got %d\n", ret);
6490     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6491     {
6492         skip("no CMS_SIGNER_INFO encode support\n");
6493         return;
6494     }
6495     ok(GetLastError() == E_INVALIDARG,
6496        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6497     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6498     SetLastError(0xdeadbeef);
6499     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6500      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6501     ok(!ret, "Expected failure, got %d\n", ret);
6502     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6503     {
6504         skip("no CMS_SIGNER_INFO encode support\n");
6505         return;
6506     }
6507     ok(GetLastError() == E_INVALIDARG,
6508        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6509     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6510      * be a key id or a issuer serial number with at least the issuer set, and
6511      * the encoding must include PKCS_7_ASN_ENCODING.
6512      * (That isn't enough to be decoded, see decoding tests.)
6513      */
6514     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6515      sizeof(encodedCommonNameNoNull);
6516     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6517     SetLastError(0xdeadbeef);
6518     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6519      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6520     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6521         ok(!ret && GetLastError() == E_INVALIDARG,
6522          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6523     else
6524     {
6525         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6526         if (buf)
6527         {
6528             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6529             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6530             LocalFree(buf);
6531         }
6532     }
6533     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6534     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6535     SetLastError(0xdeadbeef);
6536     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6537      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6538     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6539         ok(!ret && GetLastError() == E_INVALIDARG,
6540          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6541     else
6542     {
6543         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6544         if (buf)
6545         {
6546             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6547              size);
6548             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6549             LocalFree(buf);
6550         }
6551     }
6552     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6553     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6554     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6555     SetLastError(0xdeadbeef);
6556     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6557      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6558     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6559         ok(!ret && GetLastError() == E_INVALIDARG,
6560          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6561     else
6562     {
6563         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6564         if (buf)
6565         {
6566             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6567              size);
6568             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6569             LocalFree(buf);
6570         }
6571     }
6572     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6573      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6574      * (see RFC 3852, section 5.3.)
6575      */
6576     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6577     U(info.SignerId).HashId.cbData = sizeof(hash);
6578     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6579     SetLastError(0xdeadbeef);
6580     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6581      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6582     ok(!ret && GetLastError() == E_INVALIDARG,
6583      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6584     /* Now with a hash algo */
6585     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6586     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6587      sizeof(encodedCommonNameNoNull);
6588     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6589     info.HashAlgorithm.pszObjId = oid1;
6590     SetLastError(0xdeadbeef);
6591     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6592      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6593     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6594         ok(!ret && GetLastError() == E_INVALIDARG,
6595          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6596     else
6597     {
6598         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6599         if (buf)
6600         {
6601             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6602              size);
6603             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6604              "Unexpected value\n");
6605             LocalFree(buf);
6606         }
6607     }
6608     info.HashEncryptionAlgorithm.pszObjId = oid2;
6609     SetLastError(0xdeadbeef);
6610     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6611      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6612     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6613         ok(!ret && GetLastError() == E_INVALIDARG,
6614          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6615     else
6616     {
6617         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6618         if (buf)
6619         {
6620             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6621              "Unexpected size %d\n", size);
6622             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6623              "Unexpected value\n");
6624             LocalFree(buf);
6625         }
6626     }
6627     info.EncryptedHash.cbData = sizeof(hash);
6628     info.EncryptedHash.pbData = (BYTE *)hash;
6629     SetLastError(0xdeadbeef);
6630     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6631      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6632     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6633         ok(!ret && GetLastError() == E_INVALIDARG,
6634          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6635     else
6636     {
6637         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6638         if (buf)
6639         {
6640             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6641              size);
6642             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6643             LocalFree(buf);
6644         }
6645     }
6646 }
6647
6648 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6649 {
6650     BOOL ret;
6651     LPBYTE buf = NULL;
6652     DWORD size = 0;
6653     CMSG_CMS_SIGNER_INFO *info;
6654     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6655
6656     /* A CMS signer can't be decoded without a serial number. */
6657     SetLastError(0xdeadbeef);
6658     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6659      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6660      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6661     ok(!ret, "expected failure\n");
6662     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6663     {
6664         skip("no CMS_SIGNER_INFO decode support\n");
6665         return;
6666     }
6667     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6668      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6669     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6670      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6671      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6672     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6673     if (buf)
6674     {
6675         info = (CMSG_CMS_SIGNER_INFO *)buf;
6676         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6677          info->dwVersion);
6678         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6679          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6680          info->SignerId.dwIdChoice);
6681         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6682          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6683          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6684         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6685          encodedCommonNameNoNull,
6686          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6687          "Unexpected value\n");
6688         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6689          sizeof(serialNum), "Unexpected size %d\n",
6690          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6691         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6692          serialNum, sizeof(serialNum)), "Unexpected value\n");
6693         LocalFree(buf);
6694     }
6695     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6696      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6697      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6698     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6699     if (buf)
6700     {
6701         info = (CMSG_CMS_SIGNER_INFO *)buf;
6702         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6703          info->dwVersion);
6704         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6705          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6706          info->SignerId.dwIdChoice);
6707         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6708          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6709          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6710         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6711          encodedCommonNameNoNull,
6712          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6713          "Unexpected value\n");
6714         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6715          sizeof(serialNum), "Unexpected size %d\n",
6716          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6717         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6718          serialNum, sizeof(serialNum)), "Unexpected value\n");
6719         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6720          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6721         LocalFree(buf);
6722     }
6723     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6724      PKCSSignerWithHashAndEncryptionAlgo,
6725      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6726      NULL, &buf, &size);
6727     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6728     if (buf)
6729     {
6730         info = (CMSG_CMS_SIGNER_INFO *)buf;
6731         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6732          info->dwVersion);
6733         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6734          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6735          info->SignerId.dwIdChoice);
6736         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6737          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6738          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6739         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6740          encodedCommonNameNoNull,
6741          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6742          "Unexpected value\n");
6743         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6744          sizeof(serialNum), "Unexpected size %d\n",
6745          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6746         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6747          serialNum, sizeof(serialNum)), "Unexpected value\n");
6748         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6749          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6750         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6751          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6752         LocalFree(buf);
6753     }
6754     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6755      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6756      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6757     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6758     if (buf)
6759     {
6760         info = (CMSG_CMS_SIGNER_INFO *)buf;
6761         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6762          info->dwVersion);
6763         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6764          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6765          info->SignerId.dwIdChoice);
6766         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6767          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6768          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6769         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6770          encodedCommonNameNoNull,
6771          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6772          "Unexpected value\n");
6773         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6774          sizeof(serialNum), "Unexpected size %d\n",
6775          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6776         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6777          serialNum, sizeof(serialNum)), "Unexpected value\n");
6778         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6779          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6780         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6781          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6782         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6783          info->EncryptedHash.cbData);
6784         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6785          "Unexpected value\n");
6786         LocalFree(buf);
6787     }
6788     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6789      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6790      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6791     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6792     if (buf)
6793     {
6794         info = (CMSG_CMS_SIGNER_INFO *)buf;
6795         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6796          info->dwVersion);
6797         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6798          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6799          info->SignerId.dwIdChoice);
6800         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6801          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6802         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6803          "Unexpected value\n");
6804         LocalFree(buf);
6805     }
6806 }
6807
6808 static BYTE emptyDNSPermittedConstraints[] = {
6809 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6810 static BYTE emptyDNSExcludedConstraints[] = {
6811 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6812 static BYTE DNSExcludedConstraints[] = {
6813 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6814 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6815 static BYTE permittedAndExcludedConstraints[] = {
6816 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6817 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6818 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6819 static BYTE permittedAndExcludedWithMinConstraints[] = {
6820 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6821 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6822 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6823 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6824 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6825 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6826 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6827
6828 static void test_encodeNameConstraints(DWORD dwEncoding)
6829 {
6830     BOOL ret;
6831     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6832     CERT_GENERAL_SUBTREE permitted = { { 0 } };
6833     CERT_GENERAL_SUBTREE excluded = { { 0 } };
6834     LPBYTE buf;
6835     DWORD size;
6836
6837     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6838      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6839     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6840     {
6841         skip("no X509_NAME_CONSTRAINTS encode support\n");
6842         return;
6843     }
6844     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6845     if (ret)
6846     {
6847         ok(size == sizeof(emptySequence), "Unexpected size\n");
6848         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6849         LocalFree(buf);
6850     }
6851     constraints.cPermittedSubtree = 1;
6852     constraints.rgPermittedSubtree = &permitted;
6853     SetLastError(0xdeadbeef);
6854     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6855      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6856     ok(!ret && GetLastError() == E_INVALIDARG,
6857      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6858     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6859     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6860      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6861     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6862     if (ret)
6863     {
6864         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6865         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6866          "Unexpected value\n");
6867         LocalFree(buf);
6868     }
6869     constraints.cPermittedSubtree = 0;
6870     constraints.cExcludedSubtree = 1;
6871     constraints.rgExcludedSubtree = &excluded;
6872     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6873     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6874      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6875     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6876     if (ret)
6877     {
6878         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6879         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6880          "Unexpected value\n");
6881         LocalFree(buf);
6882     }
6883     U(excluded.Base).pwszURL = (LPWSTR)url;
6884     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6885      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6886     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6887     if (ret)
6888     {
6889         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6890         ok(!memcmp(buf, DNSExcludedConstraints, size),
6891          "Unexpected value\n");
6892         LocalFree(buf);
6893     }
6894     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6895     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6896     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6897     constraints.cPermittedSubtree = 1;
6898     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6899      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6900     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6901     if (ret)
6902     {
6903         ok(size == sizeof(permittedAndExcludedConstraints),
6904          "Unexpected size\n");
6905         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6906          "Unexpected value\n");
6907         LocalFree(buf);
6908     }
6909     permitted.dwMinimum = 5;
6910     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6911      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6912     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6913     if (ret)
6914     {
6915         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6916          "Unexpected size\n");
6917         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6918          "Unexpected value\n");
6919         LocalFree(buf);
6920     }
6921     permitted.fMaximum = TRUE;
6922     permitted.dwMaximum = 3;
6923     SetLastError(0xdeadbeef);
6924     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6925      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6926     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6927     if (ret)
6928     {
6929         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6930          "Unexpected size\n");
6931         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6932          "Unexpected value\n");
6933         LocalFree(buf);
6934     }
6935 }
6936
6937 struct EncodedNameConstraints
6938 {
6939     CRYPT_DATA_BLOB            encoded;
6940     CERT_NAME_CONSTRAINTS_INFO constraints;
6941 };
6942
6943 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6944  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6945 static CERT_GENERAL_SUBTREE DNSSubtree = {
6946  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6947 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6948  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6949 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6950  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6951 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6952  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6953
6954 struct EncodedNameConstraints encodedNameConstraints[] = {
6955  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6956  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6957    { 1, &emptyDNSSubtree, 0, NULL } },
6958  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6959    { 0, NULL, 1, &emptyDNSSubtree } },
6960  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6961    { 0, NULL, 1, &DNSSubtree } },
6962  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6963    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6964  { { sizeof(permittedAndExcludedWithMinConstraints),
6965      permittedAndExcludedWithMinConstraints },
6966    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6967  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6968      permittedAndExcludedWithMinMaxConstraints },
6969    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6970 };
6971
6972 static void test_decodeNameConstraints(DWORD dwEncoding)
6973 {
6974     BOOL ret;
6975     DWORD i;
6976     CERT_NAME_CONSTRAINTS_INFO *constraints;
6977
6978     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6979     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6980     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6981     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6982     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6983     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6984     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6985     for (i = 0;
6986      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6987      i++)
6988     {
6989         DWORD size;
6990
6991         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6992          encodedNameConstraints[i].encoded.pbData,
6993          encodedNameConstraints[i].encoded.cbData,
6994          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
6995         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6996         {
6997             skip("no X509_NAME_CONSTRAINTS decode support\n");
6998             return;
6999         }
7000         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7001         if (ret)
7002         {
7003             DWORD j;
7004
7005             if (constraints->cPermittedSubtree !=
7006              encodedNameConstraints[i].constraints.cPermittedSubtree)
7007                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7008                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7009                  constraints->cPermittedSubtree);
7010             if (constraints->cPermittedSubtree ==
7011              encodedNameConstraints[i].constraints.cPermittedSubtree)
7012             {
7013                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7014                 {
7015                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7016                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7017                 }
7018             }
7019             if (constraints->cExcludedSubtree !=
7020              encodedNameConstraints[i].constraints.cExcludedSubtree)
7021                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7022                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7023                  constraints->cExcludedSubtree);
7024             if (constraints->cExcludedSubtree ==
7025              encodedNameConstraints[i].constraints.cExcludedSubtree)
7026             {
7027                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7028                 {
7029                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7030                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7031                 }
7032             }
7033             LocalFree(constraints);
7034         }
7035     }
7036 }
7037
7038 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7039  'n','o','t','i','c','e',0 };
7040 static const BYTE noticeWithDisplayText[] = {
7041  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7042  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7043  0x00,0x69,0x00,0x63,0x00,0x65
7044 };
7045 static char org[] = "Wine";
7046 static int noticeNumbers[] = { 2,3 };
7047 static BYTE noticeWithReference[] = {
7048  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7049  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7050  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7051  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7052 };
7053
7054 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7055 {
7056     BOOL ret;
7057     LPBYTE buf;
7058     DWORD size;
7059     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7060     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7061
7062     memset(&notice, 0, sizeof(notice));
7063     ret = pCryptEncodeObjectEx(dwEncoding,
7064      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7065      NULL, &buf, &size);
7066     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7067     {
7068         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7069         return;
7070     }
7071     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7072     if (ret)
7073     {
7074         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7075         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7076         LocalFree(buf);
7077     }
7078     notice.pszDisplayText = noticeText;
7079     ret = pCryptEncodeObjectEx(dwEncoding,
7080      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7081      NULL, &buf, &size);
7082     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7083     if (ret)
7084     {
7085         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7086         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7087         LocalFree(buf);
7088     }
7089     reference.pszOrganization = org;
7090     reference.cNoticeNumbers = 2;
7091     reference.rgNoticeNumbers = noticeNumbers;
7092     notice.pNoticeReference = &reference;
7093     ret = pCryptEncodeObjectEx(dwEncoding,
7094      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7095      NULL, &buf, &size);
7096     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7097     if (ret)
7098     {
7099         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7100         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7101         LocalFree(buf);
7102     }
7103 }
7104
7105 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7106 {
7107     BOOL ret;
7108     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7109     DWORD size;
7110
7111     ret = pCryptDecodeObjectEx(dwEncoding,
7112      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7113      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7114      &notice, &size);
7115     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7116     {
7117         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7118         return;
7119     }
7120     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7121     if (ret)
7122     {
7123         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7124         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7125         LocalFree(notice);
7126     }
7127     ret = pCryptDecodeObjectEx(dwEncoding,
7128      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7129      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7130      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7131     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7132     if (ret)
7133     {
7134         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7135          "unexpected display text\n");
7136         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7137         LocalFree(notice);
7138     }
7139     ret = pCryptDecodeObjectEx(dwEncoding,
7140      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7141      noticeWithReference, sizeof(noticeWithReference),
7142      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7143     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7144     if (ret)
7145     {
7146         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7147          "unexpected display text\n");
7148         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7149         if (notice->pNoticeReference)
7150         {
7151             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7152              "unexpected organization %s\n",
7153              notice->pNoticeReference->pszOrganization);
7154             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7155              "expected 2 notice numbers, got %d\n",
7156              notice->pNoticeReference->cNoticeNumbers);
7157             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7158              "unexpected notice number %d\n",
7159              notice->pNoticeReference->rgNoticeNumbers[0]);
7160             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7161              "unexpected notice number %d\n",
7162              notice->pNoticeReference->rgNoticeNumbers[1]);
7163         }
7164         LocalFree(notice);
7165     }
7166 }
7167
7168 static char oid_any_policy[] = "2.5.29.32.0";
7169 static const BYTE policiesWithAnyPolicy[] = {
7170  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7171 };
7172 static char oid1[] = "1.2.3";
7173 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7174 static const BYTE twoPolicies[] = {
7175  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7176  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7177  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7178  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7179  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7180  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7181 };
7182
7183 static void test_encodeCertPolicies(DWORD dwEncoding)
7184 {
7185     BOOL ret;
7186     CERT_POLICIES_INFO info;
7187     CERT_POLICY_INFO policy[2];
7188     CERT_POLICY_QUALIFIER_INFO qualifier;
7189     LPBYTE buf;
7190     DWORD size;
7191
7192     memset(&info, 0, sizeof(info));
7193     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7194      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7195     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7196     if (ret)
7197     {
7198         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7199         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7200         LocalFree(buf);
7201     }
7202     memset(policy, 0, sizeof(policy));
7203     info.cPolicyInfo = 1;
7204     info.rgPolicyInfo = policy;
7205     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7206      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7207     ok(!ret && (GetLastError() == E_INVALIDARG ||
7208      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7209      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7210     policy[0].pszPolicyIdentifier = oid_any_policy;
7211     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7212      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7213     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7214     if (ret)
7215     {
7216         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7217         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7218         LocalFree(buf);
7219     }
7220     policy[1].pszPolicyIdentifier = oid1;
7221     memset(&qualifier, 0, sizeof(qualifier));
7222     qualifier.pszPolicyQualifierId = oid_user_notice;
7223     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7224     qualifier.Qualifier.pbData = noticeWithReference;
7225     policy[1].cPolicyQualifier = 1;
7226     policy[1].rgPolicyQualifier = &qualifier;
7227     info.cPolicyInfo = 2;
7228     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7229      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7230     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7231     if (ret)
7232     {
7233         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7234         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7235         LocalFree(buf);
7236     }
7237 }
7238
7239 static void test_decodeCertPolicies(DWORD dwEncoding)
7240 {
7241     BOOL ret;
7242     CERT_POLICIES_INFO *info;
7243     DWORD size;
7244
7245     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7246      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7247      &info, &size);
7248     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7249     if (ret)
7250     {
7251         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7252          info->cPolicyInfo);
7253         LocalFree(info);
7254     }
7255     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7256      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7257      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7258     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7259     if (ret)
7260     {
7261         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7262          info->cPolicyInfo);
7263         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7264          "unexpected policy id %s\n",
7265          info->rgPolicyInfo[0].pszPolicyIdentifier);
7266         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7267          "unexpected policy qualifier count %d\n",
7268          info->rgPolicyInfo[0].cPolicyQualifier);
7269         LocalFree(info);
7270     }
7271     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7272      twoPolicies, sizeof(twoPolicies),
7273      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7274     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7275     if (ret)
7276     {
7277         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7278          info->cPolicyInfo);
7279         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7280          "unexpected policy id %s\n",
7281          info->rgPolicyInfo[0].pszPolicyIdentifier);
7282         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7283          "unexpected policy qualifier count %d\n",
7284          info->rgPolicyInfo[0].cPolicyQualifier);
7285         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7286          "unexpected policy id %s\n",
7287          info->rgPolicyInfo[1].pszPolicyIdentifier);
7288         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7289          "unexpected policy qualifier count %d\n",
7290          info->rgPolicyInfo[1].cPolicyQualifier);
7291         ok(!strcmp(
7292          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7293          oid_user_notice), "unexpected policy qualifier id %s\n",
7294          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7295         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7296          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7297          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7298         ok(!memcmp(
7299          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7300          noticeWithReference, sizeof(noticeWithReference)),
7301          "unexpected qualifier value\n");
7302         LocalFree(info);
7303     }
7304 }
7305
7306 /* Free *pInfo with HeapFree */
7307 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7308 {
7309     BOOL ret;
7310     DWORD size = 0;
7311     HCRYPTKEY key;
7312
7313     /* This crashes
7314     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7315      */
7316     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7317     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7318      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7319     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7320      &size);
7321     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7322      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7323     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7324      NULL, &size);
7325     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7326      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7327     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7328      0, NULL, NULL, &size);
7329     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7330      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7331     /* Test with no key */
7332     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7333      0, NULL, NULL, &size);
7334     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7335      GetLastError());
7336     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7337     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7338     if (ret)
7339     {
7340         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7341          NULL, 0, NULL, NULL, &size);
7342         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7343         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7344         if (*pInfo)
7345         {
7346             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7347              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7348             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7349              GetLastError());
7350             if (ret)
7351             {
7352                 /* By default (we passed NULL as the OID) the OID is
7353                  * szOID_RSA_RSA.
7354                  */
7355                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7356                  "Expected %s, got %s\n", szOID_RSA_RSA,
7357                  (*pInfo)->Algorithm.pszObjId);
7358             }
7359         }
7360     }
7361     CryptDestroyKey(key);
7362 }
7363
7364 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7365  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7366  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7367  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7368  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7369  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7370  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7371  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7372  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7373  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7374  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7375  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7376  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7377  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7378  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7379  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7380  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7381  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7382  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7383  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7384  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7385  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7386  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7387  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7388  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7389
7390 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7391 {
7392     BOOL ret;
7393     HCRYPTKEY key;
7394     PCCERT_CONTEXT context;
7395     DWORD dwSize;
7396     ALG_ID ai;
7397
7398     /* These crash
7399     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7400     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7401     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7402     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7403      NULL);
7404      */
7405     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7406     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7407      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7408     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7409     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7410      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7411     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7412      &key);
7413     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7414      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7415
7416     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7417     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7418      &key);
7419     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7420
7421     dwSize = sizeof(ai);
7422     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7423     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7424     if(ret)
7425     {
7426       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7427       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7428     }
7429
7430     CryptDestroyKey(key);
7431
7432     /* Repeat with forced algorithm */
7433     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7434      &key);
7435     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7436
7437     dwSize = sizeof(ai);
7438     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7439     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7440     if(ret)
7441     {
7442       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7443       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7444     }
7445
7446     CryptDestroyKey(key);
7447
7448     /* Test importing a public key from a certificate context */
7449     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7450      sizeof(expiredCert));
7451     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7452      GetLastError());
7453     if (context)
7454     {
7455         ok(!strcmp(szOID_RSA_RSA,
7456          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7457          "Expected %s, got %s\n", szOID_RSA_RSA,
7458          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7459         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7460          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7461         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7462         CryptDestroyKey(key);
7463         CertFreeCertificateContext(context);
7464     }
7465 }
7466
7467 static const char cspName[] = "WineCryptTemp";
7468
7469 static void testPortPublicKeyInfo(void)
7470 {
7471     HCRYPTPROV csp;
7472     BOOL ret;
7473     PCERT_PUBLIC_KEY_INFO info = NULL;
7474
7475     /* Just in case a previous run failed, delete this thing */
7476     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7477      CRYPT_DELETEKEYSET);
7478     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7479      CRYPT_NEWKEYSET);
7480
7481     testExportPublicKey(csp, &info);
7482     testImportPublicKey(csp, info);
7483
7484     HeapFree(GetProcessHeap(), 0, info);
7485     CryptReleaseContext(csp, 0);
7486     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7487      CRYPT_DELETEKEYSET);
7488 }
7489
7490 START_TEST(encode)
7491 {
7492     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7493      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7494     HMODULE hCrypt32;
7495     DWORD i;
7496
7497     hCrypt32 = GetModuleHandleA("crypt32.dll");
7498     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7499     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7500     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7501     {
7502         skip("CryptDecodeObjectEx() is not available\n");
7503         return;
7504     }
7505
7506     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7507     {
7508         test_encodeInt(encodings[i]);
7509         test_decodeInt(encodings[i]);
7510         test_encodeEnumerated(encodings[i]);
7511         test_decodeEnumerated(encodings[i]);
7512         test_encodeFiletime(encodings[i]);
7513         test_decodeFiletime(encodings[i]);
7514         test_encodeName(encodings[i]);
7515         test_decodeName(encodings[i]);
7516         test_encodeUnicodeName(encodings[i]);
7517         test_decodeUnicodeName(encodings[i]);
7518         test_encodeNameValue(encodings[i]);
7519         test_decodeNameValue(encodings[i]);
7520         test_encodeUnicodeNameValue(encodings[i]);
7521         test_decodeUnicodeNameValue(encodings[i]);
7522         test_encodeAltName(encodings[i]);
7523         test_decodeAltName(encodings[i]);
7524         test_encodeOctets(encodings[i]);
7525         test_decodeOctets(encodings[i]);
7526         test_encodeBits(encodings[i]);
7527         test_decodeBits(encodings[i]);
7528         test_encodeBasicConstraints(encodings[i]);
7529         test_decodeBasicConstraints(encodings[i]);
7530         test_encodeRsaPublicKey(encodings[i]);
7531         test_decodeRsaPublicKey(encodings[i]);
7532         test_encodeSequenceOfAny(encodings[i]);
7533         test_decodeSequenceOfAny(encodings[i]);
7534         test_encodeExtensions(encodings[i]);
7535         test_decodeExtensions(encodings[i]);
7536         test_encodePublicKeyInfo(encodings[i]);
7537         test_decodePublicKeyInfo(encodings[i]);
7538         test_encodeCertToBeSigned(encodings[i]);
7539         test_decodeCertToBeSigned(encodings[i]);
7540         test_encodeCert(encodings[i]);
7541         test_decodeCert(encodings[i]);
7542         test_encodeCRLDistPoints(encodings[i]);
7543         test_decodeCRLDistPoints(encodings[i]);
7544         test_encodeCRLIssuingDistPoint(encodings[i]);
7545         test_decodeCRLIssuingDistPoint(encodings[i]);
7546         test_encodeCRLToBeSigned(encodings[i]);
7547         test_decodeCRLToBeSigned(encodings[i]);
7548         test_encodeEnhancedKeyUsage(encodings[i]);
7549         test_decodeEnhancedKeyUsage(encodings[i]);
7550         test_encodeAuthorityKeyId(encodings[i]);
7551         test_decodeAuthorityKeyId(encodings[i]);
7552         test_encodeAuthorityKeyId2(encodings[i]);
7553         test_decodeAuthorityKeyId2(encodings[i]);
7554         test_encodeAuthorityInfoAccess(encodings[i]);
7555         test_decodeAuthorityInfoAccess(encodings[i]);
7556         test_encodeCTL(encodings[i]);
7557         test_decodeCTL(encodings[i]);
7558         test_encodePKCSContentInfo(encodings[i]);
7559         test_decodePKCSContentInfo(encodings[i]);
7560         test_encodePKCSAttribute(encodings[i]);
7561         test_decodePKCSAttribute(encodings[i]);
7562         test_encodePKCSAttributes(encodings[i]);
7563         test_decodePKCSAttributes(encodings[i]);
7564         test_encodePKCSSMimeCapabilities(encodings[i]);
7565         test_decodePKCSSMimeCapabilities(encodings[i]);
7566         test_encodePKCSSignerInfo(encodings[i]);
7567         test_decodePKCSSignerInfo(encodings[i]);
7568         test_encodeCMSSignerInfo(encodings[i]);
7569         test_decodeCMSSignerInfo(encodings[i]);
7570         test_encodeNameConstraints(encodings[i]);
7571         test_decodeNameConstraints(encodings[i]);
7572         test_encodePolicyQualifierUserNotice(encodings[i]);
7573         test_decodePolicyQualifierUserNotice(encodings[i]);
7574         test_encodeCertPolicies(encodings[i]);
7575         test_decodeCertPolicies(encodings[i]);
7576     }
7577     testPortPublicKeyInfo();
7578 }