include: Add asynot.idl.
[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 static char embedded_null[] = "foo\0com";
1268 static BYTE ia5EmbeddedNull[] = {
1269  0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d };
1270
1271 static struct EncodedNameValue nameValues[] = {
1272  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1273      octetCommonNameValue, sizeof(octetCommonNameValue) },
1274  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1275      numericCommonNameValue, sizeof(numericCommonNameValue) },
1276  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1277      printableCommonNameValue, sizeof(printableCommonNameValue) },
1278  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1279      t61CommonNameValue, sizeof(t61CommonNameValue) },
1280  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1281      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1282  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1283      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1284  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1285      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1286  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1287      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1288  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1289      generalCommonNameValue, sizeof(generalCommonNameValue) },
1290  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1291      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1292  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1293      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1294  /* The following tests succeed under Windows, but really should fail,
1295   * they contain characters that are illegal for the encoding.  I'm
1296   * including them to justify my lazy encoding.
1297   */
1298  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1299      sizeof(bin42) },
1300  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1301      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1302  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1303      bin44, sizeof(bin44) },
1304 };
1305 /* This is kept separate, because the decoding doesn't return to the original
1306  * value.
1307  */
1308 static struct EncodedNameValue embeddedNullNameValue = {
1309  { CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } },
1310    ia5EmbeddedNull, sizeof(ia5EmbeddedNull) };
1311
1312 static void test_encodeNameValue(DWORD dwEncoding)
1313 {
1314     BYTE *buf = NULL;
1315     DWORD size = 0, i;
1316     BOOL ret;
1317     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1318
1319     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1320     value.Value.pbData = printableCommonNameValue;
1321     value.Value.cbData = sizeof(printableCommonNameValue);
1322     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1323      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1324     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1325     if (buf)
1326     {
1327         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1328          size);
1329         ok(!memcmp(buf, printableCommonNameValue, size),
1330          "Unexpected encoding\n");
1331         LocalFree(buf);
1332     }
1333     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1334     {
1335         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1336          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1337         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1338          "Type %d: CryptEncodeObjectEx failed: %08x\n",
1339          nameValues[i].value.dwValueType, GetLastError());
1340         if (ret)
1341         {
1342             ok(size == nameValues[i].encodedSize,
1343              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1344             ok(!memcmp(buf, nameValues[i].encoded, size),
1345              "Got unexpected encoding\n");
1346             LocalFree(buf);
1347         }
1348     }
1349     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1350      &embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1351     ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1352      "Type %d: CryptEncodeObjectEx failed: %08x\n",
1353      embeddedNullNameValue.value.dwValueType, GetLastError());
1354     if (ret)
1355     {
1356         ok(size == embeddedNullNameValue.encodedSize,
1357          "Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size);
1358         ok(!memcmp(buf, embeddedNullNameValue.encoded, size),
1359          "Got unexpected encoding\n");
1360         LocalFree(buf);
1361     }
1362 }
1363
1364 static void test_decodeNameValue(DWORD dwEncoding)
1365 {
1366     int i;
1367     BYTE *buf = NULL;
1368     DWORD bufSize = 0;
1369     BOOL ret;
1370
1371     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1372     {
1373         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1374          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1375          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1376          &buf, &bufSize);
1377         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1378          nameValues[i].value.dwValueType, GetLastError());
1379         if (ret)
1380         {
1381             compareNameValues(&nameValues[i].value,
1382              (const CERT_NAME_VALUE *)buf);
1383             LocalFree(buf);
1384         }
1385     }
1386     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1387      embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize,
1388      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1389      &buf, &bufSize);
1390     ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1391      embeddedNullNameValue.value.dwValueType, GetLastError());
1392     if (ret)
1393     {
1394         CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB,
1395          { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1396         CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING,
1397          { sizeof(embedded_null) - 1, (BYTE *)embedded_null } };
1398         const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf,
1399          *expected = NULL;
1400
1401         /* Some Windows versions decode name values with embedded NULLs,
1402          * others leave them encoded, even with the same version of crypt32.
1403          * Accept either.
1404          */
1405         ok(got->dwValueType == CERT_RDN_ENCODED_BLOB ||
1406          got->dwValueType == CERT_RDN_IA5_STRING,
1407          "Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n",
1408          got->dwValueType);
1409         if (got->dwValueType == CERT_RDN_ENCODED_BLOB)
1410             expected = &rdnEncodedValue;
1411         else if (got->dwValueType == CERT_RDN_IA5_STRING)
1412             expected = &embeddedNullValue;
1413         if (expected)
1414         {
1415             ok(got->Value.cbData == expected->Value.cbData,
1416              "String type %d: unexpected data size, got %d, expected %d\n",
1417              got->dwValueType, got->Value.cbData, expected->Value.cbData);
1418             if (got->Value.cbData && got->Value.pbData)
1419                 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1420                  min(got->Value.cbData, expected->Value.cbData)),
1421                  "String type %d: unexpected value\n", expected->dwValueType);
1422         }
1423         LocalFree(buf);
1424     }
1425 }
1426
1427 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1428 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1429 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1430  'h','q','.','o','r','g',0 };
1431 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1432  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1433  0x6f, 0x72, 0x67 };
1434 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1435  0x575b, 0 };
1436 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1437 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1438  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1439 static const BYTE localhost[] = { 127, 0, 0, 1 };
1440 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1441  0x01 };
1442 static const unsigned char encodedCommonName[] = {
1443     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1444 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1445 static const BYTE encodedDirectoryName[] = {
1446 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1447 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1448
1449 static void test_encodeAltName(DWORD dwEncoding)
1450 {
1451     CERT_ALT_NAME_INFO info = { 0 };
1452     CERT_ALT_NAME_ENTRY entry = { 0 };
1453     BYTE *buf = NULL;
1454     DWORD size = 0;
1455     BOOL ret;
1456     char oid[] = "1.2.3";
1457
1458     /* Test with empty info */
1459     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1460      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1461     if (buf)
1462     {
1463         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1464         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1465         LocalFree(buf);
1466     }
1467     /* Test with an empty entry */
1468     info.cAltEntry = 1;
1469     info.rgAltEntry = &entry;
1470     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1471      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1472     ok(!ret && GetLastError() == E_INVALIDARG,
1473      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1474     /* Test with an empty pointer */
1475     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1476     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1477      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1478     if (buf)
1479     {
1480         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1481         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1482         LocalFree(buf);
1483     }
1484     /* Test with a real URL */
1485     U(entry).pwszURL = (LPWSTR)url;
1486     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1487      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1488     if (buf)
1489     {
1490         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1491         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1492         LocalFree(buf);
1493     }
1494     /* Now with the URL containing an invalid IA5 char */
1495     U(entry).pwszURL = (LPWSTR)nihongoURL;
1496     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1497      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1498     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1499      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1500     /* The first invalid character is at index 7 */
1501     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1502      "Expected invalid char at index 7, got %d\n",
1503      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1504     /* Now with the URL missing a scheme */
1505     U(entry).pwszURL = (LPWSTR)dnsName;
1506     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1507      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1508     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1509     if (buf)
1510     {
1511         /* This succeeds, but it shouldn't, so don't worry about conforming */
1512         LocalFree(buf);
1513     }
1514     /* Now with a DNS name */
1515     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1516     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1517      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1518     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1519     if (buf)
1520     {
1521         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1522         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1523         LocalFree(buf);
1524     }
1525     /* Test with an IP address */
1526     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1527     U(entry).IPAddress.cbData = sizeof(localhost);
1528     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1529     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1530      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1531     if (buf)
1532     {
1533         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1534         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1535         LocalFree(buf);
1536     }
1537     /* Test with OID */
1538     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1539     U(entry).pszRegisteredID = oid;
1540     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1541      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1542     if (buf)
1543     {
1544         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1545         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1546         LocalFree(buf);
1547     }
1548     /* Test with directory name */
1549     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1550     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1551     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1552     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1553      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1554     if (buf)
1555     {
1556         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1557         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1558         LocalFree(buf);
1559     }
1560 }
1561
1562 static void test_decodeAltName(DWORD dwEncoding)
1563 {
1564     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1565      0x00, 0x00, 0x01 };
1566     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1567      0x01 };
1568     static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1569      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1570     static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1571      0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1572     static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1573      0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1574     BOOL ret;
1575     BYTE *buf = NULL;
1576     DWORD bufSize = 0;
1577     CERT_ALT_NAME_INFO *info;
1578
1579     /* Test some bogus ones first */
1580     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1581      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1582      NULL, &buf, &bufSize);
1583     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1584      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1585      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1586      GetLastError());
1587     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1588      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1589      &bufSize);
1590     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1591      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1592      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1593      GetLastError());
1594     /* Now expected cases */
1595     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1596      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1597     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1598     if (buf)
1599     {
1600         info = (CERT_ALT_NAME_INFO *)buf;
1601
1602         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1603          info->cAltEntry);
1604         LocalFree(buf);
1605     }
1606     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1607      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1608     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1609     if (buf)
1610     {
1611         info = (CERT_ALT_NAME_INFO *)buf;
1612
1613         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1614          info->cAltEntry);
1615         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1616          "Expected CERT_ALT_NAME_URL, got %d\n",
1617          info->rgAltEntry[0].dwAltNameChoice);
1618         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1619          "Expected empty URL\n");
1620         LocalFree(buf);
1621     }
1622     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1623      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1624     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1625     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1626      encodedURL[1] + 2, 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_URL,
1635          "Expected CERT_ALT_NAME_URL, got %d\n",
1636          info->rgAltEntry[0].dwAltNameChoice);
1637         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1638         LocalFree(buf);
1639     }
1640     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1641      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1642     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1643     if (buf)
1644     {
1645         info = (CERT_ALT_NAME_INFO *)buf;
1646
1647         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1648          info->cAltEntry);
1649         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1650          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1651          info->rgAltEntry[0].dwAltNameChoice);
1652         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1653          "Unexpected DNS name\n");
1654         LocalFree(buf);
1655     }
1656     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1657      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1658     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1659     if (buf)
1660     {
1661         info = (CERT_ALT_NAME_INFO *)buf;
1662
1663         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1664          info->cAltEntry);
1665         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1666          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1667          info->rgAltEntry[0].dwAltNameChoice);
1668         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1669          "Unexpected IP address length %d\n",
1670           U(info->rgAltEntry[0]).IPAddress.cbData);
1671         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1672          sizeof(localhost)), "Unexpected IP address value\n");
1673         LocalFree(buf);
1674     }
1675     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1676      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1677     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1678     if (buf)
1679     {
1680         info = (CERT_ALT_NAME_INFO *)buf;
1681
1682         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1683          info->cAltEntry);
1684         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1685          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1686          info->rgAltEntry[0].dwAltNameChoice);
1687         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1688            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1689         LocalFree(buf);
1690     }
1691     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1692      encodedDirectoryName, sizeof(encodedDirectoryName),
1693      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1694     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1695     if (buf)
1696     {
1697         info = (CERT_ALT_NAME_INFO *)buf;
1698
1699         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1700          info->cAltEntry);
1701         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1702          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1703          info->rgAltEntry[0].dwAltNameChoice);
1704         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1705          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1706           U(info->rgAltEntry[0]).DirectoryName.cbData);
1707         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1708          encodedCommonName, sizeof(encodedCommonName)),
1709          "Unexpected directory name value\n");
1710         LocalFree(buf);
1711     }
1712     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1713      dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1714      NULL, &buf, &bufSize);
1715     /* Fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned about the
1716      * particular failure, just that it doesn't decode.
1717      */
1718     ok(!ret, "expected failure\n");
1719     /* An embedded bell character is allowed, however. */
1720     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1721      dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1722      NULL, &buf, &bufSize);
1723     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1724     if (ret)
1725     {
1726         info = (CERT_ALT_NAME_INFO *)buf;
1727
1728         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1729          info->cAltEntry);
1730         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1731          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1732          info->rgAltEntry[0].dwAltNameChoice);
1733         LocalFree(buf);
1734     }
1735     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1736      url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1737      NULL, &buf, &bufSize);
1738     /* Again, fails on WinXP with CRYPT_E_ASN1_RULE.  I'm not too concerned
1739      * about the particular failure, just that it doesn't decode.
1740      */
1741     ok(!ret, "expected failure\n");
1742 }
1743
1744 struct UnicodeExpectedError
1745 {
1746     DWORD   valueType;
1747     LPCWSTR str;
1748     DWORD   errorIndex;
1749     DWORD   error;
1750 };
1751
1752 static const WCHAR oneW[] = { '1',0 };
1753 static const WCHAR aW[] = { 'a',0 };
1754 static const WCHAR quoteW[] = { '"', 0 };
1755
1756 static struct UnicodeExpectedError unicodeErrors[] = {
1757  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1758  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1759  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1760  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1761  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1762  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1763 };
1764
1765 struct UnicodeExpectedResult
1766 {
1767     DWORD           valueType;
1768     LPCWSTR         str;
1769     CRYPT_DATA_BLOB encoded;
1770 };
1771
1772 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1773 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1774 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1775 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1776 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1777 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1778 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1779 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1780 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1781 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1782 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1783 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1784  0x5b };
1785 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1786  0x6f,0x5b };
1787 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1788  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1789 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1790  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1791
1792 static struct UnicodeExpectedResult unicodeResults[] = {
1793  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1794  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1795  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1796  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1797  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1798  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1799  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1800  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1801  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1802  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1803  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1804  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1805  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1806 };
1807
1808 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1809  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1810  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1811 };
1812
1813 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1814 {
1815     BYTE *buf = NULL;
1816     DWORD size = 0, i;
1817     BOOL ret;
1818     CERT_NAME_VALUE value;
1819
1820     if (0)
1821     {
1822         /* Crashes on win9x */
1823         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1824          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1825         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1826          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1827     }
1828     /* Have to have a string of some sort */
1829     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1830     value.Value.pbData = NULL;
1831     value.Value.cbData = 0;
1832     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1833      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1834     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1835      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1836     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1837     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1838      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1839     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1840      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1841     value.dwValueType = CERT_RDN_ANY_TYPE;
1842     value.Value.pbData = (LPBYTE)oneW;
1843     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1844      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1845     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1846      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1847     value.Value.cbData = sizeof(oneW);
1848     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1849      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1850     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1851      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1852     /* An encoded string with specified length isn't good enough either */
1853     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1854     value.Value.pbData = oneUniversal;
1855     value.Value.cbData = sizeof(oneUniversal);
1856     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1857      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1858     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1859      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1860     /* More failure checking */
1861     value.Value.cbData = 0;
1862     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1863     {
1864         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1865         value.dwValueType = unicodeErrors[i].valueType;
1866         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1867          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1868         ok(!ret && GetLastError() == unicodeErrors[i].error,
1869          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1870          unicodeErrors[i].error, GetLastError());
1871         ok(size == unicodeErrors[i].errorIndex,
1872          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1873          size);
1874     }
1875     /* cbData can be zero if the string is NULL-terminated */
1876     value.Value.cbData = 0;
1877     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1878     {
1879         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1880         value.dwValueType = unicodeResults[i].valueType;
1881         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1882          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1883         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1884          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1885         if (buf)
1886         {
1887             ok(size == unicodeResults[i].encoded.cbData,
1888              "Value type %d: expected size %d, got %d\n",
1889              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1890             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1891              "Value type %d: unexpected value\n", value.dwValueType);
1892             LocalFree(buf);
1893         }
1894     }
1895     /* These "encode," but they do so by truncating each unicode character
1896      * rather than properly encoding it.  Kept separate from the proper results,
1897      * because the encoded forms won't decode to their original strings.
1898      */
1899     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1900     {
1901         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1902         value.dwValueType = unicodeWeirdness[i].valueType;
1903         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1904          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1905         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1906         if (buf)
1907         {
1908             ok(size == unicodeWeirdness[i].encoded.cbData,
1909              "Value type %d: expected size %d, got %d\n",
1910              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1911             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1912              "Value type %d: unexpected value\n", value.dwValueType);
1913             LocalFree(buf);
1914         }
1915     }
1916 }
1917
1918 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1919 {
1920     if (n <= 0) return 0;
1921     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1922     return *str1 - *str2;
1923 }
1924
1925 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1926 {
1927     DWORD i;
1928
1929     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1930     {
1931         BYTE *buf = NULL;
1932         BOOL ret;
1933         DWORD size = 0;
1934
1935         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1936          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1937          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1938         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1939          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1940         if (ret && buf)
1941         {
1942             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1943
1944             ok(value->dwValueType == unicodeResults[i].valueType,
1945              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1946              value->dwValueType);
1947             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1948              value->Value.cbData / sizeof(WCHAR)),
1949              "Unexpected decoded value for index %d (value type %d)\n", i,
1950              unicodeResults[i].valueType);
1951             LocalFree(buf);
1952         }
1953     }
1954 }
1955
1956 struct encodedOctets
1957 {
1958     const BYTE *val;
1959     const BYTE *encoded;
1960 };
1961
1962 static const unsigned char bin46[] = { 'h','i',0 };
1963 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1964 static const unsigned char bin48[] = {
1965      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1966 static const unsigned char bin49[] = {
1967      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1968 static const unsigned char bin50[] = { 0 };
1969 static const unsigned char bin51[] = { 0x04,0x00,0 };
1970
1971 static const struct encodedOctets octets[] = {
1972     { bin46, bin47 },
1973     { bin48, bin49 },
1974     { bin50, bin51 },
1975 };
1976
1977 static void test_encodeOctets(DWORD dwEncoding)
1978 {
1979     CRYPT_DATA_BLOB blob;
1980     DWORD i;
1981
1982     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1983     {
1984         BYTE *buf = NULL;
1985         BOOL ret;
1986         DWORD bufSize = 0;
1987
1988         blob.cbData = strlen((const char*)octets[i].val);
1989         blob.pbData = (BYTE*)octets[i].val;
1990         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1991          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1992         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1993         if (buf)
1994         {
1995             ok(buf[0] == 4,
1996              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1997             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1998              buf[1], octets[i].encoded[1]);
1999             ok(!memcmp(buf + 1, octets[i].encoded + 1,
2000              octets[i].encoded[1] + 1), "Got unexpected value\n");
2001             LocalFree(buf);
2002         }
2003     }
2004 }
2005
2006 static void test_decodeOctets(DWORD dwEncoding)
2007 {
2008     DWORD i;
2009
2010     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
2011     {
2012         BYTE *buf = NULL;
2013         BOOL ret;
2014         DWORD bufSize = 0;
2015
2016         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
2017          octets[i].encoded, octets[i].encoded[1] + 2,
2018          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2019         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2020         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
2021          "Expected size >= %d, got %d\n",
2022            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
2023         ok(buf != NULL, "Expected allocated buffer\n");
2024         if (buf)
2025         {
2026             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2027
2028             if (blob->cbData)
2029                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
2030                  "Unexpected value\n");
2031             LocalFree(buf);
2032         }
2033     }
2034 }
2035
2036 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2037
2038 struct encodedBits
2039 {
2040     DWORD cUnusedBits;
2041     const BYTE *encoded;
2042     DWORD cbDecoded;
2043     const BYTE *decoded;
2044 };
2045
2046 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2047 static const unsigned char bin53[] = { 0xff,0xff };
2048 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2049 static const unsigned char bin55[] = { 0xff,0xfe };
2050 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2051 static const unsigned char bin57[] = { 0xfe };
2052 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
2053
2054 static const struct encodedBits bits[] = {
2055     /* normal test cases */
2056     { 0, bin52, 2, bin53 },
2057     { 1, bin54, 2, bin55 },
2058     /* strange test case, showing cUnusedBits >= 8 is allowed */
2059     { 9, bin56, 1, bin57 },
2060 };
2061
2062 static void test_encodeBits(DWORD dwEncoding)
2063 {
2064     DWORD i;
2065
2066     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2067     {
2068         CRYPT_BIT_BLOB blob;
2069         BOOL ret;
2070         BYTE *buf = NULL;
2071         DWORD bufSize = 0;
2072
2073         blob.cbData = sizeof(bytesToEncode);
2074         blob.pbData = (BYTE *)bytesToEncode;
2075         blob.cUnusedBits = bits[i].cUnusedBits;
2076         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2077          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2078         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2079         if (buf)
2080         {
2081             ok(bufSize == bits[i].encoded[1] + 2,
2082              "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2083              bits[i].encoded[1] + 2);
2084             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2085              "%d: Unexpected value\n", i);
2086             LocalFree(buf);
2087         }
2088     }
2089 }
2090
2091 static void test_decodeBits(DWORD dwEncoding)
2092 {
2093     static const BYTE ber[] = "\x03\x02\x01\xff";
2094     static const BYTE berDecoded = 0xfe;
2095     DWORD i;
2096     BOOL ret;
2097     BYTE *buf = NULL;
2098     DWORD bufSize = 0;
2099
2100     /* normal cases */
2101     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2102     {
2103         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2104          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2105          &bufSize);
2106         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2107         if (buf)
2108         {
2109             CRYPT_BIT_BLOB *blob;
2110
2111             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2112                "Got unexpected size %d\n", bufSize);
2113             blob = (CRYPT_BIT_BLOB *)buf;
2114             ok(blob->cbData == bits[i].cbDecoded,
2115              "Got unexpected length %d, expected %d\n", blob->cbData,
2116              bits[i].cbDecoded);
2117             if (blob->cbData && bits[i].cbDecoded)
2118                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2119                  "Unexpected value\n");
2120             LocalFree(buf);
2121         }
2122     }
2123     /* special case: check that something that's valid in BER but not in DER
2124      * decodes successfully
2125      */
2126     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2127      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2128     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2129     if (buf)
2130     {
2131         CRYPT_BIT_BLOB *blob;
2132
2133         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2134            "Got unexpected size %d\n", bufSize);
2135         blob = (CRYPT_BIT_BLOB *)buf;
2136         ok(blob->cbData == sizeof(berDecoded),
2137            "Got unexpected length %d\n", blob->cbData);
2138         if (blob->cbData)
2139             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2140         LocalFree(buf);
2141     }
2142 }
2143
2144 struct Constraints2
2145 {
2146     CERT_BASIC_CONSTRAINTS2_INFO info;
2147     const BYTE *encoded;
2148 };
2149
2150 static const unsigned char bin59[] = { 0x30,0x00 };
2151 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2152 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2153 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2154 static const struct Constraints2 constraints2[] = {
2155  /* empty constraints */
2156  { { FALSE, FALSE, 0}, bin59 },
2157  /* can be a CA */
2158  { { TRUE,  FALSE, 0}, bin60 },
2159  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2160   * but that's not the case
2161   */
2162  { { FALSE, TRUE,  0}, bin61 },
2163  /* can be a CA and has path length constraints set */
2164  { { TRUE,  TRUE,  1}, bin62 },
2165 };
2166
2167 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2168 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2169  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2170  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2171  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2172 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2173  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2174  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2175  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2176  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2177
2178 static void test_encodeBasicConstraints(DWORD dwEncoding)
2179 {
2180     DWORD i, bufSize = 0;
2181     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2182     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2183      (LPBYTE)encodedDomainName };
2184     BOOL ret;
2185     BYTE *buf = NULL;
2186
2187     /* First test with the simpler info2 */
2188     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2189     {
2190         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2191          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2192          &bufSize);
2193         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2194         if (buf)
2195         {
2196             ok(bufSize == constraints2[i].encoded[1] + 2,
2197              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2198              bufSize);
2199             ok(!memcmp(buf, constraints2[i].encoded,
2200              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2201             LocalFree(buf);
2202         }
2203     }
2204     /* Now test with more complex basic constraints */
2205     info.SubjectType.cbData = 0;
2206     info.fPathLenConstraint = FALSE;
2207     info.cSubtreesConstraint = 0;
2208     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2209      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2210     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2211      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2212     if (buf)
2213     {
2214         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2215         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2216          "Unexpected value\n");
2217         LocalFree(buf);
2218     }
2219     /* None of the certs I examined had any subtree constraint, but I test one
2220      * anyway just in case.
2221      */
2222     info.cSubtreesConstraint = 1;
2223     info.rgSubtreesConstraint = &nameBlob;
2224     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2225      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2226     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2227      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2228     if (buf)
2229     {
2230         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2231         ok(!memcmp(buf, constraintWithDomainName,
2232          sizeof(constraintWithDomainName)), "Unexpected value\n");
2233         LocalFree(buf);
2234     }
2235     /* FIXME: test encoding with subject type. */
2236 }
2237
2238 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2239
2240 static void test_decodeBasicConstraints(DWORD dwEncoding)
2241 {
2242     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2243      0xff };
2244     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2245     DWORD i;
2246     BOOL ret;
2247     BYTE *buf = NULL;
2248     DWORD bufSize = 0;
2249
2250     /* First test with simpler info2 */
2251     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2252     {
2253         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2254          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2255          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2256         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2257          GetLastError());
2258         if (buf)
2259         {
2260             CERT_BASIC_CONSTRAINTS2_INFO *info =
2261              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2262
2263             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2264              "Unexpected value for item %d\n", i);
2265             LocalFree(buf);
2266         }
2267     }
2268     /* Check with the order of encoded elements inverted */
2269     buf = (PBYTE)1;
2270     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2271      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2272      &bufSize);
2273     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2274      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2275      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2276      GetLastError());
2277     ok(!buf, "Expected buf to be set to NULL\n");
2278     /* Check with a non-DER bool */
2279     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2280      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2281      &buf, &bufSize);
2282     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2283     if (buf)
2284     {
2285         CERT_BASIC_CONSTRAINTS2_INFO *info =
2286          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2287
2288         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2289         LocalFree(buf);
2290     }
2291     /* Check with a non-basic constraints value */
2292     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2293      encodedCommonName, encodedCommonName[1] + 2,
2294      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2295     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2296      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2297      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2298      GetLastError());
2299     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2300     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2301      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2302      &buf, &bufSize);
2303     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2304     if (buf)
2305     {
2306         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2307
2308         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2309         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2310         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2311         LocalFree(buf);
2312     }
2313     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2314      constraintWithDomainName, sizeof(constraintWithDomainName),
2315      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2316     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2317     if (buf)
2318     {
2319         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2320
2321         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2322         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2323         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2324         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2325         {
2326             ok(info->rgSubtreesConstraint[0].cbData ==
2327              sizeof(encodedDomainName), "Wrong size %d\n",
2328              info->rgSubtreesConstraint[0].cbData);
2329             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2330              sizeof(encodedDomainName)), "Unexpected value\n");
2331         }
2332         LocalFree(buf);
2333     }
2334 }
2335
2336 /* These are terrible public keys of course, I'm just testing encoding */
2337 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2338 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2339 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2340 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2341 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2342 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2343 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2344 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2345
2346 struct EncodedRSAPubKey
2347 {
2348     const BYTE *modulus;
2349     size_t modulusLen;
2350     const BYTE *encoded;
2351     size_t decodedModulusLen;
2352 };
2353
2354 struct EncodedRSAPubKey rsaPubKeys[] = {
2355     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2356     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2357     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2358     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2359 };
2360
2361 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2362 {
2363     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2364     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2365     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2366     BOOL ret;
2367     BYTE *buf = NULL;
2368     DWORD bufSize = 0, i;
2369
2370     /* Try with a bogus blob type */
2371     hdr->bType = 2;
2372     hdr->bVersion = CUR_BLOB_VERSION;
2373     hdr->reserved = 0;
2374     hdr->aiKeyAlg = CALG_RSA_KEYX;
2375     rsaPubKey->magic = 0x31415352;
2376     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2377     rsaPubKey->pubexp = 65537;
2378     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2379      sizeof(modulus1));
2380
2381     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2382      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2383     ok(!ret && GetLastError() == E_INVALIDARG,
2384      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2385     /* Now with a bogus reserved field */
2386     hdr->bType = PUBLICKEYBLOB;
2387     hdr->reserved = 1;
2388     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2389      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2390     if (buf)
2391     {
2392         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2393          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2394         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2395         LocalFree(buf);
2396     }
2397     /* Now with a bogus blob version */
2398     hdr->reserved = 0;
2399     hdr->bVersion = 0;
2400     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2401      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2402     if (buf)
2403     {
2404         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2405          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2406         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2407         LocalFree(buf);
2408     }
2409     /* And with a bogus alg ID */
2410     hdr->bVersion = CUR_BLOB_VERSION;
2411     hdr->aiKeyAlg = CALG_DES;
2412     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2413      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2414     if (buf)
2415     {
2416         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2417          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2418         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2419         LocalFree(buf);
2420     }
2421     /* Check a couple of RSA-related OIDs */
2422     hdr->aiKeyAlg = CALG_RSA_KEYX;
2423     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2424      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2425     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2426      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2427     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2428      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2429     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2430      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2431     /* Finally, all valid */
2432     hdr->aiKeyAlg = CALG_RSA_KEYX;
2433     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2434     {
2435         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2436          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2437         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2438          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2439         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2440         if (buf)
2441         {
2442             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2443              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2444              bufSize);
2445             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2446              "Unexpected value\n");
2447             LocalFree(buf);
2448         }
2449     }
2450 }
2451
2452 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2453 {
2454     DWORD i;
2455     LPBYTE buf = NULL;
2456     DWORD bufSize = 0;
2457     BOOL ret;
2458
2459     /* Try with a bad length */
2460     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2461      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2462      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2463     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2464      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2465      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2466      GetLastError());
2467     /* Try with a couple of RSA-related OIDs */
2468     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2469      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2470      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2471     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2472      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2473     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2474      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2475      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2476     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2477      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2478     /* Now try success cases */
2479     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2480     {
2481         bufSize = 0;
2482         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2483          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2484          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2485         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2486         if (buf)
2487         {
2488             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2489             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2490
2491             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2492              rsaPubKeys[i].decodedModulusLen,
2493              "Wrong size %d\n", bufSize);
2494             ok(hdr->bType == PUBLICKEYBLOB,
2495              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2496              hdr->bType);
2497             ok(hdr->bVersion == CUR_BLOB_VERSION,
2498              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2499              CUR_BLOB_VERSION, hdr->bVersion);
2500             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2501              hdr->reserved);
2502             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2503              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2504             ok(rsaPubKey->magic == 0x31415352,
2505              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2506             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2507              "Wrong bit len %d\n", rsaPubKey->bitlen);
2508             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2509              rsaPubKey->pubexp);
2510             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2511              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2512              "Unexpected modulus\n");
2513             LocalFree(buf);
2514         }
2515     }
2516 }
2517
2518 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2519  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2520  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2521
2522 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2523  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2524  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2525  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2526
2527 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2528 {
2529     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2530     CRYPT_SEQUENCE_OF_ANY seq;
2531     DWORD i;
2532     BOOL ret;
2533     BYTE *buf = NULL;
2534     DWORD bufSize = 0;
2535
2536     /* Encode a homogeneous sequence */
2537     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2538     {
2539         blobs[i].cbData = ints[i].encoded[1] + 2;
2540         blobs[i].pbData = (BYTE *)ints[i].encoded;
2541     }
2542     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2543     seq.rgValue = blobs;
2544
2545     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2546      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2547     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2548     if (buf)
2549     {
2550         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2551         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2552         LocalFree(buf);
2553     }
2554     /* Change the type of the first element in the sequence, and give it
2555      * another go
2556      */
2557     blobs[0].cbData = times[0].encodedTime[1] + 2;
2558     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2559     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2560      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2561     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2562     if (buf)
2563     {
2564         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2565         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2566          "Unexpected value\n");
2567         LocalFree(buf);
2568     }
2569 }
2570
2571 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2572 {
2573     BOOL ret;
2574     BYTE *buf = NULL;
2575     DWORD bufSize = 0;
2576
2577     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2578      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2579     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2580     if (buf)
2581     {
2582         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2583         DWORD i;
2584
2585         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2586          "Wrong elements %d\n", seq->cValue);
2587         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2588         {
2589             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2590              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2591              seq->rgValue[i].cbData);
2592             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2593              ints[i].encoded[1] + 2), "Unexpected value\n");
2594         }
2595         LocalFree(buf);
2596     }
2597     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2598      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2599      &bufSize);
2600     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2601     if (buf)
2602     {
2603         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2604
2605         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2606          "Wrong elements %d\n", seq->cValue);
2607         /* Just check the first element since it's all that changed */
2608         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2609          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2610          seq->rgValue[0].cbData);
2611         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2612          times[0].encodedTime[1] + 2), "Unexpected value\n");
2613         LocalFree(buf);
2614     }
2615 }
2616
2617 struct encodedExtensions
2618 {
2619     CERT_EXTENSIONS exts;
2620     const BYTE *encoded;
2621 };
2622
2623 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2624 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2625 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2626 static CERT_EXTENSION criticalExt =
2627  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2628 static CERT_EXTENSION nonCriticalExt =
2629  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2630 static CHAR oid_short[] = "1.1";
2631 static CERT_EXTENSION extWithShortOid =
2632  { oid_short, FALSE, { 0, NULL } };
2633
2634 static const BYTE ext0[] = { 0x30,0x00 };
2635 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2636                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2637 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2638                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2639 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2640
2641 static const struct encodedExtensions exts[] = {
2642  { { 0, NULL }, ext0 },
2643  { { 1, &criticalExt }, ext1 },
2644  { { 1, &nonCriticalExt }, ext2 },
2645  { { 1, &extWithShortOid }, ext3 }
2646 };
2647
2648 static void test_encodeExtensions(DWORD dwEncoding)
2649 {
2650     DWORD i;
2651
2652     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2653     {
2654         BOOL ret;
2655         BYTE *buf = NULL;
2656         DWORD bufSize = 0;
2657
2658         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2659          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2660         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2661         if (buf)
2662         {
2663             ok(bufSize == exts[i].encoded[1] + 2,
2664              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2665             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2666              "Unexpected value\n");
2667             LocalFree(buf);
2668         }
2669     }
2670 }
2671
2672 static void test_decodeExtensions(DWORD dwEncoding)
2673 {
2674     DWORD i;
2675
2676     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2677     {
2678         BOOL ret;
2679         BYTE *buf = NULL;
2680         DWORD bufSize = 0;
2681
2682         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2683          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2684          NULL, &buf, &bufSize);
2685         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2686         if (buf)
2687         {
2688             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2689             DWORD j;
2690
2691             ok(ext->cExtension == exts[i].exts.cExtension,
2692              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2693              ext->cExtension);
2694             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2695             {
2696                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2697                  exts[i].exts.rgExtension[j].pszObjId),
2698                  "Expected OID %s, got %s\n",
2699                  exts[i].exts.rgExtension[j].pszObjId,
2700                  ext->rgExtension[j].pszObjId);
2701                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2702                  exts[i].exts.rgExtension[j].Value.pbData,
2703                  exts[i].exts.rgExtension[j].Value.cbData),
2704                  "Unexpected value\n");
2705             }
2706             LocalFree(buf);
2707         }
2708     }
2709 }
2710
2711 /* MS encodes public key info with a NULL if the algorithm identifier's
2712  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2713  * it encodes them by omitting the algorithm parameters.  It accepts either
2714  * form for decoding.
2715  */
2716 struct encodedPublicKey
2717 {
2718     CERT_PUBLIC_KEY_INFO info;
2719     const BYTE *encoded;
2720     const BYTE *encodedNoNull;
2721     CERT_PUBLIC_KEY_INFO decoded;
2722 };
2723
2724 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2725  0xe, 0xf };
2726 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2727
2728 static const unsigned char bin64[] = {
2729     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2730 static const unsigned char bin65[] = {
2731     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2732 static const unsigned char bin66[] = {
2733     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2734 static const unsigned char bin67[] = {
2735     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2736 static const unsigned char bin68[] = {
2737     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2738     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2739 static const unsigned char bin69[] = {
2740     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2741     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2742 static const unsigned char bin70[] = {
2743     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2744     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2745     0x0f};
2746 static const unsigned char bin71[] = {
2747     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2748     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2749     0x0f};
2750 static unsigned char bin72[] = { 0x05,0x00};
2751
2752 static CHAR oid_bogus[] = "1.2.3",
2753             oid_rsa[]   = szOID_RSA;
2754
2755 static const struct encodedPublicKey pubKeys[] = {
2756  /* with a bogus OID */
2757  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2758   bin64, bin65,
2759   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2760  /* some normal keys */
2761  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2762   bin66, bin67,
2763   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2764  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2765   bin68, bin69,
2766   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2767  /* with add'l parameters--note they must be DER-encoded */
2768  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2769   (BYTE *)aKey, 0 } },
2770   bin70, bin71,
2771   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2772   (BYTE *)aKey, 0 } } },
2773 };
2774
2775 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2776 {
2777     DWORD i;
2778
2779     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2780     {
2781         BOOL ret;
2782         BYTE *buf = NULL;
2783         DWORD bufSize = 0;
2784
2785         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2786          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2787          &bufSize);
2788         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2789          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2790         if (buf)
2791         {
2792             ok(bufSize == pubKeys[i].encoded[1] + 2,
2793              "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2794             if (bufSize == pubKeys[i].encoded[1] + 2)
2795                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2796                  "Unexpected value\n");
2797             LocalFree(buf);
2798         }
2799     }
2800 }
2801
2802 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2803  const CERT_PUBLIC_KEY_INFO *got)
2804 {
2805     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2806      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2807      got->Algorithm.pszObjId);
2808     ok(expected->Algorithm.Parameters.cbData ==
2809      got->Algorithm.Parameters.cbData,
2810      "Expected parameters of %d bytes, got %d\n",
2811      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2812     if (expected->Algorithm.Parameters.cbData)
2813         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2814          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2815          "Unexpected algorithm parameters\n");
2816     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2817      "Expected public key of %d bytes, got %d\n",
2818      expected->PublicKey.cbData, got->PublicKey.cbData);
2819     if (expected->PublicKey.cbData)
2820         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2821          got->PublicKey.cbData), "Unexpected public key value\n");
2822 }
2823
2824 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2825 {
2826     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2827      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2828      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2829      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2830     DWORD i;
2831     BOOL ret;
2832     BYTE *buf = NULL;
2833     DWORD bufSize = 0;
2834
2835     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2836     {
2837         /* The NULL form decodes to the decoded member */
2838         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2839          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2840          NULL, &buf, &bufSize);
2841         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2842         if (buf)
2843         {
2844             comparePublicKeyInfo(&pubKeys[i].decoded,
2845              (CERT_PUBLIC_KEY_INFO *)buf);
2846             LocalFree(buf);
2847         }
2848         /* The non-NULL form decodes to the original */
2849         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2850          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2851          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2852         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2853         if (buf)
2854         {
2855             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2856             LocalFree(buf);
2857         }
2858     }
2859     /* Test with bogus (not valid DER) parameters */
2860     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2861      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2862      NULL, &buf, &bufSize);
2863     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2864      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2865      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2866      GetLastError());
2867 }
2868
2869 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2870  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2871  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2872  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2873  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2874 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2875  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2876  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2877  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2878  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2879 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2880  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2881  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2882  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2883  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2884 static const BYTE v4Cert[] = {
2885 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2886 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2887 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2888 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2889 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2890  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2891  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2892  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2893  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2894  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2895  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2896 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2897  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2898  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2899  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2900  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2901  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2902  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2903 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2904  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2905  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2906  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2907  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2908  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2909  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2910  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2911  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2912  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2913 static const BYTE v1CertWithPubKey[] = {
2914 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2915 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2916 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2917 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2918 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2919 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2920 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2921 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2922 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2923 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2924 0x01,0x01 };
2925 static const BYTE v1CertWithPubKeyNoNull[] = {
2926 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2927 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2928 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2929 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2930 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2931 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2932 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2933 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2934 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2935 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2936 static const BYTE v1CertWithSubjectKeyId[] = {
2937 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2938 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2939 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2940 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2941 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2942 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2943 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2944 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2945 0x4c,0x61,0x6e,0x67,0x00 };
2946 static const BYTE v1CertWithIssuerUniqueId[] = {
2947 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2948 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2949 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2950 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2951 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2952 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2953 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2954 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2955 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2956 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2957 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2958 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2959 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2960 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2961 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2962 0x01,0x01,0xff,0x02,0x01,0x01 };
2963 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2964 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2965 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2966 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2967 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2968 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2969 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2970 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2971 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2972 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2973 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2974 0xff,0x02,0x01,0x01 };
2975
2976 static const BYTE serialNum[] = { 0x01 };
2977
2978 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2979 {
2980     BOOL ret;
2981     BYTE *buf = NULL;
2982     DWORD size = 0;
2983     CERT_INFO info = { 0 };
2984     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2985     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2986     CERT_EXTENSION ext;
2987
2988     if (0)
2989     {
2990         /* Test with NULL pvStructInfo (crashes on win9x) */
2991         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2992          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2993         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2994          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2995     }
2996     /* Test with a V1 cert */
2997     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2998      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2999     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3000      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3001     if (buf)
3002     {
3003         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3004          v1Cert[1] + 2, size);
3005         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3006         LocalFree(buf);
3007     }
3008     /* Test v2 cert */
3009     info.dwVersion = CERT_V2;
3010     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3011      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3012     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3013      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3014     if (buf)
3015     {
3016         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3017         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3018         LocalFree(buf);
3019     }
3020     /* Test v3 cert */
3021     info.dwVersion = CERT_V3;
3022     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3023      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3024     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3025      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3026     if (buf)
3027     {
3028         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3029         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3030         LocalFree(buf);
3031     }
3032     /* A v4 cert? */
3033     info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3034     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3035      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3036     if (buf)
3037     {
3038         ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3039         ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3040         LocalFree(buf);
3041     }
3042     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3043      * API doesn't prevent it)
3044      */
3045     info.dwVersion = CERT_V1;
3046     info.cExtension = 1;
3047     info.rgExtension = &criticalExt;
3048     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3049      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3050     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3051      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3052     if (buf)
3053     {
3054         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3055         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3056         LocalFree(buf);
3057     }
3058     /* test v1 cert with a serial number */
3059     info.SerialNumber.cbData = sizeof(serialNum);
3060     info.SerialNumber.pbData = (BYTE *)serialNum;
3061     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3062      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3063     if (buf)
3064     {
3065         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3066         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3067         LocalFree(buf);
3068     }
3069     /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3070     info.dwVersion = CERT_V1;
3071     info.cExtension = 0;
3072     info.IssuerUniqueId.cbData = sizeof(serialNum);
3073     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3074     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3075      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3076     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3077     if (buf)
3078     {
3079         ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3080         ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3081          "Got unexpected value\n");
3082         LocalFree(buf);
3083     }
3084     /* Test v1 cert with an issuer name, a subject name, and a serial number */
3085     info.IssuerUniqueId.cbData = 0;
3086     info.IssuerUniqueId.pbData = NULL;
3087     info.cExtension = 1;
3088     info.rgExtension = &criticalExt;
3089     info.Issuer.cbData = sizeof(encodedCommonName);
3090     info.Issuer.pbData = (BYTE *)encodedCommonName;
3091     info.Subject.cbData = sizeof(encodedCommonName);
3092     info.Subject.pbData = (BYTE *)encodedCommonName;
3093     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3094      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3095     if (buf)
3096     {
3097         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3098         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3099         LocalFree(buf);
3100     }
3101     /* Add a public key */
3102     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3103     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3104     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3105     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3106      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3107     if (buf)
3108     {
3109         ok(size == sizeof(v1CertWithPubKey) ||
3110          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3111         if (size == sizeof(v1CertWithPubKey))
3112             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3113         else if (size == sizeof(v1CertWithPubKeyNoNull))
3114             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3115              "Got unexpected value\n");
3116         LocalFree(buf);
3117     }
3118     /* Again add an issuer unique id */
3119     info.IssuerUniqueId.cbData = sizeof(serialNum);
3120     info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3121     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3122      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3123     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3124     if (buf)
3125     {
3126         ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3127          size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3128          "Wrong size %d\n", size);
3129         if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3130             ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3131              size), "unexpected value\n");
3132         else if (size ==
3133          sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3134             ok(!memcmp(buf,
3135              v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3136              "unexpected value\n");
3137         LocalFree(buf);
3138     }
3139     /* Remove the public key, and add a subject key identifier extension */
3140     info.IssuerUniqueId.cbData = 0;
3141     info.IssuerUniqueId.pbData = NULL;
3142     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3143     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3144     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3145     ext.pszObjId = oid_subject_key_identifier;
3146     ext.fCritical = FALSE;
3147     ext.Value.cbData = sizeof(octetCommonNameValue);
3148     ext.Value.pbData = octetCommonNameValue;
3149     info.cExtension = 1;
3150     info.rgExtension = &ext;
3151     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3152      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3153     if (buf)
3154     {
3155         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3156         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3157         LocalFree(buf);
3158     }
3159 }
3160
3161 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3162 {
3163     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3164      v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3165     BOOL ret;
3166     BYTE *buf = NULL;
3167     DWORD size = 0, i;
3168
3169     /* Test with NULL pbEncoded */
3170     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3171      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3172     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3173      GetLastError() == OSS_BAD_ARG /* Win9x */),
3174      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3175     if (0)
3176     {
3177         /* Crashes on win9x */
3178         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3179          CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3180         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3181          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3182     }
3183     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3184      * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3185      * serial number, an issuer, a subject, and a public key.
3186      */
3187     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3188     {
3189         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3190          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3191          &buf, &size);
3192         ok(!ret, "Expected failure\n");
3193     }
3194     /* The following succeeds, even though v1 certs are not allowed to have
3195      * extensions.
3196      */
3197     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3198      v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3199      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3200     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3201     if (ret)
3202     {
3203         CERT_INFO *info = (CERT_INFO *)buf;
3204
3205         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3206         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3207          info->dwVersion);
3208         ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3209          info->cExtension);
3210         LocalFree(buf);
3211     }
3212     /* The following also succeeds, even though V1 certs are not allowed to
3213      * have issuer unique ids.
3214      */
3215     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3216      v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3217      sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3218      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3219     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3220     if (ret)
3221     {
3222         CERT_INFO *info = (CERT_INFO *)buf;
3223
3224         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3225         ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3226          info->dwVersion);
3227         ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3228          "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3229         ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3230          "unexpected issuer unique id value\n");
3231         LocalFree(buf);
3232     }
3233     /* Now check with serial number, subject and issuer specified */
3234     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3235      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3236     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3237     if (buf)
3238     {
3239         CERT_INFO *info = (CERT_INFO *)buf;
3240
3241         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3242         ok(info->SerialNumber.cbData == 1,
3243          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3244         ok(*info->SerialNumber.pbData == *serialNum,
3245          "Expected serial number %d, got %d\n", *serialNum,
3246          *info->SerialNumber.pbData);
3247         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3248          "Wrong size %d\n", info->Issuer.cbData);
3249         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3250          "Unexpected issuer\n");
3251         ok(info->Subject.cbData == sizeof(encodedCommonName),
3252          "Wrong size %d\n", info->Subject.cbData);
3253         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3254          info->Subject.cbData), "Unexpected subject\n");
3255         LocalFree(buf);
3256     }
3257     /* Check again with pub key specified */
3258     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3259      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3260      &buf, &size);
3261     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3262     if (buf)
3263     {
3264         CERT_INFO *info = (CERT_INFO *)buf;
3265
3266         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3267         ok(info->SerialNumber.cbData == 1,
3268          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3269         ok(*info->SerialNumber.pbData == *serialNum,
3270          "Expected serial number %d, got %d\n", *serialNum,
3271          *info->SerialNumber.pbData);
3272         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3273          "Wrong size %d\n", info->Issuer.cbData);
3274         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3275          "Unexpected issuer\n");
3276         ok(info->Subject.cbData == sizeof(encodedCommonName),
3277          "Wrong size %d\n", info->Subject.cbData);
3278         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3279          info->Subject.cbData), "Unexpected subject\n");
3280         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3281          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3282          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3283         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3284          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3285         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3286          sizeof(aKey)), "Unexpected public key\n");
3287         LocalFree(buf);
3288     }
3289 }
3290
3291 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3292  0xe, 0xf };
3293
3294 static const BYTE signedBigCert[] = {
3295  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3296  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3297  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3298  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3299  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3300  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3301  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3302  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3303  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3304  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3305  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3306  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3307
3308 static void test_encodeCert(DWORD dwEncoding)
3309 {
3310     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3311      * also that bigCert is a NULL-terminated string, so don't count its
3312      * last byte (otherwise the signed cert won't decode.)
3313      */
3314     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3315      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3316     BOOL ret;
3317     BYTE *buf = NULL;
3318     DWORD bufSize = 0;
3319
3320     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3321      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3322     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3323     if (buf)
3324     {
3325         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3326         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3327         LocalFree(buf);
3328     }
3329 }
3330
3331 static void test_decodeCert(DWORD dwEncoding)
3332 {
3333     BOOL ret;
3334     BYTE *buf = NULL;
3335     DWORD size = 0;
3336
3337     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3338      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3339     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3340     if (buf)
3341     {
3342         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3343
3344         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3345          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3346         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3347          "Unexpected cert\n");
3348         ok(info->Signature.cbData == sizeof(hash),
3349          "Wrong signature size %d\n", info->Signature.cbData);
3350         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3351          "Unexpected signature\n");
3352         LocalFree(buf);
3353     }
3354     /* A signed cert decodes as a CERT_INFO too */
3355     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3356      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3357     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3358     if (buf)
3359     {
3360         CERT_INFO *info = (CERT_INFO *)buf;
3361
3362         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3363         ok(info->SerialNumber.cbData == 1,
3364          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3365         ok(*info->SerialNumber.pbData == *serialNum,
3366          "Expected serial number %d, got %d\n", *serialNum,
3367          *info->SerialNumber.pbData);
3368         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3369          "Wrong size %d\n", info->Issuer.cbData);
3370         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3371          "Unexpected issuer\n");
3372         ok(info->Subject.cbData == sizeof(encodedCommonName),
3373          "Wrong size %d\n", info->Subject.cbData);
3374         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3375          info->Subject.cbData), "Unexpected subject\n");
3376         LocalFree(buf);
3377     }
3378 }
3379
3380 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3381 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3382  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3383  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3384 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3385  0x00, 0x03 };
3386 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3387  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3388  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3389 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3390  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3391  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3392  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3393  0x2e, 0x6f, 0x72, 0x67 };
3394 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3395  CRL_REASON_AFFILIATION_CHANGED;
3396
3397 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3398 {
3399     CRL_DIST_POINTS_INFO info = { 0 };
3400     CRL_DIST_POINT point = { { 0 } };
3401     CERT_ALT_NAME_ENTRY entry = { 0 };
3402     BOOL ret;
3403     BYTE *buf = NULL;
3404     DWORD size = 0;
3405
3406     /* Test with an empty info */
3407     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3408      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3409     ok(!ret && GetLastError() == E_INVALIDARG,
3410      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3411     /* Test with one empty dist point */
3412     info.cDistPoint = 1;
3413     info.rgDistPoint = &point;
3414     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3415      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3416     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3417     if (buf)
3418     {
3419         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3420         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3421         LocalFree(buf);
3422     }
3423     /* A dist point with an invalid name */
3424     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3425     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3426     U(entry).pwszURL = (LPWSTR)nihongoURL;
3427     U(point.DistPointName).FullName.cAltEntry = 1;
3428     U(point.DistPointName).FullName.rgAltEntry = &entry;
3429     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3430      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3431     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3432      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3433     /* The first invalid character is at index 7 */
3434     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3435      "Expected invalid char at index 7, got %d\n",
3436      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3437     /* A dist point with (just) a valid name */
3438     U(entry).pwszURL = (LPWSTR)url;
3439     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3440      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3441     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3442     if (buf)
3443     {
3444         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3445         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3446         LocalFree(buf);
3447     }
3448     /* A dist point with (just) reason flags */
3449     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3450     point.ReasonFlags.cbData = sizeof(crlReason);
3451     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3452     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3453      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3454     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3455     if (buf)
3456     {
3457         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3458         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3459         LocalFree(buf);
3460     }
3461     /* A dist point with just an issuer */
3462     point.ReasonFlags.cbData = 0;
3463     point.CRLIssuer.cAltEntry = 1;
3464     point.CRLIssuer.rgAltEntry = &entry;
3465     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3466      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3467     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3468     if (buf)
3469     {
3470         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3471         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3472         LocalFree(buf);
3473     }
3474     /* A dist point with both a name and an issuer */
3475     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3476     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3477      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3478     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3479     if (buf)
3480     {
3481         ok(size == sizeof(distPointWithUrlAndIssuer),
3482          "Wrong size %d\n", size);
3483         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3484         LocalFree(buf);
3485     }
3486 }
3487
3488 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3489 {
3490     BOOL ret;
3491     BYTE *buf = NULL;
3492     DWORD size = 0;
3493     PCRL_DIST_POINTS_INFO info;
3494     PCRL_DIST_POINT point;
3495     PCERT_ALT_NAME_ENTRY entry;
3496
3497     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3498      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3499      &buf, &size);
3500     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3501     if (ret)
3502     {
3503         info = (PCRL_DIST_POINTS_INFO)buf;
3504         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3505          "Wrong size %d\n", size);
3506         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3507          info->cDistPoint);
3508         point = info->rgDistPoint;
3509         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3510          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3511          point->DistPointName.dwDistPointNameChoice);
3512         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3513         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3514         LocalFree(buf);
3515     }
3516     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3517      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3518      &buf, &size);
3519     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3520     if (ret)
3521     {
3522         info = (PCRL_DIST_POINTS_INFO)buf;
3523         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3524          "Wrong size %d\n", size);
3525         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3526          info->cDistPoint);
3527         point = info->rgDistPoint;
3528         ok(point->DistPointName.dwDistPointNameChoice ==
3529          CRL_DIST_POINT_FULL_NAME,
3530          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3531          point->DistPointName.dwDistPointNameChoice);
3532         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3533          "Expected 1 name entry, got %d\n",
3534          U(point->DistPointName).FullName.cAltEntry);
3535         entry = U(point->DistPointName).FullName.rgAltEntry;
3536         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3537          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3538         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3539         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3540         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3541         LocalFree(buf);
3542     }
3543     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3544      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3545      NULL, &buf, &size);
3546     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3547     if (ret)
3548     {
3549         info = (PCRL_DIST_POINTS_INFO)buf;
3550         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3551          "Wrong size %d\n", size);
3552         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3553          info->cDistPoint);
3554         point = info->rgDistPoint;
3555         ok(point->DistPointName.dwDistPointNameChoice ==
3556          CRL_DIST_POINT_NO_NAME,
3557          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3558          point->DistPointName.dwDistPointNameChoice);
3559         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3560          "Expected reason length\n");
3561         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3562          "Unexpected reason\n");
3563         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3564         LocalFree(buf);
3565     }
3566     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3567      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3568      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3569     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3570     if (ret)
3571     {
3572         info = (PCRL_DIST_POINTS_INFO)buf;
3573         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3574          "Wrong size %d\n", size);
3575         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3576          info->cDistPoint);
3577         point = info->rgDistPoint;
3578         ok(point->DistPointName.dwDistPointNameChoice ==
3579          CRL_DIST_POINT_FULL_NAME,
3580          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3581          point->DistPointName.dwDistPointNameChoice);
3582         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3583          "Expected 1 name entry, got %d\n",
3584          U(point->DistPointName).FullName.cAltEntry);
3585         entry = U(point->DistPointName).FullName.rgAltEntry;
3586         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3587          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3588         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3589         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3590         ok(point->CRLIssuer.cAltEntry == 1,
3591          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3592         entry = point->CRLIssuer.rgAltEntry;
3593         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3594          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3595         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3596         LocalFree(buf);
3597     }
3598 }
3599
3600 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3601 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3602 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3603  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3604  0x67 };
3605
3606 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3607 {
3608     BOOL ret;
3609     BYTE *buf = NULL;
3610     DWORD size = 0;
3611     CRL_ISSUING_DIST_POINT point = { { 0 } };
3612     CERT_ALT_NAME_ENTRY entry;
3613
3614     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3615      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3616     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3617     {
3618         skip("no X509_ISSUING_DIST_POINT encode support\n");
3619         return;
3620     }
3621     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3622      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3623     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3624      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3625     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3626     if (buf)
3627     {
3628         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3629         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3630         LocalFree(buf);
3631     }
3632     /* nonsensical flags */
3633     point.fOnlyContainsUserCerts = TRUE;
3634     point.fOnlyContainsCACerts = TRUE;
3635     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3636      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3637     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3638     if (buf)
3639     {
3640         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3641         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3642         LocalFree(buf);
3643     }
3644     /* unimplemented name type */
3645     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3646     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3647     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3648      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3649     ok(!ret && GetLastError() == E_INVALIDARG,
3650      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3651     /* empty name */
3652     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3653     U(point.DistPointName).FullName.cAltEntry = 0;
3654     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3655      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3656     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3657     if (buf)
3658     {
3659         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3660         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3661         LocalFree(buf);
3662     }
3663     /* name with URL entry */
3664     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3665     U(entry).pwszURL = (LPWSTR)url;
3666     U(point.DistPointName).FullName.cAltEntry = 1;
3667     U(point.DistPointName).FullName.rgAltEntry = &entry;
3668     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3669      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3670     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3671     if (buf)
3672     {
3673         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3674         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3675         LocalFree(buf);
3676     }
3677 }
3678
3679 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3680  const CERT_ALT_NAME_ENTRY *got)
3681 {
3682     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3683      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3684      got->dwAltNameChoice);
3685     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3686     {
3687         switch (got->dwAltNameChoice)
3688         {
3689         case CERT_ALT_NAME_RFC822_NAME:
3690         case CERT_ALT_NAME_DNS_NAME:
3691         case CERT_ALT_NAME_EDI_PARTY_NAME:
3692         case CERT_ALT_NAME_URL:
3693         case CERT_ALT_NAME_REGISTERED_ID:
3694             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3695              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3696              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3697              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3698              "Unexpected name\n");
3699             break;
3700         case CERT_ALT_NAME_X400_ADDRESS:
3701         case CERT_ALT_NAME_DIRECTORY_NAME:
3702         case CERT_ALT_NAME_IP_ADDRESS:
3703             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3704                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3705             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3706                        U(*got).IPAddress.cbData), "Unexpected value\n");
3707             break;
3708         }
3709     }
3710 }
3711
3712 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3713  const CERT_ALT_NAME_INFO *got)
3714 {
3715     DWORD i;
3716
3717     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3718      expected->cAltEntry, got->cAltEntry);
3719     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3720         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3721 }
3722
3723 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3724  const CRL_DIST_POINT_NAME *got)
3725 {
3726     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3727      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3728     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3729         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3730 }
3731
3732 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3733  const CRL_ISSUING_DIST_POINT *got)
3734 {
3735     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3736     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3737      "Unexpected fOnlyContainsUserCerts\n");
3738     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3739      "Unexpected fOnlyContainsCACerts\n");
3740     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3741      "Unexpected reason flags\n");
3742     ok(got->fIndirectCRL == expected->fIndirectCRL,
3743      "Unexpected fIndirectCRL\n");
3744 }
3745
3746 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3747 {
3748     BOOL ret;
3749     BYTE *buf = NULL;
3750     DWORD size = 0;
3751     CRL_ISSUING_DIST_POINT point = { { 0 } };
3752
3753     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3754      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3755      &buf, &size);
3756     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3757     {
3758         skip("no X509_ISSUING_DIST_POINT decode support\n");
3759         return;
3760     }
3761     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3762     if (ret)
3763     {
3764         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3765         LocalFree(buf);
3766     }
3767     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3768      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3769      &buf, &size);
3770     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3771     if (ret)
3772     {
3773         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3774         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3775         LocalFree(buf);
3776     }
3777     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3778      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3779      &buf, &size);
3780     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3781     if (ret)
3782     {
3783         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3784         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3785         U(point.DistPointName).FullName.cAltEntry = 0;
3786         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3787         LocalFree(buf);
3788     }
3789     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3790      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3791     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3792     if (ret)
3793     {
3794         CERT_ALT_NAME_ENTRY entry;
3795
3796         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3797         U(entry).pwszURL = (LPWSTR)url;
3798         U(point.DistPointName).FullName.cAltEntry = 1;
3799         U(point.DistPointName).FullName.rgAltEntry = &entry;
3800         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3801         LocalFree(buf);
3802     }
3803 }
3804
3805 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3806  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3807  0x30, 0x5a };
3808 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3809  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3810  0x30, 0x30, 0x30, 0x30, 0x5a };
3811 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3812  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3813  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3814  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3815  0x5a };
3816 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3817  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3818  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3819  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3820  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3821  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3822 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3823  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3824  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3825  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3826  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3827  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3828 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3829  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3830  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3831  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3832  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3833  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3834  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3835 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3836  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3837  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3838  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3839  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3840  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3841  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3842 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3843  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3844  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3845  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3846  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3847  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3848  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3849 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3850  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3851  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3852  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3853  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3854  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3855  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3856
3857 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3858 {
3859     BOOL ret;
3860     BYTE *buf = NULL;
3861     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3862     DWORD size = 0;
3863     CRL_INFO info = { 0 };
3864     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3865     CERT_EXTENSION ext;
3866
3867     /* Test with a V1 CRL */
3868     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3869      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3870     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3871      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3872     if (buf)
3873     {
3874         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3875         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3876         LocalFree(buf);
3877     }
3878     /* Test v2 CRL */
3879     info.dwVersion = CRL_V2;
3880     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3881      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3882     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3883      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3884     if (buf)
3885     {
3886         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3887          v2CRL[1] + 2, size);
3888         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3889         LocalFree(buf);
3890     }
3891     /* v1 CRL with a name */
3892     info.dwVersion = CRL_V1;
3893     info.Issuer.cbData = sizeof(encodedCommonName);
3894     info.Issuer.pbData = (BYTE *)encodedCommonName;
3895     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3896      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3897     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3898     if (buf)
3899     {
3900         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3901         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3902         LocalFree(buf);
3903     }
3904     if (0)
3905     {
3906         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3907         info.cCRLEntry = 1;
3908         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3909          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3910         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3911          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3912     }
3913     /* now set an empty entry */
3914     info.cCRLEntry = 1;
3915     info.rgCRLEntry = &entry;
3916     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3917      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3918     if (buf)
3919     {
3920         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3921          "Wrong size %d\n", size);
3922         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3923          "Got unexpected value\n");
3924         LocalFree(buf);
3925     }
3926     /* an entry with a serial number */
3927     entry.SerialNumber.cbData = sizeof(serialNum);
3928     entry.SerialNumber.pbData = (BYTE *)serialNum;
3929     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3930      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3931     if (buf)
3932     {
3933         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3934          "Wrong size %d\n", size);
3935         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3936          "Got unexpected value\n");
3937         LocalFree(buf);
3938     }
3939     /* an entry with an extension */
3940     entry.cExtension = 1;
3941     entry.rgExtension = &criticalExt;
3942     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3943      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3944     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3945     if (buf)
3946     {
3947         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3948         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3949         LocalFree(buf);
3950     }
3951     /* a CRL with an extension */
3952     entry.cExtension = 0;
3953     info.cExtension = 1;
3954     info.rgExtension = &criticalExt;
3955     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3956      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3957     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3958     if (buf)
3959     {
3960         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3961         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3962         LocalFree(buf);
3963     }
3964     /* a v2 CRL with an extension, this time non-critical */
3965     info.dwVersion = CRL_V2;
3966     info.rgExtension = &nonCriticalExt;
3967     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3968      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3969     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3970     if (buf)
3971     {
3972         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3973         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3974         LocalFree(buf);
3975     }
3976     /* a v2 CRL with an issuing dist point extension */
3977     ext.pszObjId = oid_issuing_dist_point;
3978     ext.fCritical = TRUE;
3979     ext.Value.cbData = sizeof(urlIDP);
3980     ext.Value.pbData = (LPBYTE)urlIDP;
3981     entry.rgExtension = &ext;
3982     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3983      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3984     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3985     if (buf)
3986     {
3987         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3988         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3989         LocalFree(buf);
3990     }
3991 }
3992
3993 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3994  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3995  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3996  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3997  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3998  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3999  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
4000  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
4001  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
4002  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
4003  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
4004  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
4005  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
4006  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
4007  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
4008  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
4009  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
4010  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
4011  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
4012  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
4013  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
4014  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
4015  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
4016  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
4017  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
4018  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4019  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4020  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4021  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4022  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4023  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4024  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4025  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4026  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4027  0xcd };
4028 static const BYTE verisignCRLWithLotsOfEntries[] = {
4029 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4030 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4031 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4032 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4033 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4034 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4035 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4036 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4037 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4038 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4039 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4040 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4041 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4042 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4043 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4044 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4045 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4046 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4047 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4048 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4049 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4050 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4051 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4052 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4053 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4054 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4055 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4056 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4057 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4058 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4059 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4060 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4061 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4062 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4063 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4064 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4065 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4066 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4067 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4068 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4069 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4070 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4071 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4072 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4073 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4074 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4075 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4076 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4077 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4078 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4079 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4080 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4081 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4082 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4083 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4084 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4085 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4086 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4087 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4088 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4089 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4090 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4091 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4092 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4093 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4094 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4095 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4096 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4097 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4098 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4099 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4100 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4101 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4102 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4103 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4104 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4105 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4106 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4107 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4108 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4109 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4110 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4111 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4112 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4113 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4114 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4115 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4116 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4117 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4118 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4119 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4120 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4121 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4122 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4123 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4124 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4125 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4126 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4127 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4128 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4129 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4130 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4131 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4132 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4133 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4134 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4135 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4136 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4137 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4138 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4139 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4140 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4141 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4142 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4143 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4144 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4145 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4146 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4147 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4148 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4149 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4150 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4151 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4152 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4153 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4154 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4155 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4156 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4157 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4158 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4159 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4160 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4161 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4162 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4163 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4164 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4165 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4166 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4167 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4168 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4169 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4170 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4171 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4172 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4173 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4174 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4175 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4176 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4177 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4178 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4179 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4180 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4181 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4182 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4183 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4184 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4185 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4186 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4187 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4188 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4189 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4190 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4191 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4192 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4193 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4194 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4195 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4196 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4197 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4198 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4199 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4200 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4201 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4202 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4203 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4204 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4205 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4206 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4207 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4208 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4209 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4210 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4211 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4212 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4213 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4214 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4215 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4216 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4217 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4218 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4219 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4220 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4221 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4222 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4223 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4224 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4225 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4226 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4227 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4228 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4229 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4230 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4231 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4232 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4233 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4234 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4235 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4236 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4237 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4238 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4239 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4240 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4241 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4242 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4243 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4244 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4245 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4246 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4247 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4248 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4249 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4250 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4251 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4252 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4253 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4254 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4255 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4256 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4257 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4258 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4259 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4260 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4261 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4262 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4263 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4264 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4265 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4266 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4267 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4268 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4269 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4270 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4271 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4272 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4273 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4274 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4275 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4276 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4277 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4278 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4279 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4280 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4281 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4282 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4283 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4284 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4285 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4286 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4287 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4288 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4289 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4290 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4291 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4292 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4293 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4294 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4295 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4296 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4297 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4298 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4299 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4300 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4301 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4302 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4303 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4304 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4305 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4306 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4307 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4308 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4309 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4310 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4311 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4312 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4313 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4314 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4315 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4316 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4317 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4318 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4319 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4320 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4321 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4322 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4323 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4324 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4325 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4326 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4327 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4328 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4329 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4330 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4331 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4332 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4333 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4334 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4335 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4336 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4337 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4338 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4339 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4340 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4341 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4342 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4343 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4344 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4345 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4346 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4347 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4348 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4349 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4350 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4351 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4352 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4353 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4354 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4355 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4356 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4357 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4358 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4359 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4360 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4361 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4362 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4363 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4364 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4365 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4366 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4367 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4368 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4369 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4370 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4371 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4372 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4373 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4374 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4375 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4376 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4377 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4378 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4379 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4380 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4381 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4382 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4383 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4384 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4385 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4386 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4387 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4388 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4389 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4390 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4391 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4392 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4393 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4394 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4395 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4396 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4397 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4398 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4399 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4400 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4401 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4402 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4403 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4404 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4405 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4406 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4407 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4408 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4409 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4410 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4411 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4412 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4413 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4414 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4415 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4416 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4417 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4418 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4419 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4420 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4421 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4422 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4423 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4424 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4425 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4426 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4427 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4428 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4429 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4430 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4431 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4432 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4433 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4434 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4435 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4436 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4437 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4438 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4439 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4440 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4441 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4442 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4443 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4444 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4445 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4446 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4447 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4448 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4449 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4450 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4451 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4452 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4453 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4454 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4455 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4456 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4457 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4458 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4459 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4460 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4461 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4462 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4463 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4464 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4465 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4466 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4467 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4468 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4469 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4470 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4471 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4472 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4473 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4474 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4475 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4476 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4477 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4478 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4479 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4480 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4481 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4482 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4483 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4484 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4485 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4486 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4487 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4488 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4489 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4490 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4491 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4492 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4493 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4494 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4495 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4496 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4497 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4498 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4499 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4500 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4501 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4502 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4503 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4504 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4505 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4506 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4507 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4508 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4509 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4510 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4511 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4512 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4513 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4514 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4515 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4516 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4517 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4518 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4519 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4520 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4521 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4522 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4523 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4524 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4525 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4526 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4527 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4528 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4529 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4530 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4531 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4532 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4533 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4534 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4535 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4536 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4537
4538 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4539 {
4540     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4541     BOOL ret;
4542     BYTE *buf = NULL;
4543     DWORD size = 0, i;
4544
4545     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4546     {
4547         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4548          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4549          &buf, &size);
4550         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4551          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4552          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4553          GetLastError());
4554     }
4555     /* at a minimum, a CRL must contain an issuer: */
4556     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4557      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4558      &buf, &size);
4559     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4560     if (buf)
4561     {
4562         CRL_INFO *info = (CRL_INFO *)buf;
4563
4564         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4565         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4566          info->cCRLEntry);
4567         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4568          "Wrong issuer size %d\n", info->Issuer.cbData);
4569         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4570          "Unexpected issuer\n");
4571         LocalFree(buf);
4572     }
4573     /* check decoding with an empty CRL entry */
4574     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4575      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4576      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4577     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4578      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4579      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4580      GetLastError());
4581     /* with a real CRL entry */
4582     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4583      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4584      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4585     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4586     if (buf)
4587     {
4588         CRL_INFO *info = (CRL_INFO *)buf;
4589         CRL_ENTRY *entry;
4590
4591         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4592         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4593          info->cCRLEntry);
4594         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4595         entry = info->rgCRLEntry;
4596         ok(entry->SerialNumber.cbData == 1,
4597          "Expected serial number size 1, got %d\n",
4598          entry->SerialNumber.cbData);
4599         ok(*entry->SerialNumber.pbData == *serialNum,
4600          "Expected serial number %d, got %d\n", *serialNum,
4601          *entry->SerialNumber.pbData);
4602         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4603          "Wrong issuer size %d\n", info->Issuer.cbData);
4604         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4605          "Unexpected issuer\n");
4606         LocalFree(buf);
4607     }
4608     /* a real CRL from verisign that has extensions */
4609     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4610      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4611      NULL, &buf, &size);
4612     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4613     if (buf)
4614     {
4615         CRL_INFO *info = (CRL_INFO *)buf;
4616         CRL_ENTRY *entry;
4617
4618         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4619         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4620          info->cCRLEntry);
4621         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4622         entry = info->rgCRLEntry;
4623         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4624          info->cExtension);
4625         LocalFree(buf);
4626     }
4627     /* another real CRL from verisign that has lots of entries */
4628     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4629      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4630      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4631     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4632     if (buf)
4633     {
4634         CRL_INFO *info = (CRL_INFO *)buf;
4635
4636         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4637         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4638          info->cCRLEntry);
4639         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4640          info->cExtension);
4641         LocalFree(buf);
4642     }
4643     /* and finally, with an extension */
4644     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4645      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4646      NULL, &buf, &size);
4647     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4648     if (buf)
4649     {
4650         CRL_INFO *info = (CRL_INFO *)buf;
4651         CRL_ENTRY *entry;
4652
4653         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4654         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4655          info->cCRLEntry);
4656         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4657         entry = info->rgCRLEntry;
4658         ok(entry->SerialNumber.cbData == 1,
4659          "Expected serial number size 1, got %d\n",
4660          entry->SerialNumber.cbData);
4661         ok(*entry->SerialNumber.pbData == *serialNum,
4662          "Expected serial number %d, got %d\n", *serialNum,
4663          *entry->SerialNumber.pbData);
4664         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4665          "Wrong issuer size %d\n", info->Issuer.cbData);
4666         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4667          "Unexpected issuer\n");
4668         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4669          info->cExtension);
4670         LocalFree(buf);
4671     }
4672     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4673      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4674      NULL, &buf, &size);
4675     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4676     if (buf)
4677     {
4678         CRL_INFO *info = (CRL_INFO *)buf;
4679
4680         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4681          info->cExtension);
4682         LocalFree(buf);
4683     }
4684     /* And again, with an issuing dist point */
4685     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4686      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4687      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4688     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4689     if (buf)
4690     {
4691         CRL_INFO *info = (CRL_INFO *)buf;
4692
4693         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4694          info->cExtension);
4695         LocalFree(buf);
4696     }
4697 }
4698
4699 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4700  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4701 static const BYTE encodedUsage[] = {
4702  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4703  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4704  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4705
4706 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4707 {
4708     BOOL ret;
4709     BYTE *buf = NULL;
4710     DWORD size = 0;
4711     CERT_ENHKEY_USAGE usage;
4712
4713     /* Test with empty usage */
4714     usage.cUsageIdentifier = 0;
4715     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4716      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4717     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4718     if (buf)
4719     {
4720         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4721         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4722         LocalFree(buf);
4723     }
4724     /* Test with a few usages */
4725     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4726     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4727     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4728      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4729     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4730     if (buf)
4731     {
4732         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4733         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4734         LocalFree(buf);
4735     }
4736 }
4737
4738 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4739 {
4740     BOOL ret;
4741     LPBYTE buf = NULL;
4742     DWORD size = 0;
4743
4744     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4745      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4746      &buf, &size);
4747     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4748     if (buf)
4749     {
4750         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4751
4752         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4753          "Wrong size %d\n", size);
4754         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4755          usage->cUsageIdentifier);
4756         LocalFree(buf);
4757     }
4758     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4759      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4760      &buf, &size);
4761     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4762     if (buf)
4763     {
4764         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4765         DWORD i;
4766
4767         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4768          "Wrong size %d\n", size);
4769         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4770          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4771         for (i = 0; i < usage->cUsageIdentifier; i++)
4772             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4773              "Expected OID %s, got %s\n", keyUsages[i],
4774              usage->rgpszUsageIdentifier[i]);
4775         LocalFree(buf);
4776     }
4777 }
4778
4779 static BYTE keyId[] = { 1,2,3,4 };
4780 static const BYTE authorityKeyIdWithId[] = {
4781  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4782 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4783  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4784  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4785 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4786
4787 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4788 {
4789     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4790     BOOL ret;
4791     BYTE *buf = NULL;
4792     DWORD size = 0;
4793
4794     /* Test with empty id */
4795     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4796      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4797     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4798     if (buf)
4799     {
4800         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4801         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4802         LocalFree(buf);
4803     }
4804     /* With just a key id */
4805     info.KeyId.cbData = sizeof(keyId);
4806     info.KeyId.pbData = keyId;
4807     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4808      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4809     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4810     if (buf)
4811     {
4812         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4813         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4814         LocalFree(buf);
4815     }
4816     /* With just an issuer */
4817     info.KeyId.cbData = 0;
4818     info.CertIssuer.cbData = sizeof(encodedCommonName);
4819     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4820     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4821      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4822     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4823     if (buf)
4824     {
4825         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4826          size);
4827         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4828         LocalFree(buf);
4829     }
4830     /* With just a serial number */
4831     info.CertIssuer.cbData = 0;
4832     info.CertSerialNumber.cbData = sizeof(serialNum);
4833     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4834     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4835      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4836     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4837     if (buf)
4838     {
4839         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4840          size);
4841         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4842         LocalFree(buf);
4843     }
4844 }
4845
4846 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4847 {
4848     BOOL ret;
4849     LPBYTE buf = NULL;
4850     DWORD size = 0;
4851
4852     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4853      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4854      &buf, &size);
4855     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4856     if (buf)
4857     {
4858         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4859
4860         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4861          size);
4862         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4863         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4864         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4865         LocalFree(buf);
4866     }
4867     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4868      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4869      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4870     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4871     if (buf)
4872     {
4873         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4874
4875         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4876          size);
4877         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4878         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4879          "Unexpected key id\n");
4880         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4881         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4882         LocalFree(buf);
4883     }
4884     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4885      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4886      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4887     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4888     if (buf)
4889     {
4890         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4891
4892         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4893          size);
4894         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4895         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4896          "Unexpected issuer len\n");
4897         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4898          sizeof(encodedCommonName)), "Unexpected issuer\n");
4899         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4900         LocalFree(buf);
4901     }
4902     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4903      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4904      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4905     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4906     if (buf)
4907     {
4908         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4909
4910         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4911          size);
4912         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4913         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4914         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4915          "Unexpected serial number len\n");
4916         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4917          "Unexpected serial number\n");
4918         LocalFree(buf);
4919     }
4920 }
4921
4922 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4923  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4924  0x6f,0x72,0x67 };
4925
4926 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4927 {
4928     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4929     CERT_ALT_NAME_ENTRY entry = { 0 };
4930     BOOL ret;
4931     BYTE *buf = NULL;
4932     DWORD size = 0;
4933
4934     /* Test with empty id */
4935     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4936      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4937     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4938     if (buf)
4939     {
4940         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4941         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4942         LocalFree(buf);
4943     }
4944     /* With just a key id */
4945     info.KeyId.cbData = sizeof(keyId);
4946     info.KeyId.pbData = keyId;
4947     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4948      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4949     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4950     if (buf)
4951     {
4952         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4953          size);
4954         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4955         LocalFree(buf);
4956     }
4957     /* With a bogus issuer name */
4958     info.KeyId.cbData = 0;
4959     info.AuthorityCertIssuer.cAltEntry = 1;
4960     info.AuthorityCertIssuer.rgAltEntry = &entry;
4961     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4962      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4963     ok(!ret && GetLastError() == E_INVALIDARG,
4964      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4965     /* With an issuer name */
4966     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4967     U(entry).pwszURL = (LPWSTR)url;
4968     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4969      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4970     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4971     if (buf)
4972     {
4973         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4974          size);
4975         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4976          "Unexpected value\n");
4977         LocalFree(buf);
4978     }
4979     /* With just a serial number */
4980     info.AuthorityCertIssuer.cAltEntry = 0;
4981     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4982     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4983     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4984      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4985     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4986     if (buf)
4987     {
4988         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4989          size);
4990         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4991         LocalFree(buf);
4992     }
4993 }
4994
4995 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4996 {
4997     BOOL ret;
4998     LPBYTE buf = NULL;
4999     DWORD size = 0;
5000
5001     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5002      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5003      &buf, &size);
5004     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5005     if (buf)
5006     {
5007         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5008
5009         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5010          size);
5011         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5012         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5013          "Expected no issuer name entries\n");
5014         ok(info->AuthorityCertSerialNumber.cbData == 0,
5015          "Expected no serial number\n");
5016         LocalFree(buf);
5017     }
5018     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5019      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
5020      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5021     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5022     if (buf)
5023     {
5024         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5025
5026         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5027          size);
5028         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5029         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5030          "Unexpected key id\n");
5031         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5032          "Expected no issuer name entries\n");
5033         ok(info->AuthorityCertSerialNumber.cbData == 0,
5034          "Expected no serial number\n");
5035         LocalFree(buf);
5036     }
5037     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5038      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5039      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5040     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5041     if (buf)
5042     {
5043         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5044
5045         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5046          size);
5047         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5048         ok(info->AuthorityCertIssuer.cAltEntry == 1,
5049          "Expected 1 issuer entry, got %d\n",
5050          info->AuthorityCertIssuer.cAltEntry);
5051         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5052          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5053          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5054         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5055          url), "Unexpected URL\n");
5056         ok(info->AuthorityCertSerialNumber.cbData == 0,
5057          "Expected no serial number\n");
5058         LocalFree(buf);
5059     }
5060     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5061      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5062      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5063     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5064     if (buf)
5065     {
5066         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5067
5068         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5069          size);
5070         ok(info->KeyId.cbData == 0, "Expected no key id\n");
5071         ok(info->AuthorityCertIssuer.cAltEntry == 0,
5072          "Expected no issuer name entries\n");
5073         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5074          "Unexpected serial number len\n");
5075         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5076          sizeof(serialNum)), "Unexpected serial number\n");
5077         LocalFree(buf);
5078     }
5079 }
5080
5081 static const BYTE authorityInfoAccessWithUrl[] = {
5082 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5083 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5084 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5085 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5086 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5087 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5088
5089 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5090 {
5091     static char oid1[] = "1.2.3";
5092     static char oid2[] = "1.5.6";
5093     BOOL ret;
5094     BYTE *buf = NULL;
5095     DWORD size = 0;
5096     CERT_ACCESS_DESCRIPTION accessDescription[2];
5097     CERT_AUTHORITY_INFO_ACCESS aia;
5098
5099     memset(accessDescription, 0, sizeof(accessDescription));
5100     aia.cAccDescr = 0;
5101     aia.rgAccDescr = NULL;
5102     /* Having no access descriptions is allowed */
5103     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5104      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5105     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5106     if (buf)
5107     {
5108         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5109         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5110         LocalFree(buf);
5111         buf = NULL;
5112     }
5113     /* It can't have an empty access method */
5114     aia.cAccDescr = 1;
5115     aia.rgAccDescr = accessDescription;
5116     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5117      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5118     ok(!ret && (GetLastError() == E_INVALIDARG ||
5119      GetLastError() == OSS_LIMITED /* Win9x */),
5120      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5121     /* It can't have an empty location */
5122     accessDescription[0].pszAccessMethod = oid1;
5123     SetLastError(0xdeadbeef);
5124     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5125      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5126     ok(!ret && GetLastError() == E_INVALIDARG,
5127      "expected E_INVALIDARG, got %08x\n", GetLastError());
5128     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5129     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5130     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5131      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5132     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5133     if (buf)
5134     {
5135         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5136          size);
5137         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5138          "unexpected value\n");
5139         LocalFree(buf);
5140         buf = NULL;
5141     }
5142     accessDescription[1].pszAccessMethod = oid2;
5143     accessDescription[1].AccessLocation.dwAltNameChoice =
5144      CERT_ALT_NAME_IP_ADDRESS;
5145     U(accessDescription[1].AccessLocation).IPAddress.cbData =
5146      sizeof(encodedIPAddr);
5147     U(accessDescription[1].AccessLocation).IPAddress.pbData =
5148      (LPBYTE)encodedIPAddr;
5149     aia.cAccDescr = 2;
5150     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5151      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5152     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5153     if (buf)
5154     {
5155         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5156          "unexpected size %d\n", size);
5157         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5158          "unexpected value\n");
5159         LocalFree(buf);
5160         buf = NULL;
5161     }
5162 }
5163
5164 static void compareAuthorityInfoAccess(LPCSTR header,
5165  const CERT_AUTHORITY_INFO_ACCESS *expected,
5166  const CERT_AUTHORITY_INFO_ACCESS *got)
5167 {
5168     DWORD i;
5169
5170     ok(expected->cAccDescr == got->cAccDescr,
5171      "%s: expected %d access descriptions, got %d\n", header,
5172      expected->cAccDescr, got->cAccDescr);
5173     for (i = 0; i < expected->cAccDescr; i++)
5174     {
5175         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5176          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5177          header, i, expected->rgAccDescr[i].pszAccessMethod,
5178          got->rgAccDescr[i].pszAccessMethod);
5179         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5180          &got->rgAccDescr[i].AccessLocation);
5181     }
5182 }
5183
5184 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5185 {
5186     static char oid1[] = "1.2.3";
5187     static char oid2[] = "1.5.6";
5188     BOOL ret;
5189     LPBYTE buf = NULL;
5190     DWORD size = 0;
5191
5192     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5193      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5194      &buf, &size);
5195     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5196     if (buf)
5197     {
5198         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5199
5200         compareAuthorityInfoAccess("empty AIA", &aia,
5201          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5202         LocalFree(buf);
5203         buf = NULL;
5204     }
5205     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5206      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5207      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5208     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5209     if (buf)
5210     {
5211         CERT_ACCESS_DESCRIPTION accessDescription;
5212         CERT_AUTHORITY_INFO_ACCESS aia;
5213
5214         accessDescription.pszAccessMethod = oid1;
5215         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5216         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5217         aia.cAccDescr = 1;
5218         aia.rgAccDescr = &accessDescription;
5219         compareAuthorityInfoAccess("AIA with URL", &aia,
5220          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5221         LocalFree(buf);
5222         buf = NULL;
5223     }
5224     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5225      authorityInfoAccessWithUrlAndIPAddr,
5226      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5227      NULL, &buf, &size);
5228     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5229     if (buf)
5230     {
5231         CERT_ACCESS_DESCRIPTION accessDescription[2];
5232         CERT_AUTHORITY_INFO_ACCESS aia;
5233
5234         accessDescription[0].pszAccessMethod = oid1;
5235         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5236         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5237         accessDescription[1].pszAccessMethod = oid2;
5238         accessDescription[1].AccessLocation.dwAltNameChoice =
5239          CERT_ALT_NAME_IP_ADDRESS;
5240         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5241          sizeof(encodedIPAddr);
5242         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5243          (LPBYTE)encodedIPAddr;
5244         aia.cAccDescr = 2;
5245         aia.rgAccDescr = accessDescription;
5246         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5247          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5248         LocalFree(buf);
5249         buf = NULL;
5250     }
5251 }
5252
5253 static const BYTE emptyCTL[] = {
5254 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5255 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5256 static const BYTE emptyCTLWithVersion1[] = {
5257 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5258 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5259 static const BYTE ctlWithUsageIdentifier[] = {
5260 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5261 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5262 static const BYTE ctlWithListIdentifier[] = {
5263 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5264 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5265 static const BYTE ctlWithSequenceNumber[] = {
5266 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5267 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5268 static const BYTE ctlWithThisUpdate[] = {
5269 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5270 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5271 static const BYTE ctlWithThisAndNextUpdate[] = {
5272 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5273 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5274 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5275 static const BYTE ctlWithAlgId[] = {
5276 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5277 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5278 static const BYTE ctlWithBogusEntry[] = {
5279 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5280 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5281 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5282 static const BYTE ctlWithOneEntry[] = {
5283 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5284 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5285 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5286 static const BYTE ctlWithTwoEntries[] = {
5287 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5288 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5289 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5290 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5291 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5292
5293 static void test_encodeCTL(DWORD dwEncoding)
5294 {
5295     static char oid1[] = "1.2.3";
5296     static char oid2[] = "1.5.6";
5297     char *pOid1 = oid1;
5298     BOOL ret;
5299     BYTE *buf = NULL;
5300     DWORD size = 0;
5301     CTL_INFO info;
5302     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5303     CTL_ENTRY ctlEntry[2];
5304     CRYPT_ATTRIBUTE attr1, attr2;
5305     CRYPT_ATTR_BLOB value1, value2;
5306
5307     memset(&info, 0, sizeof(info));
5308     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5309      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5310     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5311     if (buf)
5312     {
5313         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5314         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5315         LocalFree(buf);
5316         buf = NULL;
5317     }
5318     info.dwVersion = 1;
5319     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5320      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5321     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5322     if (buf)
5323     {
5324         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5325         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5326         LocalFree(buf);
5327         buf = NULL;
5328     }
5329     info.dwVersion = 0;
5330     info.SubjectUsage.cUsageIdentifier = 1;
5331     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5332     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5333      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5334     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5335     if (buf)
5336     {
5337         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5338          size);
5339         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5340         LocalFree(buf);
5341         buf = NULL;
5342     }
5343     info.SubjectUsage.cUsageIdentifier = 0;
5344     info.ListIdentifier.cbData = sizeof(serialNum);
5345     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5346     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5347      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5348     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5349     if (buf)
5350     {
5351         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5352         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5353         LocalFree(buf);
5354         buf = NULL;
5355     }
5356     info.ListIdentifier.cbData = 0;
5357     info.SequenceNumber.cbData = sizeof(serialNum);
5358     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5359     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5360      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5361     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5362     if (buf)
5363     {
5364         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5365          size);
5366         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5367         LocalFree(buf);
5368         buf = NULL;
5369     }
5370     info.SequenceNumber.cbData = 0;
5371     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5372     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5373      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5374     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5375     if (buf)
5376     {
5377         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5378         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5379         LocalFree(buf);
5380         buf = NULL;
5381     }
5382     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5383     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5384      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5385     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5386     if (buf)
5387     {
5388         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5389          size);
5390         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5391         LocalFree(buf);
5392         buf = NULL;
5393     }
5394     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5395     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5396     info.SubjectAlgorithm.pszObjId = oid2;
5397     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5398      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5399     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5400     if (buf)
5401     {
5402         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5403         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5404         LocalFree(buf);
5405         buf = NULL;
5406     }
5407     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5408      * (see tests below) but it'll encode fine.
5409      */
5410     info.SubjectAlgorithm.pszObjId = NULL;
5411     value1.cbData = sizeof(serialNum);
5412     value1.pbData = (LPBYTE)serialNum;
5413     attr1.pszObjId = oid1;
5414     attr1.cValue = 1;
5415     attr1.rgValue = &value1;
5416     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5417     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5418     ctlEntry[0].cAttribute = 1;
5419     ctlEntry[0].rgAttribute = &attr1;
5420     info.cCTLEntry = 1;
5421     info.rgCTLEntry = ctlEntry;
5422     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5423      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5424     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5425     if (buf)
5426     {
5427         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5428         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5429         LocalFree(buf);
5430         buf = NULL;
5431     }
5432     value1.cbData = sizeof(emptySequence);
5433     value1.pbData = (LPBYTE)emptySequence;
5434     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5435      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5436     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5437     if (buf)
5438     {
5439         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5440         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5441         LocalFree(buf);
5442         buf = NULL;
5443     }
5444     value2.cbData = sizeof(encodedIPAddr);
5445     value2.pbData = (LPBYTE)encodedIPAddr;
5446     attr2.pszObjId = oid2;
5447     attr2.cValue = 1;
5448     attr2.rgValue = &value2;
5449     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5450     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5451     ctlEntry[1].cAttribute = 1;
5452     ctlEntry[1].rgAttribute = &attr2;
5453     info.cCTLEntry = 2;
5454     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5455      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5456     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5457     if (buf)
5458     {
5459         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5460         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5461         LocalFree(buf);
5462         buf = NULL;
5463     }
5464 }
5465
5466 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5467  const CTL_INFO *got)
5468 {
5469     DWORD i, j, k;
5470
5471     ok(expected->dwVersion == got->dwVersion,
5472      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5473      got->dwVersion);
5474     ok(expected->SubjectUsage.cUsageIdentifier ==
5475      got->SubjectUsage.cUsageIdentifier,
5476      "%s: expected %d usage identifiers, got %d\n", header,
5477      expected->SubjectUsage.cUsageIdentifier,
5478      got->SubjectUsage.cUsageIdentifier);
5479     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5480         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5481          got->SubjectUsage.rgpszUsageIdentifier[i]),
5482          "%s[%d]: expected %s, got %s\n", header, i,
5483          expected->SubjectUsage.rgpszUsageIdentifier[i],
5484          got->SubjectUsage.rgpszUsageIdentifier[i]);
5485     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5486      "%s: expected list identifier of %d bytes, got %d\n", header,
5487      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5488     if (expected->ListIdentifier.cbData)
5489         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5490          expected->ListIdentifier.cbData),
5491          "%s: unexpected list identifier value\n", header);
5492     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5493      "%s: expected sequence number of %d bytes, got %d\n", header,
5494      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5495     if (expected->SequenceNumber.cbData)
5496         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5497          expected->SequenceNumber.cbData),
5498          "%s: unexpected sequence number value\n", header);
5499     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5500      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5501      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5502      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5503     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5504      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5505      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5506      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5507     if (expected->SubjectAlgorithm.pszObjId &&
5508      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5509         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5510          expected->SubjectAlgorithm.pszObjId);
5511     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5512         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5513          got->SubjectAlgorithm.pszObjId),
5514          "%s: expected subject algorithm %s, got %s\n", header,
5515          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5516     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5517      got->SubjectAlgorithm.Parameters.cbData,
5518      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5519      expected->SubjectAlgorithm.Parameters.cbData,
5520      got->SubjectAlgorithm.Parameters.cbData);
5521     if (expected->SubjectAlgorithm.Parameters.cbData)
5522         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5523          got->SubjectAlgorithm.Parameters.pbData,
5524          expected->SubjectAlgorithm.Parameters.cbData),
5525          "%s: unexpected subject algorithm parameter value\n", header);
5526     ok(expected->cCTLEntry == got->cCTLEntry,
5527      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5528      got->cCTLEntry);
5529     for (i = 0; i < expected->cCTLEntry; i++)
5530     {
5531         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5532          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5533          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5534          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5535          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5536         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5537             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5538              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5539              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5540              "%s[%d]: unexpected subject identifier value\n",
5541              header, i);
5542         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5543         {
5544             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5545              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5546              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5547              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5548              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5549             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5550             {
5551                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5552                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5553                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5554                  header, i, j, k,
5555                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5556                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5557                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5558                     ok(!memcmp(
5559                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5560                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5561                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5562                      "%s[%d][%d][%d]: unexpected value\n",
5563                      header, i, j, k);
5564             }
5565         }
5566     }
5567     ok(expected->cExtension == got->cExtension,
5568      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5569      got->cExtension);
5570     for (i = 0; i < expected->cExtension; i++)
5571     {
5572         ok(!strcmp(expected->rgExtension[i].pszObjId,
5573          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5574          header, i, expected->rgExtension[i].pszObjId,
5575          got->rgExtension[i].pszObjId);
5576         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5577          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5578          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5579         ok(expected->rgExtension[i].Value.cbData ==
5580          got->rgExtension[i].Value.cbData,
5581          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5582          header, i, expected->rgExtension[i].Value.cbData,
5583          got->rgExtension[i].Value.cbData);
5584         if (expected->rgExtension[i].Value.cbData)
5585             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5586              got->rgExtension[i].Value.pbData,
5587              expected->rgExtension[i].Value.cbData),
5588              "%s[%d]: unexpected extension value\n", header, i);
5589     }
5590 }
5591
5592 static const BYTE signedCTL[] = {
5593 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5594 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5595 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5596 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5597 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5598 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5599 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5600 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5601 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5602 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5603 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5604 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5605 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5606 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5607 static const BYTE signedCTLWithCTLInnerContent[] = {
5608 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5609 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5610 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5611 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5612 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5613 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5614 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5615 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5616 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5617 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5618 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5619 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5620 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5621 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5622 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5623 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5624 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5625 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5626 0x57,0x6c,0x0b,0x47,0xb8 };
5627
5628 static void test_decodeCTL(DWORD dwEncoding)
5629 {
5630     static char oid1[] = "1.2.3";
5631     static char oid2[] = "1.5.6";
5632     static BYTE nullData[] = { 5,0 };
5633     char *pOid1 = oid1;
5634     BOOL ret;
5635     BYTE *buf = NULL;
5636     DWORD size = 0;
5637     CTL_INFO info;
5638     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5639     CTL_ENTRY ctlEntry[2];
5640     CRYPT_ATTRIBUTE attr1, attr2;
5641     CRYPT_ATTR_BLOB value1, value2;
5642
5643     memset(&info, 0, sizeof(info));
5644     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5645      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5646     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5647     if (buf)
5648     {
5649         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5650         LocalFree(buf);
5651         buf = NULL;
5652     }
5653     info.dwVersion = 1;
5654     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5655      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5656      &size);
5657     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5658     if (buf)
5659     {
5660         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5661         LocalFree(buf);
5662         buf = NULL;
5663     }
5664     info.dwVersion = 0;
5665     info.SubjectUsage.cUsageIdentifier = 1;
5666     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5667     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5668      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5669      &buf, &size);
5670     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5671     if (buf)
5672     {
5673         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5674         LocalFree(buf);
5675         buf = NULL;
5676     }
5677     info.SubjectUsage.cUsageIdentifier = 0;
5678     info.ListIdentifier.cbData = sizeof(serialNum);
5679     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5680     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5681      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5682     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5683     if (buf)
5684     {
5685         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5686         LocalFree(buf);
5687         buf = NULL;
5688     }
5689     info.ListIdentifier.cbData = 0;
5690     info.SequenceNumber.cbData = sizeof(serialNum);
5691     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5692     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5693      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5694     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5695     if (buf)
5696     {
5697         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5698         LocalFree(buf);
5699         buf = NULL;
5700     }
5701     info.SequenceNumber.cbData = 0;
5702     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5703     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5704      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5705     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5706     if (buf)
5707     {
5708         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5709         LocalFree(buf);
5710         buf = NULL;
5711     }
5712     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5713     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5714      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5715      &buf, &size);
5716     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5717     if (buf)
5718     {
5719         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5720         LocalFree(buf);
5721         buf = NULL;
5722     }
5723     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5724     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5725     info.SubjectAlgorithm.pszObjId = oid2;
5726     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5727     info.SubjectAlgorithm.Parameters.pbData = nullData;
5728     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5729      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5730     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5731     if (buf)
5732     {
5733         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5734         LocalFree(buf);
5735         buf = NULL;
5736     }
5737     SetLastError(0xdeadbeef);
5738     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5739      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5740     ok(!ret &&
5741      (GetLastError() == CRYPT_E_ASN1_EOD ||
5742       GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5743       GetLastError() == OSS_MORE_INPUT), /* Win9x */
5744      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5745      GetLastError());
5746     info.SubjectAlgorithm.Parameters.cbData = 0;
5747     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5748     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5749     info.SubjectAlgorithm.pszObjId = oid2;
5750     info.SubjectAlgorithm.pszObjId = NULL;
5751     value1.cbData = sizeof(emptySequence);
5752     value1.pbData = (LPBYTE)emptySequence;
5753     attr1.pszObjId = oid1;
5754     attr1.cValue = 1;
5755     attr1.rgValue = &value1;
5756     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5757     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5758     ctlEntry[0].cAttribute = 1;
5759     ctlEntry[0].rgAttribute = &attr1;
5760     info.cCTLEntry = 1;
5761     info.rgCTLEntry = ctlEntry;
5762     SetLastError(0xdeadbeef);
5763     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5764      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5765     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5766     if (buf)
5767     {
5768         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5769         LocalFree(buf);
5770         buf = NULL;
5771     }
5772     value2.cbData = sizeof(encodedIPAddr);
5773     value2.pbData = (LPBYTE)encodedIPAddr;
5774     attr2.pszObjId = oid2;
5775     attr2.cValue = 1;
5776     attr2.rgValue = &value2;
5777     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5778     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5779     ctlEntry[1].cAttribute = 1;
5780     ctlEntry[1].rgAttribute = &attr2;
5781     info.cCTLEntry = 2;
5782     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5783      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5784     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5785     if (buf)
5786     {
5787         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5788         LocalFree(buf);
5789         buf = NULL;
5790     }
5791     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5792     SetLastError(0xdeadbeef);
5793     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5794      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5795     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5796      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5797      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5798      GetLastError());
5799     SetLastError(0xdeadbeef);
5800     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5801      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5802      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5803     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5804      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5805      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5806      GetLastError());
5807 }
5808
5809 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5810 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5811  0x03,0,0,0,0,0,0 };
5812 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5813  0xa0,0x01,0x01 };
5814 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5815  0x03,0x02,0x01,0x01 };
5816 static BYTE bogusDER[] = { 1 };
5817
5818 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5819 {
5820     BOOL ret;
5821     BYTE *buf = NULL;
5822     DWORD size = 0;
5823     CRYPT_CONTENT_INFO info = { 0 };
5824     char oid1[] = "1.2.3";
5825
5826     if (0)
5827     {
5828         /* Crashes on win9x */
5829         SetLastError(0xdeadbeef);
5830         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5831          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5832         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5833          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5834     }
5835     SetLastError(0xdeadbeef);
5836     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5837      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5838     ok(!ret && (GetLastError() == E_INVALIDARG ||
5839      GetLastError() == OSS_LIMITED /* Win9x */),
5840      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5841     info.pszObjId = oid1;
5842     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5843      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5844     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5845     if (buf)
5846     {
5847         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5848         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5849         LocalFree(buf);
5850     }
5851     info.Content.pbData = bogusDER;
5852     info.Content.cbData = sizeof(bogusDER);
5853     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5854      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5855     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5856     if (buf)
5857     {
5858         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5859         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5860         LocalFree(buf);
5861     }
5862     info.Content.pbData = (BYTE *)ints[0].encoded;
5863     info.Content.cbData = ints[0].encoded[1] + 2;
5864     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5865      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5866     if (buf)
5867     {
5868         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5869         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5870         LocalFree(buf);
5871     }
5872 }
5873
5874 static const BYTE indefiniteSignedPKCSContent[] = {
5875 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5876 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5877 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5878 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5879 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5880 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5881 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5882 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5883 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5884 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5885 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5886 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5887 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5888 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5889 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5890 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5891 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5892 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5893 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5894 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5895 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5896 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5897 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5898 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5899 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5900 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5901 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5902 0x00,0x00,0x00,0x00,0x00,0x00 };
5903
5904 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5905 {
5906     BOOL ret;
5907     LPBYTE buf = NULL;
5908     DWORD size = 0;
5909     CRYPT_CONTENT_INFO *info;
5910
5911     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5912      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5913      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5914     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5915     if (buf)
5916     {
5917         info = (CRYPT_CONTENT_INFO *)buf;
5918
5919         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5920          info->pszObjId);
5921         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5922          info->Content.cbData);
5923         LocalFree(buf);
5924     }
5925     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5926      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5927      0, NULL, NULL, &size);
5928     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5929     SetLastError(0xdeadbeef);
5930     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5931      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5932      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5933     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5934      * I doubt an app depends on that.
5935      */
5936     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5937      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5938      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5939      GetLastError());
5940     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5941      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5942      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5943     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5944     if (buf)
5945     {
5946         info = (CRYPT_CONTENT_INFO *)buf;
5947
5948         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5949          info->pszObjId);
5950         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5951          "Unexpected size %d\n", info->Content.cbData);
5952         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5953          info->Content.cbData), "Unexpected value\n");
5954         LocalFree(buf);
5955     }
5956     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5957      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5958      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5959     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5960     if (buf)
5961     {
5962         info = (CRYPT_CONTENT_INFO *)buf;
5963
5964         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5965          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5966         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5967          info->Content.cbData);
5968         LocalFree(buf);
5969     }
5970 }
5971
5972 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5973  0x00 };
5974 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5975  0x01 };
5976 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5977  0x02,0x01,0x01 };
5978
5979 static void test_encodePKCSAttribute(DWORD dwEncoding)
5980 {
5981     CRYPT_ATTRIBUTE attr = { 0 };
5982     BOOL ret;
5983     LPBYTE buf = NULL;
5984     DWORD size = 0;
5985     CRYPT_ATTR_BLOB blob;
5986     char oid[] = "1.2.3";
5987
5988     if (0)
5989     {
5990         /* Crashes on win9x */
5991         SetLastError(0xdeadbeef);
5992         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5993          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5994         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5995          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5996     }
5997     SetLastError(0xdeadbeef);
5998     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5999      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6000     ok(!ret && (GetLastError() == E_INVALIDARG ||
6001      GetLastError() == OSS_LIMITED /* Win9x */),
6002      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
6003     attr.pszObjId = oid;
6004     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6005      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6006     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6007     if (buf)
6008     {
6009         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
6010         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
6011         LocalFree(buf);
6012     }
6013     blob.cbData = sizeof(bogusDER);
6014     blob.pbData = bogusDER;
6015     attr.cValue = 1;
6016     attr.rgValue = &blob;
6017     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6018      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6019     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6020     if (buf)
6021     {
6022         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
6023         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
6024         LocalFree(buf);
6025     }
6026     blob.pbData = (BYTE *)ints[0].encoded;
6027     blob.cbData = ints[0].encoded[1] + 2;
6028     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6029      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6030     if (buf)
6031     {
6032         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6033         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6034         LocalFree(buf);
6035     }
6036 }
6037
6038 static void test_decodePKCSAttribute(DWORD dwEncoding)
6039 {
6040     BOOL ret;
6041     LPBYTE buf = NULL;
6042     DWORD size = 0;
6043     CRYPT_ATTRIBUTE *attr;
6044
6045     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6046      emptyPKCSAttr, sizeof(emptyPKCSAttr),
6047      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6048     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6049     if (buf)
6050     {
6051         attr = (CRYPT_ATTRIBUTE *)buf;
6052
6053         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6054          attr->pszObjId);
6055         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6056         LocalFree(buf);
6057     }
6058     SetLastError(0xdeadbeef);
6059     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6060      bogusPKCSAttr, sizeof(bogusPKCSAttr),
6061      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6062     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6063      * I doubt an app depends on that.
6064      */
6065     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6066      GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6067      GetLastError() == OSS_MORE_INPUT /* Win9x */),
6068      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6069      GetLastError());
6070     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6071      intPKCSAttr, sizeof(intPKCSAttr),
6072      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6073     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6074     if (buf)
6075     {
6076         attr = (CRYPT_ATTRIBUTE *)buf;
6077
6078         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6079          attr->pszObjId);
6080         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6081         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6082          "Unexpected size %d\n", attr->rgValue[0].cbData);
6083         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6084          attr->rgValue[0].cbData), "Unexpected value\n");
6085         LocalFree(buf);
6086     }
6087 }
6088
6089 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6090 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6091  0x2a,0x03,0x31,0x00 };
6092 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6093  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6094
6095 static void test_encodePKCSAttributes(DWORD dwEncoding)
6096 {
6097     CRYPT_ATTRIBUTES attributes = { 0 };
6098     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6099     CRYPT_ATTR_BLOB blob;
6100     BOOL ret;
6101     LPBYTE buf = NULL;
6102     DWORD size = 0;
6103     char oid1[] = "1.2.3", oid2[] = "1.5.6";
6104
6105     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6106      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6107     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6108     if (buf)
6109     {
6110         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6111         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6112         LocalFree(buf);
6113     }
6114     attributes.cAttr = 1;
6115     attributes.rgAttr = attr;
6116     SetLastError(0xdeadbeef);
6117     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6118      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6119     ok(!ret && (GetLastError() == E_INVALIDARG ||
6120      GetLastError() == OSS_LIMITED /* Win9x */),
6121      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6122     attr[0].pszObjId = oid1;
6123     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6124      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6125     if (buf)
6126     {
6127         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6128         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6129         LocalFree(buf);
6130     }
6131     attr[1].pszObjId = oid2;
6132     attr[1].cValue = 1;
6133     attr[1].rgValue = &blob;
6134     blob.pbData = (BYTE *)ints[0].encoded;
6135     blob.cbData = ints[0].encoded[1] + 2;
6136     attributes.cAttr = 2;
6137     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6138      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6139     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6140     if (buf)
6141     {
6142         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6143         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6144         LocalFree(buf);
6145     }
6146 }
6147
6148 static void test_decodePKCSAttributes(DWORD dwEncoding)
6149 {
6150     BOOL ret;
6151     LPBYTE buf = NULL;
6152     DWORD size = 0;
6153     CRYPT_ATTRIBUTES *attributes;
6154
6155     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6156      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6157      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6158     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6159     if (buf)
6160     {
6161         attributes = (CRYPT_ATTRIBUTES *)buf;
6162         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6163          attributes->cAttr);
6164         LocalFree(buf);
6165     }
6166     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6167      singlePKCSAttributes, sizeof(singlePKCSAttributes),
6168      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6169     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6170     if (buf)
6171     {
6172         attributes = (CRYPT_ATTRIBUTES *)buf;
6173         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6174          attributes->cAttr);
6175         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6176          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6177         ok(attributes->rgAttr[0].cValue == 0,
6178          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6179         LocalFree(buf);
6180     }
6181     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6182      doublePKCSAttributes, sizeof(doublePKCSAttributes),
6183      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6184     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6185     if (buf)
6186     {
6187         attributes = (CRYPT_ATTRIBUTES *)buf;
6188         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6189          attributes->cAttr);
6190         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6191          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6192         ok(attributes->rgAttr[0].cValue == 0,
6193          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6194         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6195          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6196         ok(attributes->rgAttr[1].cValue == 1,
6197          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6198         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6199          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6200         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6201          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6202         LocalFree(buf);
6203     }
6204 }
6205
6206 static const BYTE singleCapability[] = {
6207 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6208 static const BYTE twoCapabilities[] = {
6209 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6210 static const BYTE singleCapabilitywithNULL[] = {
6211 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6212
6213 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6214 {
6215     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6216     BOOL ret;
6217     LPBYTE buf = NULL;
6218     DWORD size = 0;
6219     CRYPT_SMIME_CAPABILITY capability[2];
6220     CRYPT_SMIME_CAPABILITIES capabilities;
6221
6222     /* An empty capabilities is allowed */
6223     capabilities.cCapability = 0;
6224     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6225      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6226     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6227     if (buf)
6228     {
6229         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6230         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6231         LocalFree(buf);
6232     }
6233     /* A non-empty capabilities with an empty capability (lacking an OID) is
6234      * not allowed
6235      */
6236     capability[0].pszObjId = NULL;
6237     capability[0].Parameters.cbData = 0;
6238     capabilities.cCapability = 1;
6239     capabilities.rgCapability = capability;
6240     SetLastError(0xdeadbeef);
6241     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6242      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6243     ok(!ret && (GetLastError() == E_INVALIDARG ||
6244      GetLastError() == OSS_LIMITED /* Win9x */),
6245      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6246     capability[0].pszObjId = oid1;
6247     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6248      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6249     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6250     if (buf)
6251     {
6252         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6253         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6254         LocalFree(buf);
6255     }
6256     capability[1].pszObjId = oid2;
6257     capability[1].Parameters.cbData = 0;
6258     capabilities.cCapability = 2;
6259     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6260      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6261     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6262     if (buf)
6263     {
6264         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6265         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6266         LocalFree(buf);
6267     }
6268 }
6269
6270 static void compareSMimeCapabilities(LPCSTR header,
6271  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6272 {
6273     DWORD i;
6274
6275     ok(got->cCapability == expected->cCapability,
6276      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6277      got->cCapability);
6278     for (i = 0; i < expected->cCapability; i++)
6279     {
6280         ok(!strcmp(expected->rgCapability[i].pszObjId,
6281          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6282          header, i, expected->rgCapability[i].pszObjId,
6283          got->rgCapability[i].pszObjId);
6284         ok(expected->rgCapability[i].Parameters.cbData ==
6285          got->rgCapability[i].Parameters.cbData,
6286          "%s[%d]: expected %d bytes, got %d\n", header, i,
6287          expected->rgCapability[i].Parameters.cbData,
6288          got->rgCapability[i].Parameters.cbData);
6289         if (expected->rgCapability[i].Parameters.cbData)
6290             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6291              got->rgCapability[i].Parameters.pbData,
6292              expected->rgCapability[i].Parameters.cbData),
6293              "%s[%d]: unexpected value\n", header, i);
6294     }
6295 }
6296
6297 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6298 {
6299     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6300     BOOL ret;
6301     DWORD size = 0;
6302     CRYPT_SMIME_CAPABILITY capability[2];
6303     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6304
6305     SetLastError(0xdeadbeef);
6306     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6307      emptySequence, sizeof(emptySequence),
6308      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6309     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6310     if (ret)
6311     {
6312         capabilities.cCapability = 0;
6313         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6314         LocalFree(ptr);
6315     }
6316     SetLastError(0xdeadbeef);
6317     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6318      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6319      &ptr, &size);
6320     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6321     if (ret)
6322     {
6323         capability[0].pszObjId = oid1;
6324         capability[0].Parameters.cbData = 0;
6325         capabilities.cCapability = 1;
6326         capabilities.rgCapability = capability;
6327         compareSMimeCapabilities("single capability", &capabilities, ptr);
6328         LocalFree(ptr);
6329     }
6330     SetLastError(0xdeadbeef);
6331     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6332      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6333      CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6334     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6335     if (ret)
6336     {
6337         BYTE NULLparam[] = {0x05, 0x00};
6338         capability[0].pszObjId = oid1;
6339         capability[0].Parameters.cbData = 2;
6340         capability[0].Parameters.pbData = NULLparam;
6341         capabilities.cCapability = 1;
6342         capabilities.rgCapability = capability;
6343         compareSMimeCapabilities("single capability with NULL", &capabilities,
6344          ptr);
6345         LocalFree(ptr);
6346     }
6347     SetLastError(0xdeadbeef);
6348     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6349     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6350     &ptr, &size);
6351     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6352     if (ret)
6353     {
6354         capability[0].Parameters.cbData = 0;
6355         capability[1].pszObjId = oid2;
6356         capability[1].Parameters.cbData = 0;
6357         capabilities.cCapability = 2;
6358         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6359         LocalFree(ptr);
6360     }
6361 }
6362
6363 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6364  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6365  0x67 };
6366 static const BYTE minimalPKCSSigner[] = {
6367  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6368  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6369  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6370 static const BYTE PKCSSignerWithSerial[] = {
6371  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6372  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6373  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6374  0x00 };
6375 static const BYTE PKCSSignerWithHashAlgo[] = {
6376  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6377  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6378  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6379  0x00,0x04,0x00 };
6380 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6381  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6382  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6383  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6384  0x06,0x05,0x00,0x04,0x00 };
6385 static const BYTE PKCSSignerWithHash[] = {
6386  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6387  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6388  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6389  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6390  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6391 static const BYTE PKCSSignerWithAuthAttr[] = {
6392 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6393 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6394 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6395 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6396 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6397 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6398 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6399
6400 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6401 {
6402     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6403     BOOL ret;
6404     LPBYTE buf = NULL;
6405     DWORD size = 0;
6406     CMSG_SIGNER_INFO info = { 0 };
6407     char oid_common_name[] = szOID_COMMON_NAME;
6408     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6409      (LPBYTE)encodedCommonName };
6410     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6411
6412     SetLastError(0xdeadbeef);
6413     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6414      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6415     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6416     {
6417         skip("no PKCS7_SIGNER_INFO encode support\n");
6418         return;
6419     }
6420     ok(!ret && (GetLastError() == E_INVALIDARG ||
6421      GetLastError() == OSS_LIMITED /* Win9x */),
6422      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6423     /* To be encoded, a signer must have an issuer at least, and the encoding
6424      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6425      * see decoding tests.)
6426      */
6427     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6428     info.Issuer.pbData = encodedCommonNameNoNull;
6429     SetLastError(0xdeadbeef);
6430     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6431      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6432     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6433         ok(!ret && GetLastError() == E_INVALIDARG,
6434          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6435     else
6436     {
6437         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6438          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6439         if (buf)
6440         {
6441             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6442             if (size == sizeof(minimalPKCSSigner))
6443                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6444             else
6445                 ok(0, "Unexpected value\n");
6446             LocalFree(buf);
6447         }
6448     }
6449     info.SerialNumber.cbData = sizeof(serialNum);
6450     info.SerialNumber.pbData = (BYTE *)serialNum;
6451     SetLastError(0xdeadbeef);
6452     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6453      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6454     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6455         ok(!ret && GetLastError() == E_INVALIDARG,
6456          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6457     else
6458     {
6459         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6460          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6461         if (buf)
6462         {
6463             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6464              size);
6465             if (size == sizeof(PKCSSignerWithSerial))
6466                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6467                  "Unexpected value\n");
6468             else
6469                 ok(0, "Unexpected value\n");
6470             LocalFree(buf);
6471         }
6472     }
6473     info.HashAlgorithm.pszObjId = oid1;
6474     SetLastError(0xdeadbeef);
6475     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6476      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6477     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6478         ok(!ret && GetLastError() == E_INVALIDARG,
6479          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6480     else
6481     {
6482         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6483          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6484         if (buf)
6485         {
6486             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6487              size);
6488             if (size == sizeof(PKCSSignerWithHashAlgo))
6489                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6490                  "Unexpected value\n");
6491             else
6492                 ok(0, "Unexpected value\n");
6493             LocalFree(buf);
6494         }
6495     }
6496     info.HashEncryptionAlgorithm.pszObjId = oid2;
6497     SetLastError(0xdeadbeef);
6498     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6499      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6500     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6501         ok(!ret && GetLastError() == E_INVALIDARG,
6502          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6503     else
6504     {
6505         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6506         if (buf)
6507         {
6508             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6509              "Unexpected size %d\n", size);
6510             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6511                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6512                  "Unexpected value\n");
6513             else
6514                 ok(0, "Unexpected value\n");
6515             LocalFree(buf);
6516         }
6517     }
6518     info.EncryptedHash.cbData = sizeof(hash);
6519     info.EncryptedHash.pbData = (BYTE *)hash;
6520     SetLastError(0xdeadbeef);
6521     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6522      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6523     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6524         ok(!ret && GetLastError() == E_INVALIDARG,
6525          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6526     else
6527     {
6528         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6529         if (buf)
6530         {
6531             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6532              size);
6533             if (size == sizeof(PKCSSignerWithHash))
6534                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6535                  "Unexpected value\n");
6536             else
6537                 ok(0, "Unexpected value\n");
6538             LocalFree(buf);
6539         }
6540     }
6541     info.AuthAttrs.cAttr = 1;
6542     info.AuthAttrs.rgAttr = &attr;
6543     SetLastError(0xdeadbeef);
6544     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6545      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6546     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6547         ok(!ret && GetLastError() == E_INVALIDARG,
6548          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6549     else
6550     {
6551         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6552         if (buf)
6553         {
6554             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6555              size);
6556             if (size == sizeof(PKCSSignerWithAuthAttr))
6557                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6558                  "Unexpected value\n");
6559             else
6560                 ok(0, "Unexpected value\n");
6561             LocalFree(buf);
6562         }
6563     }
6564 }
6565
6566 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6567 {
6568     BOOL ret;
6569     LPBYTE buf = NULL;
6570     DWORD size = 0;
6571     CMSG_SIGNER_INFO *info;
6572
6573     /* A PKCS signer can't be decoded without a serial number. */
6574     SetLastError(0xdeadbeef);
6575     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6576      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6577      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6578     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6579      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6580      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6581      GetLastError());
6582     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6583      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6584      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6585     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6586      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6587     if (buf)
6588     {
6589         info = (CMSG_SIGNER_INFO *)buf;
6590         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6591          info->dwVersion);
6592         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6593          "Unexpected size %d\n", info->Issuer.cbData);
6594         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6595          info->Issuer.cbData), "Unexpected value\n");
6596         ok(info->SerialNumber.cbData == sizeof(serialNum),
6597          "Unexpected size %d\n", info->SerialNumber.cbData);
6598         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6599          "Unexpected value\n");
6600         LocalFree(buf);
6601     }
6602     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6603      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6604      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6605     if (buf)
6606     {
6607         info = (CMSG_SIGNER_INFO *)buf;
6608         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6609          info->dwVersion);
6610         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6611          "Unexpected size %d\n", info->Issuer.cbData);
6612         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6613          info->Issuer.cbData), "Unexpected value\n");
6614         ok(info->SerialNumber.cbData == sizeof(serialNum),
6615          "Unexpected size %d\n", info->SerialNumber.cbData);
6616         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6617          "Unexpected value\n");
6618         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6619          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6620         LocalFree(buf);
6621     }
6622     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6623      PKCSSignerWithHashAndEncryptionAlgo,
6624      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6625      NULL, &buf, &size);
6626     if (buf)
6627     {
6628         info = (CMSG_SIGNER_INFO *)buf;
6629         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6630          info->dwVersion);
6631         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6632          "Unexpected size %d\n", info->Issuer.cbData);
6633         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6634          info->Issuer.cbData), "Unexpected value\n");
6635         ok(info->SerialNumber.cbData == sizeof(serialNum),
6636          "Unexpected size %d\n", info->SerialNumber.cbData);
6637         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6638          "Unexpected value\n");
6639         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6640          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6641         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6642          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6643         LocalFree(buf);
6644     }
6645     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6646      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6647      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6648     if (buf)
6649     {
6650         info = (CMSG_SIGNER_INFO *)buf;
6651         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6652          info->dwVersion);
6653         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6654          "Unexpected size %d\n", info->Issuer.cbData);
6655         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6656          info->Issuer.cbData), "Unexpected value\n");
6657         ok(info->SerialNumber.cbData == sizeof(serialNum),
6658          "Unexpected size %d\n", info->SerialNumber.cbData);
6659         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6660          "Unexpected value\n");
6661         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6662          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6663         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6664          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6665         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6666          info->EncryptedHash.cbData);
6667         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6668          "Unexpected value\n");
6669         LocalFree(buf);
6670     }
6671     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6672      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6673      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6674     if (buf)
6675     {
6676         info = (CMSG_SIGNER_INFO *)buf;
6677         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6678          info->AuthAttrs.cAttr);
6679         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6680          "Expected %s, got %s\n", szOID_COMMON_NAME,
6681          info->AuthAttrs.rgAttr[0].pszObjId);
6682         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6683          info->AuthAttrs.rgAttr[0].cValue);
6684         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6685          sizeof(encodedCommonName), "Unexpected size %d\n",
6686          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6687         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6688          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6689         LocalFree(buf);
6690     }
6691 }
6692
6693 static const BYTE CMSSignerWithKeyId[] = {
6694 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6695 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6696
6697 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6698 {
6699     BOOL ret;
6700     LPBYTE buf = NULL;
6701     DWORD size = 0;
6702     CMSG_CMS_SIGNER_INFO info = { 0 };
6703     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6704
6705     SetLastError(0xdeadbeef);
6706     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6707      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6708     ok(!ret, "Expected failure, got %d\n", ret);
6709     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6710     {
6711         skip("no CMS_SIGNER_INFO encode support\n");
6712         return;
6713     }
6714     ok(GetLastError() == E_INVALIDARG,
6715        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6716     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6717     SetLastError(0xdeadbeef);
6718     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6719      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6720     ok(!ret, "Expected failure, got %d\n", ret);
6721     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6722     {
6723         skip("no CMS_SIGNER_INFO encode support\n");
6724         return;
6725     }
6726     ok(GetLastError() == E_INVALIDARG,
6727        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6728     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6729      * be a key id or a issuer serial number with at least the issuer set, and
6730      * the encoding must include PKCS_7_ASN_ENCODING.
6731      * (That isn't enough to be decoded, see decoding tests.)
6732      */
6733     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6734      sizeof(encodedCommonNameNoNull);
6735     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6736     SetLastError(0xdeadbeef);
6737     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6738      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6739     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6740         ok(!ret && GetLastError() == E_INVALIDARG,
6741          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6742     else
6743     {
6744         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6745         if (buf)
6746         {
6747             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6748             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6749             LocalFree(buf);
6750         }
6751     }
6752     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6753     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6754     SetLastError(0xdeadbeef);
6755     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6756      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6757     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6758         ok(!ret && GetLastError() == E_INVALIDARG,
6759          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6760     else
6761     {
6762         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6763         if (buf)
6764         {
6765             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6766              size);
6767             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6768             LocalFree(buf);
6769         }
6770     }
6771     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6772     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6773     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6774     SetLastError(0xdeadbeef);
6775     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6776      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6777     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6778         ok(!ret && GetLastError() == E_INVALIDARG,
6779          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6780     else
6781     {
6782         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6783         if (buf)
6784         {
6785             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6786              size);
6787             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6788             LocalFree(buf);
6789         }
6790     }
6791     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6792      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6793      * (see RFC 3852, section 5.3.)
6794      */
6795     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6796     U(info.SignerId).HashId.cbData = sizeof(hash);
6797     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6798     SetLastError(0xdeadbeef);
6799     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6800      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6801     ok(!ret && GetLastError() == E_INVALIDARG,
6802      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6803     /* Now with a hash algo */
6804     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6805     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6806      sizeof(encodedCommonNameNoNull);
6807     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6808     info.HashAlgorithm.pszObjId = oid1;
6809     SetLastError(0xdeadbeef);
6810     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6811      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6812     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6813         ok(!ret && GetLastError() == E_INVALIDARG,
6814          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6815     else
6816     {
6817         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6818         if (buf)
6819         {
6820             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6821              size);
6822             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6823              "Unexpected value\n");
6824             LocalFree(buf);
6825         }
6826     }
6827     info.HashEncryptionAlgorithm.pszObjId = oid2;
6828     SetLastError(0xdeadbeef);
6829     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6830      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6831     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6832         ok(!ret && GetLastError() == E_INVALIDARG,
6833          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6834     else
6835     {
6836         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6837         if (buf)
6838         {
6839             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6840              "Unexpected size %d\n", size);
6841             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6842              "Unexpected value\n");
6843             LocalFree(buf);
6844         }
6845     }
6846     info.EncryptedHash.cbData = sizeof(hash);
6847     info.EncryptedHash.pbData = (BYTE *)hash;
6848     SetLastError(0xdeadbeef);
6849     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6850      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6851     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6852         ok(!ret && GetLastError() == E_INVALIDARG,
6853          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6854     else
6855     {
6856         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6857         if (buf)
6858         {
6859             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6860              size);
6861             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6862             LocalFree(buf);
6863         }
6864     }
6865 }
6866
6867 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6868 {
6869     BOOL ret;
6870     LPBYTE buf = NULL;
6871     DWORD size = 0;
6872     CMSG_CMS_SIGNER_INFO *info;
6873     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6874
6875     /* A CMS signer can't be decoded without a serial number. */
6876     SetLastError(0xdeadbeef);
6877     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6878      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6879      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6880     ok(!ret, "expected failure\n");
6881     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6882     {
6883         skip("no CMS_SIGNER_INFO decode support\n");
6884         return;
6885     }
6886     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6887      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6888     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6889      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6890      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6891     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6892     if (buf)
6893     {
6894         info = (CMSG_CMS_SIGNER_INFO *)buf;
6895         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6896          info->dwVersion);
6897         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6898          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6899          info->SignerId.dwIdChoice);
6900         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6901          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6902          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6903         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6904          encodedCommonNameNoNull,
6905          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6906          "Unexpected value\n");
6907         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6908          sizeof(serialNum), "Unexpected size %d\n",
6909          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6910         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6911          serialNum, sizeof(serialNum)), "Unexpected value\n");
6912         LocalFree(buf);
6913     }
6914     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6915      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6916      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6917     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6918     if (buf)
6919     {
6920         info = (CMSG_CMS_SIGNER_INFO *)buf;
6921         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6922          info->dwVersion);
6923         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6924          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6925          info->SignerId.dwIdChoice);
6926         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6927          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6928          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6929         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6930          encodedCommonNameNoNull,
6931          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6932          "Unexpected value\n");
6933         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6934          sizeof(serialNum), "Unexpected size %d\n",
6935          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6936         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6937          serialNum, sizeof(serialNum)), "Unexpected value\n");
6938         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6939          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6940         LocalFree(buf);
6941     }
6942     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6943      PKCSSignerWithHashAndEncryptionAlgo,
6944      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6945      NULL, &buf, &size);
6946     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6947     if (buf)
6948     {
6949         info = (CMSG_CMS_SIGNER_INFO *)buf;
6950         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6951          info->dwVersion);
6952         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6953          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6954          info->SignerId.dwIdChoice);
6955         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6956          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6957          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6958         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6959          encodedCommonNameNoNull,
6960          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6961          "Unexpected value\n");
6962         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6963          sizeof(serialNum), "Unexpected size %d\n",
6964          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6965         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6966          serialNum, sizeof(serialNum)), "Unexpected value\n");
6967         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6968          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6969         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6970          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6971         LocalFree(buf);
6972     }
6973     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6974      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6975      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6976     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6977     if (buf)
6978     {
6979         info = (CMSG_CMS_SIGNER_INFO *)buf;
6980         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6981          info->dwVersion);
6982         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6983          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6984          info->SignerId.dwIdChoice);
6985         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6986          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6987          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6988         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6989          encodedCommonNameNoNull,
6990          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6991          "Unexpected value\n");
6992         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6993          sizeof(serialNum), "Unexpected size %d\n",
6994          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6995         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6996          serialNum, sizeof(serialNum)), "Unexpected value\n");
6997         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6998          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6999         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7000          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7001         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
7002          info->EncryptedHash.cbData);
7003         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
7004          "Unexpected value\n");
7005         LocalFree(buf);
7006     }
7007     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7008      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
7009      CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7010     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7011     if (buf)
7012     {
7013         info = (CMSG_CMS_SIGNER_INFO *)buf;
7014         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7015          info->dwVersion);
7016         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
7017          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
7018          info->SignerId.dwIdChoice);
7019         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
7020          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
7021         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
7022          "Unexpected value\n");
7023         LocalFree(buf);
7024     }
7025 }
7026
7027 static BYTE emptyDNSPermittedConstraints[] = {
7028 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
7029 static BYTE emptyDNSExcludedConstraints[] = {
7030 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
7031 static BYTE DNSExcludedConstraints[] = {
7032 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7033 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7034 static BYTE permittedAndExcludedConstraints[] = {
7035 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7036 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7037 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7038 static BYTE permittedAndExcludedWithMinConstraints[] = {
7039 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7040 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7041 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7042 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7043 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7044 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7045 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7046
7047 static void test_encodeNameConstraints(DWORD dwEncoding)
7048 {
7049     BOOL ret;
7050     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7051     CERT_GENERAL_SUBTREE permitted = { { 0 } };
7052     CERT_GENERAL_SUBTREE excluded = { { 0 } };
7053     LPBYTE buf;
7054     DWORD size;
7055
7056     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7057      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7058     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7059     {
7060         skip("no X509_NAME_CONSTRAINTS encode support\n");
7061         return;
7062     }
7063     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7064     if (ret)
7065     {
7066         ok(size == sizeof(emptySequence), "Unexpected size\n");
7067         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7068         LocalFree(buf);
7069     }
7070     constraints.cPermittedSubtree = 1;
7071     constraints.rgPermittedSubtree = &permitted;
7072     SetLastError(0xdeadbeef);
7073     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7074      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7075     ok(!ret && GetLastError() == E_INVALIDARG,
7076      "Expected E_INVALIDARG, got %08x\n", GetLastError());
7077     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7078     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7079      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7080     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7081     if (ret)
7082     {
7083         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7084         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7085          "Unexpected value\n");
7086         LocalFree(buf);
7087     }
7088     constraints.cPermittedSubtree = 0;
7089     constraints.cExcludedSubtree = 1;
7090     constraints.rgExcludedSubtree = &excluded;
7091     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7092     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7093      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7094     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7095     if (ret)
7096     {
7097         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7098         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7099          "Unexpected value\n");
7100         LocalFree(buf);
7101     }
7102     U(excluded.Base).pwszURL = (LPWSTR)url;
7103     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7104      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7105     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7106     if (ret)
7107     {
7108         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7109         ok(!memcmp(buf, DNSExcludedConstraints, size),
7110          "Unexpected value\n");
7111         LocalFree(buf);
7112     }
7113     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7114     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7115     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7116     constraints.cPermittedSubtree = 1;
7117     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7118      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7119     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7120     if (ret)
7121     {
7122         ok(size == sizeof(permittedAndExcludedConstraints),
7123          "Unexpected size\n");
7124         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7125          "Unexpected value\n");
7126         LocalFree(buf);
7127     }
7128     permitted.dwMinimum = 5;
7129     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7130      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7131     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7132     if (ret)
7133     {
7134         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7135          "Unexpected size\n");
7136         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7137          "Unexpected value\n");
7138         LocalFree(buf);
7139     }
7140     permitted.fMaximum = TRUE;
7141     permitted.dwMaximum = 3;
7142     SetLastError(0xdeadbeef);
7143     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7144      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7145     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7146     if (ret)
7147     {
7148         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7149          "Unexpected size\n");
7150         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7151          "Unexpected value\n");
7152         LocalFree(buf);
7153     }
7154 }
7155
7156 struct EncodedNameConstraints
7157 {
7158     CRYPT_DATA_BLOB            encoded;
7159     CERT_NAME_CONSTRAINTS_INFO constraints;
7160 };
7161
7162 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7163  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7164 static CERT_GENERAL_SUBTREE DNSSubtree = {
7165  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7166 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7167  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7168 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7169  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7170 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7171  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7172
7173 struct EncodedNameConstraints encodedNameConstraints[] = {
7174  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7175  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7176    { 1, &emptyDNSSubtree, 0, NULL } },
7177  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7178    { 0, NULL, 1, &emptyDNSSubtree } },
7179  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7180    { 0, NULL, 1, &DNSSubtree } },
7181  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7182    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7183  { { sizeof(permittedAndExcludedWithMinConstraints),
7184      permittedAndExcludedWithMinConstraints },
7185    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7186  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7187      permittedAndExcludedWithMinMaxConstraints },
7188    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7189 };
7190
7191 static void test_decodeNameConstraints(DWORD dwEncoding)
7192 {
7193     BOOL ret;
7194     DWORD i;
7195     CERT_NAME_CONSTRAINTS_INFO *constraints;
7196
7197     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7198     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7199     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7200     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7201     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7202     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7203     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7204     for (i = 0;
7205      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7206      i++)
7207     {
7208         DWORD size;
7209
7210         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7211          encodedNameConstraints[i].encoded.pbData,
7212          encodedNameConstraints[i].encoded.cbData,
7213          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7214         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7215         {
7216             skip("no X509_NAME_CONSTRAINTS decode support\n");
7217             return;
7218         }
7219         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7220         if (ret)
7221         {
7222             DWORD j;
7223
7224             if (constraints->cPermittedSubtree !=
7225              encodedNameConstraints[i].constraints.cPermittedSubtree)
7226                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7227                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7228                  constraints->cPermittedSubtree);
7229             if (constraints->cPermittedSubtree ==
7230              encodedNameConstraints[i].constraints.cPermittedSubtree)
7231             {
7232                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7233                 {
7234                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7235                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7236                 }
7237             }
7238             if (constraints->cExcludedSubtree !=
7239              encodedNameConstraints[i].constraints.cExcludedSubtree)
7240                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7241                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7242                  constraints->cExcludedSubtree);
7243             if (constraints->cExcludedSubtree ==
7244              encodedNameConstraints[i].constraints.cExcludedSubtree)
7245             {
7246                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7247                 {
7248                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7249                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7250                 }
7251             }
7252             LocalFree(constraints);
7253         }
7254     }
7255 }
7256
7257 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7258  'n','o','t','i','c','e',0 };
7259 static const BYTE noticeWithDisplayText[] = {
7260  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7261  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7262  0x00,0x69,0x00,0x63,0x00,0x65
7263 };
7264 static char org[] = "Wine";
7265 static int noticeNumbers[] = { 2,3 };
7266 static BYTE noticeWithReference[] = {
7267  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7268  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7269  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7270  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7271 };
7272
7273 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7274 {
7275     BOOL ret;
7276     LPBYTE buf;
7277     DWORD size;
7278     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7279     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7280
7281     memset(&notice, 0, sizeof(notice));
7282     ret = pCryptEncodeObjectEx(dwEncoding,
7283      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7284      NULL, &buf, &size);
7285     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7286     {
7287         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7288         return;
7289     }
7290     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7291     if (ret)
7292     {
7293         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7294         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7295         LocalFree(buf);
7296     }
7297     notice.pszDisplayText = noticeText;
7298     ret = pCryptEncodeObjectEx(dwEncoding,
7299      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7300      NULL, &buf, &size);
7301     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7302     if (ret)
7303     {
7304         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7305         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7306         LocalFree(buf);
7307     }
7308     reference.pszOrganization = org;
7309     reference.cNoticeNumbers = 2;
7310     reference.rgNoticeNumbers = noticeNumbers;
7311     notice.pNoticeReference = &reference;
7312     ret = pCryptEncodeObjectEx(dwEncoding,
7313      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7314      NULL, &buf, &size);
7315     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7316     if (ret)
7317     {
7318         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7319         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7320         LocalFree(buf);
7321     }
7322 }
7323
7324 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7325 {
7326     BOOL ret;
7327     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7328     DWORD size;
7329
7330     ret = pCryptDecodeObjectEx(dwEncoding,
7331      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7332      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7333      &notice, &size);
7334     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7335     {
7336         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7337         return;
7338     }
7339     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7340     if (ret)
7341     {
7342         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7343         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7344         LocalFree(notice);
7345     }
7346     ret = pCryptDecodeObjectEx(dwEncoding,
7347      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7348      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7349      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7350     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7351     if (ret)
7352     {
7353         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7354          "unexpected display text\n");
7355         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7356         LocalFree(notice);
7357     }
7358     ret = pCryptDecodeObjectEx(dwEncoding,
7359      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7360      noticeWithReference, sizeof(noticeWithReference),
7361      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7362     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7363     if (ret)
7364     {
7365         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7366          "unexpected display text\n");
7367         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7368         if (notice->pNoticeReference)
7369         {
7370             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7371              "unexpected organization %s\n",
7372              notice->pNoticeReference->pszOrganization);
7373             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7374              "expected 2 notice numbers, got %d\n",
7375              notice->pNoticeReference->cNoticeNumbers);
7376             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7377              "unexpected notice number %d\n",
7378              notice->pNoticeReference->rgNoticeNumbers[0]);
7379             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7380              "unexpected notice number %d\n",
7381              notice->pNoticeReference->rgNoticeNumbers[1]);
7382         }
7383         LocalFree(notice);
7384     }
7385 }
7386
7387 static char oid_any_policy[] = "2.5.29.32.0";
7388 static const BYTE policiesWithAnyPolicy[] = {
7389  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7390 };
7391 static char oid1[] = "1.2.3";
7392 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7393 static const BYTE twoPolicies[] = {
7394  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7395  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7396  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7397  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7398  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7399  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7400 };
7401
7402 static void test_encodeCertPolicies(DWORD dwEncoding)
7403 {
7404     BOOL ret;
7405     CERT_POLICIES_INFO info;
7406     CERT_POLICY_INFO policy[2];
7407     CERT_POLICY_QUALIFIER_INFO qualifier;
7408     LPBYTE buf;
7409     DWORD size;
7410
7411     memset(&info, 0, sizeof(info));
7412     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7413      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7414     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7415     if (ret)
7416     {
7417         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7418         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7419         LocalFree(buf);
7420     }
7421     memset(policy, 0, sizeof(policy));
7422     info.cPolicyInfo = 1;
7423     info.rgPolicyInfo = policy;
7424     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7425      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7426     ok(!ret && (GetLastError() == E_INVALIDARG ||
7427      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7428      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7429     policy[0].pszPolicyIdentifier = oid_any_policy;
7430     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7431      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7432     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7433     if (ret)
7434     {
7435         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7436         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7437         LocalFree(buf);
7438     }
7439     policy[1].pszPolicyIdentifier = oid1;
7440     memset(&qualifier, 0, sizeof(qualifier));
7441     qualifier.pszPolicyQualifierId = oid_user_notice;
7442     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7443     qualifier.Qualifier.pbData = noticeWithReference;
7444     policy[1].cPolicyQualifier = 1;
7445     policy[1].rgPolicyQualifier = &qualifier;
7446     info.cPolicyInfo = 2;
7447     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7448      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7449     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7450     if (ret)
7451     {
7452         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7453         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7454         LocalFree(buf);
7455     }
7456 }
7457
7458 static void test_decodeCertPolicies(DWORD dwEncoding)
7459 {
7460     BOOL ret;
7461     CERT_POLICIES_INFO *info;
7462     DWORD size;
7463
7464     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7465      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7466      &info, &size);
7467     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7468     if (ret)
7469     {
7470         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7471          info->cPolicyInfo);
7472         LocalFree(info);
7473     }
7474     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7475      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7476      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7477     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7478     if (ret)
7479     {
7480         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7481          info->cPolicyInfo);
7482         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7483          "unexpected policy id %s\n",
7484          info->rgPolicyInfo[0].pszPolicyIdentifier);
7485         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7486          "unexpected policy qualifier count %d\n",
7487          info->rgPolicyInfo[0].cPolicyQualifier);
7488         LocalFree(info);
7489     }
7490     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7491      twoPolicies, sizeof(twoPolicies),
7492      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7493     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7494     if (ret)
7495     {
7496         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7497          info->cPolicyInfo);
7498         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7499          "unexpected policy id %s\n",
7500          info->rgPolicyInfo[0].pszPolicyIdentifier);
7501         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7502          "unexpected policy qualifier count %d\n",
7503          info->rgPolicyInfo[0].cPolicyQualifier);
7504         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7505          "unexpected policy id %s\n",
7506          info->rgPolicyInfo[1].pszPolicyIdentifier);
7507         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7508          "unexpected policy qualifier count %d\n",
7509          info->rgPolicyInfo[1].cPolicyQualifier);
7510         ok(!strcmp(
7511          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7512          oid_user_notice), "unexpected policy qualifier id %s\n",
7513          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7514         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7515          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7516          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7517         ok(!memcmp(
7518          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7519          noticeWithReference, sizeof(noticeWithReference)),
7520          "unexpected qualifier value\n");
7521         LocalFree(info);
7522     }
7523 }
7524
7525 static const BYTE policyMappingWithOneMapping[] = {
7526 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7527 static const BYTE policyMappingWithTwoMappings[] = {
7528 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7529 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7530 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7531  szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7532
7533 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7534 {
7535     static char oid2[] = "2.3.4";
7536     static char oid3[] = "1.3.4";
7537     static char oid4[] = "2.5.6";
7538     BOOL ret;
7539     CERT_POLICY_MAPPINGS_INFO info = { 0 };
7540     CERT_POLICY_MAPPING mapping[2];
7541     LPBYTE buf;
7542     DWORD size, i;
7543
7544     /* Each of the mapping OIDs is equivalent, so check with all of them */
7545     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7546     {
7547         memset(&info, 0, sizeof(info));
7548         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7549          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7550         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7551          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7552         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7553         {
7554             win_skip("no policy mappings support\n");
7555             return;
7556         }
7557         if (ret)
7558         {
7559             ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7560             ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7561              "unexpected value\n");
7562             LocalFree(buf);
7563         }
7564         mapping[0].pszIssuerDomainPolicy = NULL;
7565         mapping[0].pszSubjectDomainPolicy = NULL;
7566         info.cPolicyMapping = 1;
7567         info.rgPolicyMapping = mapping;
7568         SetLastError(0xdeadbeef);
7569         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7570          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7571         ok(!ret && GetLastError() == E_INVALIDARG,
7572          "expected E_INVALIDARG, got %08x\n", GetLastError());
7573         mapping[0].pszIssuerDomainPolicy = oid1;
7574         mapping[0].pszSubjectDomainPolicy = oid2;
7575         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7576          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7577         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7578         if (ret)
7579         {
7580             ok(size == sizeof(policyMappingWithOneMapping),
7581              "unexpected size %d\n", size);
7582             ok(!memcmp(buf, policyMappingWithOneMapping, size),
7583              "unexpected value\n");
7584             LocalFree(buf);
7585         }
7586         mapping[1].pszIssuerDomainPolicy = oid3;
7587         mapping[1].pszSubjectDomainPolicy = oid4;
7588         info.cPolicyMapping = 2;
7589         ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7590          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7591         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7592         if (ret)
7593         {
7594             ok(size == sizeof(policyMappingWithTwoMappings),
7595              "unexpected size %d\n", size);
7596             ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7597              "unexpected value\n");
7598             LocalFree(buf);
7599         }
7600     }
7601 }
7602
7603 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7604 {
7605     DWORD size, i;
7606     CERT_POLICY_MAPPINGS_INFO *info;
7607     BOOL ret;
7608
7609     /* Each of the mapping OIDs is equivalent, so check with all of them */
7610     for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7611     {
7612         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7613          emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7614          &info, &size);
7615         ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7616          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7617         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7618         {
7619             win_skip("no policy mappings support\n");
7620             return;
7621         }
7622         if (ret)
7623         {
7624             ok(info->cPolicyMapping == 0,
7625              "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7626             LocalFree(info);
7627         }
7628         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7629          policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7630          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7631         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7632         if (ret)
7633         {
7634             ok(info->cPolicyMapping == 1,
7635              "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7636             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7637              "unexpected issuer policy %s\n",
7638              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7639             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7640              "2.3.4"), "unexpected subject policy %s\n",
7641              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7642             LocalFree(info);
7643         }
7644         ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7645          policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7646          CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7647         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7648         if (ret)
7649         {
7650             ok(info->cPolicyMapping == 2,
7651              "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7652             ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7653              "unexpected issuer policy %s\n",
7654              info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7655             ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7656              "2.3.4"), "unexpected subject policy %s\n",
7657              info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7658             ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7659              "unexpected issuer policy %s\n",
7660              info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7661             ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7662              "2.5.6"), "unexpected subject policy %s\n",
7663              info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7664             LocalFree(info);
7665         }
7666     }
7667 }
7668
7669 static const BYTE policyConstraintsWithRequireExplicit[] = {
7670 0x30,0x03,0x80,0x01,0x00 };
7671 static const BYTE policyConstraintsWithInhibitMapping[] = {
7672 0x30,0x03,0x81,0x01,0x01 };
7673 static const BYTE policyConstraintsWithBoth[] = {
7674 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7675
7676 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7677 {
7678     CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7679     LPBYTE buf;
7680     DWORD size;
7681     BOOL ret;
7682
7683     /* Even though RFC 5280 explicitly states CAs must not issue empty
7684      * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7685      */
7686     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7687      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7688     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7689      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7690     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7691     {
7692         win_skip("no policy constraints support\n");
7693         return;
7694     }
7695     if (ret)
7696     {
7697         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7698         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7699          "unexpected value\n");
7700         LocalFree(buf);
7701     }
7702     /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7703      * is not, then a skip of 0 is encoded.
7704      */
7705     info.fRequireExplicitPolicy = TRUE;
7706     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7707      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7708     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7709     if (ret)
7710     {
7711         ok(size == sizeof(policyConstraintsWithRequireExplicit),
7712          "unexpected size %d\n", size);
7713         ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7714          sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7715         LocalFree(buf);
7716     }
7717     /* With inhibit policy mapping */
7718     info.fRequireExplicitPolicy = FALSE;
7719     info.dwRequireExplicitPolicySkipCerts = 0;
7720     info.fInhibitPolicyMapping = TRUE;
7721     info.dwInhibitPolicyMappingSkipCerts = 1;
7722     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7723      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7724     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7725     if (ret)
7726     {
7727         ok(size == sizeof(policyConstraintsWithInhibitMapping),
7728          "unexpected size %d\n", size);
7729         ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7730          sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7731         LocalFree(buf);
7732     }
7733     /* And with both */
7734     info.fRequireExplicitPolicy = TRUE;
7735     info.dwRequireExplicitPolicySkipCerts = 1;
7736     ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7737      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7738     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7739     if (ret)
7740     {
7741         ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7742          size);
7743         ok(!memcmp(buf, policyConstraintsWithBoth,
7744          sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7745         LocalFree(buf);
7746     }
7747 }
7748
7749 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7750 {
7751     CERT_POLICY_CONSTRAINTS_INFO *info;
7752     DWORD size;
7753     BOOL ret;
7754
7755     /* Again, even though CAs must not issue such constraints, they can be
7756      * decoded.
7757      */
7758     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7759      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7760      &info, &size);
7761     ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7762      "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7763     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7764     {
7765         win_skip("no policy mappings support\n");
7766         return;
7767     }
7768     if (ret)
7769     {
7770         ok(!info->fRequireExplicitPolicy,
7771          "expected require explicit = FALSE\n");
7772         ok(!info->fInhibitPolicyMapping,
7773          "expected implicit mapping = FALSE\n");
7774         LocalFree(info);
7775     }
7776     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7777      policyConstraintsWithRequireExplicit,
7778      sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7779      NULL, &info, &size);
7780     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7781     if (ret)
7782     {
7783         ok(info->fRequireExplicitPolicy,
7784          "expected require explicit = TRUE\n");
7785         ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7786          info->dwRequireExplicitPolicySkipCerts);
7787         ok(!info->fInhibitPolicyMapping,
7788          "expected implicit mapping = FALSE\n");
7789         LocalFree(info);
7790     }
7791     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7792      policyConstraintsWithInhibitMapping,
7793      sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7794      NULL, &info, &size);
7795     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7796     if (ret)
7797     {
7798         ok(!info->fRequireExplicitPolicy,
7799          "expected require explicit = FALSE\n");
7800         ok(info->fInhibitPolicyMapping,
7801          "expected implicit mapping = TRUE\n");
7802         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7803          info->dwInhibitPolicyMappingSkipCerts);
7804         LocalFree(info);
7805     }
7806     ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7807      policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7808      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7809     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7810     if (ret)
7811     {
7812         ok(info->fRequireExplicitPolicy,
7813          "expected require explicit = TRUE\n");
7814         ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7815          info->dwRequireExplicitPolicySkipCerts);
7816         ok(info->fInhibitPolicyMapping,
7817          "expected implicit mapping = TRUE\n");
7818         ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7819          info->dwInhibitPolicyMappingSkipCerts);
7820         LocalFree(info);
7821     }
7822 }
7823
7824 /* Free *pInfo with HeapFree */
7825 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7826 {
7827     BOOL ret;
7828     DWORD size = 0;
7829     HCRYPTKEY key;
7830
7831     /* This crashes
7832     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7833      */
7834     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7835     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7836      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7837     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7838      &size);
7839     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7840      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7841     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7842      NULL, &size);
7843     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7844      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7845     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7846      0, NULL, NULL, &size);
7847     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7848      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7849     /* Test with no key */
7850     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7851      0, NULL, NULL, &size);
7852     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7853      GetLastError());
7854     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7855     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7856     if (ret)
7857     {
7858         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7859          NULL, 0, NULL, NULL, &size);
7860         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7861         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7862         if (*pInfo)
7863         {
7864             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7865              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7866             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7867              GetLastError());
7868             if (ret)
7869             {
7870                 /* By default (we passed NULL as the OID) the OID is
7871                  * szOID_RSA_RSA.
7872                  */
7873                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7874                  "Expected %s, got %s\n", szOID_RSA_RSA,
7875                  (*pInfo)->Algorithm.pszObjId);
7876             }
7877         }
7878     }
7879     CryptDestroyKey(key);
7880 }
7881
7882 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7883  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7884  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7885  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7886  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7887  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7888  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7889  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7890  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7891  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7892  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7893  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7894  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7895  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7896  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7897  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7898  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7899  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7900  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7901  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7902  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7903  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7904  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7905  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7906  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7907
7908 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7909 {
7910     BOOL ret;
7911     HCRYPTKEY key;
7912     PCCERT_CONTEXT context;
7913     DWORD dwSize;
7914     ALG_ID ai;
7915
7916     /* These crash
7917     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7918     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7919     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7920     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7921      NULL);
7922      */
7923     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7924     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7925      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7926     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7927     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7928      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7929     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7930      &key);
7931     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7932      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7933
7934     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7935     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7936      &key);
7937     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7938
7939     dwSize = sizeof(ai);
7940     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7941     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7942     if(ret)
7943     {
7944       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7945       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7946     }
7947
7948     CryptDestroyKey(key);
7949
7950     /* Repeat with forced algorithm */
7951     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7952      &key);
7953     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7954
7955     dwSize = sizeof(ai);
7956     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7957     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7958     if(ret)
7959     {
7960       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7961       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7962     }
7963
7964     CryptDestroyKey(key);
7965
7966     /* Test importing a public key from a certificate context */
7967     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7968      sizeof(expiredCert));
7969     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7970      GetLastError());
7971     if (context)
7972     {
7973         ok(!strcmp(szOID_RSA_RSA,
7974          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7975          "Expected %s, got %s\n", szOID_RSA_RSA,
7976          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7977         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7978          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7979         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7980         CryptDestroyKey(key);
7981         CertFreeCertificateContext(context);
7982     }
7983 }
7984
7985 static const char cspName[] = "WineCryptTemp";
7986
7987 static void testPortPublicKeyInfo(void)
7988 {
7989     HCRYPTPROV csp;
7990     BOOL ret;
7991     PCERT_PUBLIC_KEY_INFO info = NULL;
7992
7993     /* Just in case a previous run failed, delete this thing */
7994     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7995      CRYPT_DELETEKEYSET);
7996     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7997      CRYPT_NEWKEYSET);
7998
7999     testExportPublicKey(csp, &info);
8000     testImportPublicKey(csp, info);
8001
8002     HeapFree(GetProcessHeap(), 0, info);
8003     CryptReleaseContext(csp, 0);
8004     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
8005      CRYPT_DELETEKEYSET);
8006 }
8007
8008 START_TEST(encode)
8009 {
8010     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
8011      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
8012     HMODULE hCrypt32;
8013     DWORD i;
8014
8015     hCrypt32 = GetModuleHandleA("crypt32.dll");
8016     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
8017     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
8018     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
8019     {
8020         win_skip("CryptDecodeObjectEx() is not available\n");
8021         return;
8022     }
8023
8024     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
8025     {
8026         test_encodeInt(encodings[i]);
8027         test_decodeInt(encodings[i]);
8028         test_encodeEnumerated(encodings[i]);
8029         test_decodeEnumerated(encodings[i]);
8030         test_encodeFiletime(encodings[i]);
8031         test_decodeFiletime(encodings[i]);
8032         test_encodeName(encodings[i]);
8033         test_decodeName(encodings[i]);
8034         test_encodeUnicodeName(encodings[i]);
8035         test_decodeUnicodeName(encodings[i]);
8036         test_encodeNameValue(encodings[i]);
8037         test_decodeNameValue(encodings[i]);
8038         test_encodeUnicodeNameValue(encodings[i]);
8039         test_decodeUnicodeNameValue(encodings[i]);
8040         test_encodeAltName(encodings[i]);
8041         test_decodeAltName(encodings[i]);
8042         test_encodeOctets(encodings[i]);
8043         test_decodeOctets(encodings[i]);
8044         test_encodeBits(encodings[i]);
8045         test_decodeBits(encodings[i]);
8046         test_encodeBasicConstraints(encodings[i]);
8047         test_decodeBasicConstraints(encodings[i]);
8048         test_encodeRsaPublicKey(encodings[i]);
8049         test_decodeRsaPublicKey(encodings[i]);
8050         test_encodeSequenceOfAny(encodings[i]);
8051         test_decodeSequenceOfAny(encodings[i]);
8052         test_encodeExtensions(encodings[i]);
8053         test_decodeExtensions(encodings[i]);
8054         test_encodePublicKeyInfo(encodings[i]);
8055         test_decodePublicKeyInfo(encodings[i]);
8056         test_encodeCertToBeSigned(encodings[i]);
8057         test_decodeCertToBeSigned(encodings[i]);
8058         test_encodeCert(encodings[i]);
8059         test_decodeCert(encodings[i]);
8060         test_encodeCRLDistPoints(encodings[i]);
8061         test_decodeCRLDistPoints(encodings[i]);
8062         test_encodeCRLIssuingDistPoint(encodings[i]);
8063         test_decodeCRLIssuingDistPoint(encodings[i]);
8064         test_encodeCRLToBeSigned(encodings[i]);
8065         test_decodeCRLToBeSigned(encodings[i]);
8066         test_encodeEnhancedKeyUsage(encodings[i]);
8067         test_decodeEnhancedKeyUsage(encodings[i]);
8068         test_encodeAuthorityKeyId(encodings[i]);
8069         test_decodeAuthorityKeyId(encodings[i]);
8070         test_encodeAuthorityKeyId2(encodings[i]);
8071         test_decodeAuthorityKeyId2(encodings[i]);
8072         test_encodeAuthorityInfoAccess(encodings[i]);
8073         test_decodeAuthorityInfoAccess(encodings[i]);
8074         test_encodeCTL(encodings[i]);
8075         test_decodeCTL(encodings[i]);
8076         test_encodePKCSContentInfo(encodings[i]);
8077         test_decodePKCSContentInfo(encodings[i]);
8078         test_encodePKCSAttribute(encodings[i]);
8079         test_decodePKCSAttribute(encodings[i]);
8080         test_encodePKCSAttributes(encodings[i]);
8081         test_decodePKCSAttributes(encodings[i]);
8082         test_encodePKCSSMimeCapabilities(encodings[i]);
8083         test_decodePKCSSMimeCapabilities(encodings[i]);
8084         test_encodePKCSSignerInfo(encodings[i]);
8085         test_decodePKCSSignerInfo(encodings[i]);
8086         test_encodeCMSSignerInfo(encodings[i]);
8087         test_decodeCMSSignerInfo(encodings[i]);
8088         test_encodeNameConstraints(encodings[i]);
8089         test_decodeNameConstraints(encodings[i]);
8090         test_encodePolicyQualifierUserNotice(encodings[i]);
8091         test_decodePolicyQualifierUserNotice(encodings[i]);
8092         test_encodeCertPolicies(encodings[i]);
8093         test_decodeCertPolicies(encodings[i]);
8094         test_encodeCertPolicyMappings(encodings[i]);
8095         test_decodeCertPolicyMappings(encodings[i]);
8096         test_encodeCertPolicyConstraints(encodings[i]);
8097         test_decodeCertPolicyConstraints(encodings[i]);
8098     }
8099     testPortPublicKeyInfo();
8100 }