EnumThemeColors() and EnumThemeSizes() actually do not return a single
[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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  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 struct encodedInt
30 {
31     int val;
32     const BYTE *encoded;
33 };
34
35 static const struct encodedInt ints[] = {
36  { 1,          "\x02\x01\x01" },
37  { 127,        "\x02\x01\x7f" },
38  { 128,        "\x02\x02\x00\x80" },
39  { 256,        "\x02\x02\x01\x00" },
40  { -128,       "\x02\x01\x80" },
41  { -129,       "\x02\x02\xff\x7f" },
42  { 0xbaddf00d, "\x02\x04\xba\xdd\xf0\x0d" },
43 };
44
45 struct encodedBigInt
46 {
47     const BYTE *val;
48     const BYTE *encoded;
49     const BYTE *decoded;
50 };
51
52 static const struct encodedBigInt bigInts[] = {
53  { "\xff\xff\x01\x02\x03\x04\x05\x06\x07\x08",
54    "\x02\x0a\x08\x07\x06\x05\x04\x03\x02\x01\xff\xff",
55    "\xff\xff\x01\x02\x03\x04\x05\x06\x07\x08" },
56  { "\x08\x07\x06\x05\x04\x03\x02\x01\xff\xff\xff",
57    "\x02\x09\xff\x01\x02\x03\x04\x05\x06\x07\x08",
58    "\x08\x07\x06\x05\x04\x03\x02\x01\xff" },
59 };
60
61 /* Decoded is the same as original, so don't bother storing a separate copy */
62 static const struct encodedBigInt bigUInts[] = {
63  { "\xff\xff\x01\x02\x03\x04\x05\x06\x07\x08",
64    "\x02\x0a\x08\x07\x06\x05\x04\x03\x02\x01\xff\xff", NULL },
65  { "\x08\x07\x06\x05\x04\x03\x02\x01\xff\xff\xff",
66    "\x02\x0c\x00\xff\xff\xff\x01\x02\x03\x04\x05\x06\x07\x08", NULL },
67 };
68
69 static void test_encodeInt(DWORD dwEncoding)
70 {
71     DWORD bufSize = 0;
72     int i;
73     BOOL ret;
74     CRYPT_INTEGER_BLOB blob;
75     BYTE *buf = NULL;
76
77     /* CryptEncodeObjectEx with NULL bufSize crashes..
78     ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
79      NULL);
80      */
81     /* check bogus encoding */
82     ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
83      &bufSize);
84     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
85      "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
86     /* check with NULL integer buffer.  Windows XP incorrectly returns an
87      * NTSTATUS.
88      */
89     ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
90      &bufSize);
91     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
92      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
93     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
94     {
95         /* encode as normal integer */
96         ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
97          NULL, NULL, &bufSize);
98         ok(ret, "Expected success, got %ld\n", GetLastError());
99         ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
100          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
101         ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
102         if (buf)
103         {
104             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
105              buf[0]);
106             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
107              buf[1], ints[i].encoded[1]);
108             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
109              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
110             LocalFree(buf);
111         }
112         /* encode as multibyte integer */
113         blob.cbData = sizeof(ints[i].val);
114         blob.pbData = (BYTE *)&ints[i].val;
115         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
116          0, NULL, NULL, &bufSize);
117         ok(ret, "Expected success, got %ld\n", GetLastError());
118         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
119          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
120         ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
121         if (buf)
122         {
123             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
124              buf[0]);
125             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
126              buf[1], ints[i].encoded[1]);
127             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
128              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
129             LocalFree(buf);
130         }
131     }
132     /* encode a couple bigger ints, just to show it's little-endian and leading
133      * sign bytes are dropped
134      */
135     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
136     {
137         blob.cbData = strlen(bigInts[i].val);
138         blob.pbData = (BYTE *)bigInts[i].val;
139         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
140          0, NULL, NULL, &bufSize);
141         ok(ret, "Expected success, got %ld\n", GetLastError());
142         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
143          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
144         ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
145         if (buf)
146         {
147             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
148              buf[0]);
149             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
150              buf[1], bigInts[i].encoded[1]);
151             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
152              bigInts[i].encoded[1] + 1),
153              "Encoded value didn't match expected\n");
154             LocalFree(buf);
155         }
156     }
157     /* and, encode some uints */
158     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
159     {
160         blob.cbData = strlen(bigUInts[i].val);
161         blob.pbData = (BYTE *)bigUInts[i].val;
162         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
163          0, NULL, NULL, &bufSize);
164         ok(ret, "Expected success, got %ld\n", GetLastError());
165         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
166          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
167         ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
168         if (buf)
169         {
170             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
171              buf[0]);
172             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
173              buf[1], bigUInts[i].encoded[1]);
174             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
175              bigUInts[i].encoded[1] + 1),
176              "Encoded value didn't match expected\n");
177             LocalFree(buf);
178         }
179     }
180 }
181
182 static void test_decodeInt(DWORD dwEncoding)
183 {
184     static const char bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
185     static const char testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
186     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
187     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
188     BYTE *buf = NULL;
189     DWORD bufSize = 0;
190     int i;
191     BOOL ret;
192
193     /* CryptDecodeObjectEx with NULL bufSize crashes..
194     ret = CryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded, 
195      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
196      */
197     /* check bogus encoding */
198     ret = CryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded, 
199      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
200     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
201      "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
202     /* check with NULL integer buffer */
203     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
204      &bufSize);
205     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
206      "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
207     /* check with a valid, but too large, integer */
208     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
209      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
210     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
211      "Expected CRYPT_E_ASN1_LARGE, got %ld\n", GetLastError());
212     /* check with a DER-encoded string */
213     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
214      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
215     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
216      "Expected CRYPT_E_ASN1_BADTAG, got %ld\n", GetLastError());
217     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
218     {
219         /* When the output buffer is NULL, this always succeeds */
220         SetLastError(0xdeadbeef);
221         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
222          (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
223          &bufSize);
224         ok(ret && GetLastError() == NOERROR,
225          "Expected success and NOERROR, got %ld\n", GetLastError());
226         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
227          (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2,
228          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
229         ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
230         ok(bufSize == sizeof(int), "Expected size %d, got %ld\n", sizeof(int),
231          bufSize);
232         ok(buf != NULL, "Expected allocated buffer\n");
233         if (buf)
234         {
235             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
236              ints[i].val, *(int *)buf);
237             LocalFree(buf);
238         }
239     }
240     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
241     {
242         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
243          (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
244          &bufSize);
245         ok(ret && GetLastError() == NOERROR,
246          "Expected success and NOERROR, got %ld\n", GetLastError());
247         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
248          (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2,
249          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
250         ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
251         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB),
252          "Expected size at least %d, got %ld\n", sizeof(CRYPT_INTEGER_BLOB),
253          bufSize);
254         ok(buf != NULL, "Expected allocated buffer\n");
255         if (buf)
256         {
257             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
258
259             ok(blob->cbData == strlen(bigInts[i].decoded),
260              "Expected len %d, got %ld\n", strlen(bigInts[i].decoded),
261              blob->cbData);
262             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
263              "Unexpected value\n");
264             LocalFree(buf);
265         }
266     }
267     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
268     {
269         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
270          (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
271          &bufSize);
272         ok(ret && GetLastError() == NOERROR,
273          "Expected success and NOERROR, got %ld\n", GetLastError());
274         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
275          (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
276          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
277         ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
278         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB),
279          "Expected size at least %d, got %ld\n", sizeof(CRYPT_INTEGER_BLOB),
280          bufSize);
281         ok(buf != NULL, "Expected allocated buffer\n");
282         if (buf)
283         {
284             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
285
286             ok(blob->cbData == strlen(bigUInts[i].val),
287              "Expected len %d, got %ld\n", strlen(bigUInts[i].val),
288              blob->cbData);
289             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
290              "Unexpected value\n");
291             LocalFree(buf);
292         }
293     }
294     /* Decode the value 1 with long-form length */
295     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
296      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
297     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
298     if (buf)
299     {
300         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
301         LocalFree(buf);
302     }
303     /* Try to decode some bogus large items */
304     /* The buffer size is smaller than the encoded length, so this should fail
305      * with CRYPT_E_ASN1_EOD if it's being decoded.
306      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
307      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
308      * So this test unfortunately isn't useful.
309     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
310      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
311     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
312      "Expected CRYPT_E_ASN1_LARGE, got %08lx\n", GetLastError());
313      */
314     /* This will try to decode the buffer and overflow it, check that it's
315      * caught.
316      */
317     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
318      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
319     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
320      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
321 }
322
323 /* These are always encoded unsigned, and aren't constrained to be any
324  * particular value
325  */
326 static const struct encodedInt enums[] = {
327  { 1,    "\x0a\x01\x01" },
328  { -128, "\x0a\x05\x00\xff\xff\xff\x80" },
329 };
330
331 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
332  * X509_ENUMERATED.
333  */
334 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
335  szOID_CRL_REASON_CODE };
336
337 static void test_encodeEnumerated(DWORD dwEncoding)
338 {
339     DWORD i, j;
340
341     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
342     {
343         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
344         {
345             BOOL ret;
346             BYTE *buf = NULL;
347             DWORD bufSize = 0;
348
349             ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
350              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
351              &bufSize);
352             ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
353             if (buf)
354             {
355                 ok(buf[0] == 0xa,
356                  "Got unexpected type %d for enumerated (expected 0xa)\n",
357                  buf[0]);
358                 ok(buf[1] == enums[j].encoded[1],
359                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
360                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
361                  enums[j].encoded[1] + 1),
362                  "Encoded value of 0x%08x didn't match expected\n",
363                  enums[j].val);
364                 LocalFree(buf);
365             }
366         }
367     }
368 }
369
370 static void test_decodeEnumerated(DWORD dwEncoding)
371 {
372     DWORD i, j;
373
374     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
375     {
376         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
377         {
378             BOOL ret;
379             DWORD bufSize = sizeof(int);
380             int val;
381
382             ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
383              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
384              (BYTE *)&val, &bufSize);
385             ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
386             ok(bufSize == sizeof(int),
387              "Got unexpected size %ld for enumerated (expected %d)\n",
388              bufSize, sizeof(int));
389             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
390              val, enums[j].val);
391         }
392     }
393 }
394
395 struct encodedFiletime
396 {
397     SYSTEMTIME sysTime;
398     const BYTE *encodedTime;
399 };
400
401 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
402  const struct encodedFiletime *time)
403 {
404     FILETIME ft = { 0 };
405     BYTE *buf = NULL;
406     DWORD bufSize = 0;
407     BOOL ret;
408
409     ret = SystemTimeToFileTime(&time->sysTime, &ft);
410     ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
411     ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
412      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
413     /* years other than 1950-2050 are not allowed for encodings other than
414      * X509_CHOICE_OF_TIME.
415      */
416     if (structType == X509_CHOICE_OF_TIME ||
417      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
418     {
419         ok(ret, "CryptEncodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
420          GetLastError());
421         ok(buf != NULL, "Expected an allocated buffer\n");
422         if (buf)
423         {
424             ok(buf[0] == time->encodedTime[0],
425              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
426              buf[0]);
427             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %ld\n",
428              time->encodedTime[1], bufSize);
429             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
430              "Got unexpected value for time encoding\n");
431             LocalFree(buf);
432         }
433     }
434     else
435         ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
436          "Expected CRYPT_E_BAD_ENCODE, got 0x%08lx\n", GetLastError());
437 }
438
439 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
440  const struct encodedFiletime *time)
441 {
442     FILETIME ft1 = { 0 }, ft2 = { 0 };
443     DWORD size = sizeof(ft2);
444     BOOL ret;
445
446     ret = SystemTimeToFileTime(&time->sysTime, &ft1);
447     ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
448     ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
449      time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
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, "CryptDecodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
457          GetLastError());
458         ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
459          "Got unexpected value for time decoding\n");
460     }
461     else
462         ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
463          "Expected CRYPT_E_ASN1_BADTAG, got 0x%08lx\n", GetLastError());
464 }
465
466 static const struct encodedFiletime times[] = {
467  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, "\x17" "\x0d" "050606161000Z" },
468  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, "\x18" "\x0f" "19450606161000Z" },
469  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, "\x18" "\x0f" "21450606161000Z" },
470 };
471
472 static void test_encodeFiletime(DWORD dwEncoding)
473 {
474     DWORD i;
475
476     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
477     {
478         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
479         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
480         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
481     }
482 }
483
484 static void test_decodeFiletime(DWORD dwEncoding)
485 {
486     static const struct encodedFiletime otherTimes[] = {
487      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   "\x18" "\x13" "19450606161000.000Z" },
488      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, "\x18" "\x13" "19450606161000.999Z" },
489      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   "\x18" "\x13" "19450606161000+0100" },
490      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   "\x18" "\x13" "19450606161000-0100" },
491      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   "\x18" "\x13" "19450606161000-0115" },
492      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   "\x18" "\x0a" "2145060616" },
493      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   "\x17" "\x0a" "4506061610" },
494      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   "\x17" "\x0b" "4506061610Z" },
495      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   "\x17" "\x0d" "4506061610+01" },
496      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   "\x17" "\x0d" "4506061610-01" },
497      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   "\x17" "\x0f" "4506061610+0100" },
498      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   "\x17" "\x0f" "4506061610-0100" },
499     };
500     /* An oddball case that succeeds in Windows, but doesn't seem correct
501      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
502      */
503     static const char *bogusTimes[] = {
504      /* oddly, this succeeds on Windows, with year 2765
505      "\x18" "\x0f" "21r50606161000Z",
506       */
507      "\x17" "\x08" "45060616",
508      "\x18" "\x0f" "aaaaaaaaaaaaaaZ",
509      "\x18" "\x04" "2145",
510      "\x18" "\x08" "21450606",
511     };
512     DWORD i, size;
513     FILETIME ft1 = { 0 }, ft2 = { 0 };
514     BOOL ret;
515
516     /* Check bogus length with non-NULL buffer */
517     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
518     ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
519     size = 1;
520     ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
521      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
522     ok(!ret && GetLastError() == ERROR_MORE_DATA,
523      "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
524     /* Normal tests */
525     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
526     {
527         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
528         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
529         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
530     }
531     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
532     {
533         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
534         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
535         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
536     }
537     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
538     {
539         size = sizeof(ft1);
540         ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
541          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
542         ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
543          "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
544     }
545 }
546
547 struct EncodedName
548 {
549     CERT_RDN_ATTR attr;
550     const BYTE *encoded;
551 };
552
553 static const char commonName[] = "Juan Lang";
554 static const char surName[] = "Lang";
555 static const char bogusIA5[] = "\x80";
556 static const char bogusPrintable[] = "~";
557 static const char bogusNumeric[] = "A";
558 static const struct EncodedName names[] = {
559  { { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING,
560    { sizeof(commonName), (BYTE *)commonName } },
561  "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0aJuan Lang" },
562  { { szOID_COMMON_NAME, CERT_RDN_IA5_STRING,
563    { sizeof(commonName), (BYTE *)commonName } },
564  "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x16\x0aJuan Lang" },
565  { { szOID_SUR_NAME, CERT_RDN_IA5_STRING,
566    { sizeof(surName), (BYTE *)surName } },
567  "\x30\x10\x31\x0e\x30\x0c\x06\x03\x55\x04\x04\x16\x05Lang" },
568  { { NULL, CERT_RDN_PRINTABLE_STRING,
569    { sizeof(commonName), (BYTE *)commonName } },
570  "\x30\x12\x31\x10\x30\x0e\x06\x00\x13\x0aJuan Lang" },
571 /* The following test isn't a very good one, because it doesn't encode any
572  * Japanese characters.  I'm leaving it out for now.
573  { { szOID_COMMON_NAME, CERT_RDN_T61_STRING,
574    { sizeof(commonName), (BYTE *)commonName } },
575  "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x14\x0aJuan Lang" },
576  */
577  /* The following tests succeed under Windows, but really should fail,
578   * they contain characters that are illegal for the encoding.  I'm
579   * including them to justify my lazy encoding.
580   */
581  { { szOID_COMMON_NAME, CERT_RDN_IA5_STRING,
582    { sizeof(bogusIA5), (BYTE *)bogusIA5 } },
583  "\x30\x0d\x31\x0b\x30\x09\x06\x03\x55\x04\x03\x16\x02\x80" },
584  { { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING,
585    { sizeof(bogusPrintable), (BYTE *)bogusPrintable } },
586  "\x30\x0d\x31\x0b\x30\x09\x06\x03\x55\x04\x03\x13\x02\x7e" },
587  { { szOID_COMMON_NAME, CERT_RDN_NUMERIC_STRING,
588    { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
589  "\x30\x0d\x31\x0b\x30\x09\x06\x03\x55\x04\x03\x12\x02\x41" },
590 };
591
592 static const BYTE emptyName[] = { 0x30, 0 };
593 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
594 static const BYTE twoRDNs[] = "\x30\x23\x31\x21\x30\x0c\x06\x03\x55\x04\x04"
595  "\x13\x05\x4c\x61\x6e\x67\x00\x30\x11\x06\x03\x55\x04\x03"
596  "\x13\x0a\x4a\x75\x61\x6e\x20\x4c\x61\x6e\x67";
597
598 static void test_encodeName(DWORD dwEncoding)
599 {
600     CERT_RDN_ATTR attrs[2];
601     CERT_RDN rdn;
602     CERT_NAME_INFO info;
603     BYTE *buf = NULL;
604     DWORD size = 0, i;
605     BOOL ret;
606
607     /* Test with NULL pvStructInfo */
608     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
609      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
610     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
611      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
612     /* Test with empty CERT_NAME_INFO */
613     info.cRDN = 0;
614     info.rgRDN = NULL;
615     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
616      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
617     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
618     if (buf)
619     {
620         ok(!memcmp(buf, emptyName, sizeof(emptyName)),
621          "Got unexpected encoding for empty name\n");
622         LocalFree(buf);
623     }
624     /* Test with bogus CERT_RDN */
625     info.cRDN = 1;
626     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
627      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
628     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
629      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
630     /* Test with empty CERT_RDN */
631     rdn.cRDNAttr = 0;
632     rdn.rgRDNAttr = NULL;
633     info.cRDN = 1;
634     info.rgRDN = &rdn;
635     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
636      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
637     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
638     if (buf)
639     {
640         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
641          "Got unexpected encoding for empty RDN array\n");
642         LocalFree(buf);
643     }
644     /* Test with bogus attr array */
645     rdn.cRDNAttr = 1;
646     rdn.rgRDNAttr = NULL;
647     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
648      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
649     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
650      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
651     /* oddly, a bogus OID is accepted by Windows XP; not testing.
652     attrs[0].pszObjId = "bogus";
653     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
654     attrs[0].Value.cbData = sizeof(commonName);
655     attrs[0].Value.pbData = (BYTE *)commonName;
656     rdn.cRDNAttr = 1;
657     rdn.rgRDNAttr = attrs;
658     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
659      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
660     ok(!ret, "Expected failure, got success\n");
661      */
662     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
663      * the encoded attributes to be swapped.
664      */
665     attrs[0].pszObjId = szOID_COMMON_NAME;
666     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
667     attrs[0].Value.cbData = sizeof(commonName);
668     attrs[0].Value.pbData = (BYTE *)commonName;
669     attrs[1].pszObjId = szOID_SUR_NAME;
670     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
671     attrs[1].Value.cbData = sizeof(surName);
672     attrs[1].Value.pbData = (BYTE *)surName;
673     rdn.cRDNAttr = 2;
674     rdn.rgRDNAttr = attrs;
675     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
676      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
677     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
678     if (buf)
679     {
680         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
681          "Got unexpected encoding for two RDN array\n");
682         LocalFree(buf);
683     }
684     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
685     rdn.cRDNAttr = 1;
686     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
687     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
688      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
689     ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
690      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
691     for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
692     {
693         rdn.cRDNAttr = 1;
694         rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
695         ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
696          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
697         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
698         if (buf)
699         {
700             ok(size == names[i].encoded[1] + 2, "Expected size %d, got %ld\n",
701              names[i].encoded[1] + 2, size);
702             ok(!memcmp(buf, names[i].encoded, names[i].encoded[1] + 2),
703              "Got unexpected encoding\n");
704             LocalFree(buf);
705         }
706     }
707 }
708
709 static void compareNames(const CERT_NAME_INFO *expected,
710  const CERT_NAME_INFO *got)
711 {
712     ok(got->cRDN == expected->cRDN, "Expected %ld RDNs, got %ld\n",
713      expected->cRDN, got->cRDN);
714     if (expected->cRDN)
715     {
716         ok(got->rgRDN[0].cRDNAttr == expected->rgRDN[0].cRDNAttr,
717          "Expected %ld RDN attrs, got %ld\n", expected->rgRDN[0].cRDNAttr,
718          got->rgRDN[0].cRDNAttr);
719         if (expected->rgRDN[0].cRDNAttr)
720         {
721             if (expected->rgRDN[0].rgRDNAttr[0].pszObjId &&
722              strlen(expected->rgRDN[0].rgRDNAttr[0].pszObjId))
723             {
724                 ok(got->rgRDN[0].rgRDNAttr[0].pszObjId != NULL,
725                  "Expected OID %s, got NULL\n",
726                  expected->rgRDN[0].rgRDNAttr[0].pszObjId);
727                 if (got->rgRDN[0].rgRDNAttr[0].pszObjId)
728                     ok(!strcmp(got->rgRDN[0].rgRDNAttr[0].pszObjId,
729                      expected->rgRDN[0].rgRDNAttr[0].pszObjId),
730                      "Got unexpected OID %s, expected %s\n",
731                      got->rgRDN[0].rgRDNAttr[0].pszObjId,
732                      expected->rgRDN[0].rgRDNAttr[0].pszObjId);
733             }
734             ok(got->rgRDN[0].rgRDNAttr[0].Value.cbData ==
735              expected->rgRDN[0].rgRDNAttr[0].Value.cbData,
736              "Unexpected data size, got %ld, expected %ld\n",
737              got->rgRDN[0].rgRDNAttr[0].Value.cbData,
738              expected->rgRDN[0].rgRDNAttr[0].Value.cbData);
739             if (expected->rgRDN[0].rgRDNAttr[0].Value.pbData)
740                 ok(!memcmp(got->rgRDN[0].rgRDNAttr[0].Value.pbData,
741                  expected->rgRDN[0].rgRDNAttr[0].Value.pbData,
742                  expected->rgRDN[0].rgRDNAttr[0].Value.cbData),
743                  "Unexpected value\n");
744         }
745     }
746 }
747
748 static void test_decodeName(DWORD dwEncoding)
749 {
750     int i;
751     BYTE *buf = NULL;
752     DWORD bufSize = 0;
753     BOOL ret;
754     CERT_RDN rdn;
755     CERT_NAME_INFO info = { 1, &rdn };
756
757     for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
758     {
759         /* When the output buffer is NULL, this always succeeds */
760         SetLastError(0xdeadbeef);
761         ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
762          names[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
763         ok(ret && GetLastError() == NOERROR,
764          "Expected success and NOERROR, got %08lx\n", GetLastError());
765         ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
766          names[i].encoded[1] + 2,
767          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
768          (BYTE *)&buf, &bufSize);
769         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
770         rdn.cRDNAttr = 1;
771         rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
772         if (buf)
773         {
774             compareNames((CERT_NAME_INFO *)buf, &info);
775             LocalFree(buf);
776         }
777     }
778     /* test empty name */
779     bufSize = 0;
780     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyName,
781      emptyName[1] + 2,
782      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
783      (BYTE *)&buf, &bufSize);
784     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
785     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
786      * decoder works the same way, so only test the count.
787      */
788     if (buf)
789     {
790         ok(bufSize == sizeof(CERT_NAME_INFO),
791          "Expected bufSize %d, got %ld\n", sizeof(CERT_NAME_INFO), bufSize);
792         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
793          "Expected 0 RDNs in empty info, got %ld\n",
794          ((CERT_NAME_INFO *)buf)->cRDN);
795         LocalFree(buf);
796     }
797     /* test empty RDN */
798     bufSize = 0;
799     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
800      emptyRDNs[1] + 2,
801      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
802      (BYTE *)&buf, &bufSize);
803     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
804     if (buf)
805     {
806         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
807
808         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
809          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
810          "Got unexpected value for empty RDN\n");
811         LocalFree(buf);
812     }
813     /* test two RDN attrs */
814     bufSize = 0;
815     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
816      twoRDNs[1] + 2,
817      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
818      (BYTE *)&buf, &bufSize);
819     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
820     if (buf)
821     {
822         CERT_RDN_ATTR attrs[] = {
823          { szOID_SUR_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
824           (BYTE *)surName } },
825          { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
826           (BYTE *)commonName } },
827         };
828
829         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
830         rdn.rgRDNAttr = attrs;
831         compareNames((CERT_NAME_INFO *)buf, &info);
832         LocalFree(buf);
833     }
834 }
835
836 static const BYTE emptyAltName[] = { 0x30, 0x00 };
837 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
838 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
839  'h','q','.','o','r','g',0 };
840 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
841  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
842  0x6f, 0x72, 0x67 };
843 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
844 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
845  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
846 static const BYTE localhost[] = { 127, 0, 0, 1 };
847 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
848  0x01 };
849
850 static void printBytes(const char *hdr, const BYTE *pb, size_t cb)
851 {
852     size_t i;
853
854     printf("%s:\n", hdr);
855     for (i = 0; i < cb; i++)
856         printf("%02x ", pb[i]);
857     putchar('\n');
858 }
859
860 static void test_encodeAltName(DWORD dwEncoding)
861 {
862     static const WCHAR nihongo[] = { 0x226f, 0x575b, 0 };
863     CERT_ALT_NAME_INFO info = { 0 };
864     CERT_ALT_NAME_ENTRY entry = { 0 };
865     BYTE *buf = NULL;
866     DWORD size = 0;
867     BOOL ret;
868
869     /* Test with empty info */
870     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
871      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
872     if (buf)
873     {
874         ok(size == sizeof(emptyAltName), "Expected size %d, got %ld\n",
875          sizeof(emptyAltName), size);
876         ok(!memcmp(buf, emptyAltName, size), "Unexpected value\n");
877         LocalFree(buf);
878     }
879     /* Test with an empty entry */
880     info.cAltEntry = 1;
881     info.rgAltEntry = &entry;
882     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
883      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
884     ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
885      "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
886      GetLastError());
887     /* Test with an empty pointer */
888     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
889     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
890      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
891     if (buf)
892     {
893         ok(size == sizeof(emptyURL), "Expected size %d, got %ld\n",
894          sizeof(emptyURL), size);
895         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
896         LocalFree(buf);
897     }
898     /* Test with a real URL */
899     U(entry).pwszURL = (LPWSTR)url;
900     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
901      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
902     if (buf)
903     {
904         ok(size == sizeof(encodedURL), "Expected size %d, got %ld\n",
905          sizeof(encodedURL), size);
906         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
907         LocalFree(buf);
908     }
909     /* Now with the URL containing an invalid IA5 char */
910     U(entry).pwszURL = (LPWSTR)nihongo;
911     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
912      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
913     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
914      "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
915     /* Now with the URL missing a scheme */
916     U(entry).pwszURL = (LPWSTR)dnsName;
917     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
918      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
919     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
920     if (buf)
921     {
922         /* This succeeds, but it shouldn't, so don't worry about conforming */
923         LocalFree(buf);
924     }
925     /* Now with a DNS name */
926     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
927     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
928      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
929     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
930     if (buf)
931     {
932         ok(size == sizeof(encodedDnsName), "Expected size %d, got %ld\n",
933          sizeof(encodedDnsName), size);
934         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
935         LocalFree(buf);
936     }
937     /* Test with an IP address */
938     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
939     U(entry).IPAddress.cbData = sizeof(localhost);
940     U(entry).IPAddress.pbData = (LPBYTE)localhost;
941     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
942      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
943     if (buf)
944     {
945         ok(size == sizeof(encodedIPAddr), "Expected size %d, got %ld\n",
946          sizeof(encodedIPAddr), size);
947         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
948         LocalFree(buf);
949     }
950 }
951
952 static void test_decodeAltName(DWORD dwEncoding)
953 {
954     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
955      0x00, 0x00, 0x01 };
956     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
957      0x01 };
958     BOOL ret;
959     BYTE *buf = NULL;
960     DWORD bufSize = 0;
961     CERT_ALT_NAME_INFO *info;
962
963     /* Test some bogus ones first */
964     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
965      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
966      NULL, (BYTE *)&buf, &bufSize);
967     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
968      "Expected CRYPT_E_ASN1_BADTAG, got %08lx\n", GetLastError());
969     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
970      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
971      &bufSize);
972     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
973      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
974     /* Now expected cases */
975     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyAltName,
976      emptyAltName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
977      &bufSize);
978     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
979     if (buf)
980     {
981         info = (CERT_ALT_NAME_INFO *)buf;
982
983         ok(info->cAltEntry == 0, "Expected 0 entries, got %ld\n",
984          info->cAltEntry);
985         LocalFree(buf);
986     }
987     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
988      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
989      &bufSize);
990     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
991     if (buf)
992     {
993         info = (CERT_ALT_NAME_INFO *)buf;
994
995         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
996          info->cAltEntry);
997         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
998          "Expected CERT_ALT_NAME_URL, got %ld\n",
999          info->rgAltEntry[0].dwAltNameChoice);
1000         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1001          "Expected empty URL\n");
1002         LocalFree(buf);
1003     }
1004     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1005      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1006      &bufSize);
1007     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1008     if (buf)
1009     {
1010         info = (CERT_ALT_NAME_INFO *)buf;
1011
1012         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1013          info->cAltEntry);
1014         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1015          "Expected CERT_ALT_NAME_URL, got %ld\n",
1016          info->rgAltEntry[0].dwAltNameChoice);
1017         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1018         LocalFree(buf);
1019     }
1020     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1021      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1022      &bufSize);
1023     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1024     if (buf)
1025     {
1026         info = (CERT_ALT_NAME_INFO *)buf;
1027
1028         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1029          info->cAltEntry);
1030         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1031          "Expected CERT_ALT_NAME_DNS_NAME, got %ld\n",
1032          info->rgAltEntry[0].dwAltNameChoice);
1033         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1034          "Unexpected DNS name\n");
1035         LocalFree(buf);
1036     }
1037     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1038      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1039      &bufSize);
1040     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1041     if (buf)
1042     {
1043         info = (CERT_ALT_NAME_INFO *)buf;
1044
1045         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1046          info->cAltEntry);
1047         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1048          "Expected CERT_ALT_NAME_IP_ADDRESS, got %ld\n",
1049          info->rgAltEntry[0].dwAltNameChoice);
1050         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1051          "Unexpected IP address length %ld\n",
1052           U(info->rgAltEntry[0]).IPAddress.cbData);
1053         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1054          sizeof(localhost)), "Unexpected IP address value\n");
1055         LocalFree(buf);
1056     }
1057 }
1058
1059 struct encodedOctets
1060 {
1061     const BYTE *val;
1062     const BYTE *encoded;
1063 };
1064
1065 static const struct encodedOctets octets[] = {
1066     { "hi", "\x04\x02hi" },
1067     { "somelong\xffstring", "\x04\x0fsomelong\xffstring" },
1068     { "", "\x04\x00" },
1069 };
1070
1071 static void test_encodeOctets(DWORD dwEncoding)
1072 {
1073     CRYPT_DATA_BLOB blob;
1074     DWORD i;
1075
1076     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1077     {
1078         BYTE *buf = NULL;
1079         BOOL ret;
1080         DWORD bufSize = 0;
1081
1082         blob.cbData = strlen(octets[i].val);
1083         blob.pbData = (BYTE *)octets[i].val;
1084         ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1085          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1086         ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
1087         if (buf)
1088         {
1089             ok(buf[0] == 4,
1090              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1091             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1092              buf[1], octets[i].encoded[1]);
1093             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1094              octets[i].encoded[1] + 1), "Got unexpected value\n");
1095             LocalFree(buf);
1096         }
1097     }
1098 }
1099
1100 static void test_decodeOctets(DWORD dwEncoding)
1101 {
1102     DWORD i;
1103
1104     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1105     {
1106         BYTE *buf = NULL;
1107         BOOL ret;
1108         DWORD bufSize = 0;
1109
1110         ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1111          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1112          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1113         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1114         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1115          "Expected size >= %d, got %ld\n",
1116          sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1117         ok(buf != NULL, "Expected allocated buffer\n");
1118         if (buf)
1119         {
1120             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1121
1122             if (blob->cbData)
1123                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1124                  "Unexpected value\n");
1125             LocalFree(buf);
1126         }
1127     }
1128 }
1129
1130 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1131
1132 struct encodedBits
1133 {
1134     DWORD cUnusedBits;
1135     const BYTE *encoded;
1136     DWORD cbDecoded;
1137     const BYTE *decoded;
1138 };
1139
1140 static const struct encodedBits bits[] = {
1141     /* normal test cases */
1142     { 0, "\x03\x03\x00\xff\xff", 2, "\xff\xff" },
1143     { 1, "\x03\x03\x01\xff\xfe", 2, "\xff\xfe" },
1144     /* strange test case, showing cUnusedBits >= 8 is allowed */
1145     { 9, "\x03\x02\x01\xfe", 1, "\xfe" },
1146     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1147     { 17, "\x03\x01\x00", 0, NULL },
1148 };
1149
1150 static void test_encodeBits(DWORD dwEncoding)
1151 {
1152     DWORD i;
1153
1154     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1155     {
1156         CRYPT_BIT_BLOB blob;
1157         BOOL ret;
1158         BYTE *buf = NULL;
1159         DWORD bufSize = 0;
1160
1161         blob.cbData = sizeof(bytesToEncode);
1162         blob.pbData = (BYTE *)bytesToEncode;
1163         blob.cUnusedBits = bits[i].cUnusedBits;
1164         ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1165          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1166         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1167         if (buf)
1168         {
1169             ok(bufSize == bits[i].encoded[1] + 2,
1170              "Got unexpected size %ld, expected %d\n", bufSize,
1171              bits[i].encoded[1] + 2);
1172             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1173              "Unexpected value\n");
1174             LocalFree(buf);
1175         }
1176     }
1177 }
1178
1179 static void test_decodeBits(DWORD dwEncoding)
1180 {
1181     static const BYTE ber[] = "\x03\x02\x01\xff";
1182     static const BYTE berDecoded = 0xfe;
1183     DWORD i;
1184     BOOL ret;
1185     BYTE *buf = NULL;
1186     DWORD bufSize = 0;
1187
1188     /* normal cases */
1189     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1190     {
1191         ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1192          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1193          &bufSize);
1194         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1195         if (buf)
1196         {
1197             CRYPT_BIT_BLOB *blob;
1198
1199             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1200              "Got unexpected size %ld, expected >= %ld\n", bufSize,
1201              sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded);
1202             blob = (CRYPT_BIT_BLOB *)buf;
1203             ok(blob->cbData == bits[i].cbDecoded,
1204              "Got unexpected length %ld, expected %ld\n", blob->cbData,
1205              bits[i].cbDecoded);
1206             if (blob->cbData && bits[i].cbDecoded)
1207                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1208                  "Unexpected value\n");
1209             LocalFree(buf);
1210         }
1211     }
1212     /* special case: check that something that's valid in BER but not in DER
1213      * decodes successfully
1214      */
1215     ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1216      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1217     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1218     if (buf)
1219     {
1220         CRYPT_BIT_BLOB *blob;
1221
1222         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1223          "Got unexpected size %ld, expected >= %d\n", bufSize,
1224          sizeof(CRYPT_BIT_BLOB) + berDecoded);
1225         blob = (CRYPT_BIT_BLOB *)buf;
1226         ok(blob->cbData == sizeof(berDecoded),
1227          "Got unexpected length %ld, expected %d\n", blob->cbData,
1228          sizeof(berDecoded));
1229         if (blob->cbData)
1230             ok(*blob->pbData == berDecoded, "Unexpected value\n");
1231         LocalFree(buf);
1232     }
1233 }
1234
1235 struct Constraints2
1236 {
1237     CERT_BASIC_CONSTRAINTS2_INFO info;
1238     const BYTE *encoded;
1239 };
1240
1241 static const struct Constraints2 constraints2[] = {
1242  /* empty constraints */
1243  { { FALSE, FALSE, 0}, "\x30\x00" },
1244  /* can be a CA */
1245  { { TRUE,  FALSE, 0}, "\x30\x03\x01\x01\xff" },
1246  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1247   * but that's not the case
1248   */
1249  { { FALSE, TRUE,  0}, "\x30\x03\x02\x01\x00" },
1250  /* can be a CA and has path length constraints set */
1251  { { TRUE,  TRUE,  1}, "\x30\x06\x01\x01\xff\x02\x01\x01" },
1252 };
1253
1254 static void test_encodeBasicConstraints(DWORD dwEncoding)
1255 {
1256     DWORD i;
1257
1258     /* First test with the simpler info2 */
1259     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1260     {
1261         BOOL ret;
1262         BYTE *buf = NULL;
1263         DWORD bufSize = 0;
1264
1265         ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1266          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1267          &bufSize);
1268         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1269         if (buf)
1270         {
1271             ok(bufSize == constraints2[i].encoded[1] + 2,
1272              "Expected %d bytes, got %ld\n", constraints2[i].encoded[1] + 2,
1273              bufSize);
1274             ok(!memcmp(buf, constraints2[i].encoded,
1275              constraints2[i].encoded[1] + 2), "Unexpected value\n");
1276             LocalFree(buf);
1277         }
1278     }
1279 }
1280
1281 static void test_decodeBasicConstraints(DWORD dwEncoding)
1282 {
1283     static const BYTE inverted[] = "\x30\x06\x02\x01\x01\x01\x01\xff";
1284     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 },
1285      "\x30\x06\x01\x01\x01\x02\x01\x01" };
1286     DWORD i;
1287     BOOL ret;
1288     BYTE *buf = NULL;
1289     DWORD bufSize = 0;
1290
1291     /* First test with simpler info2 */
1292     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1293     {
1294         ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1295          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1296          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1297         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1298         if (buf)
1299         {
1300             CERT_BASIC_CONSTRAINTS2_INFO *info =
1301              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1302
1303             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1304              "Unexpected value\n");
1305             LocalFree(buf);
1306         }
1307     }
1308     /* Check with the order of encoded elements inverted */
1309     buf = (PBYTE)1;
1310     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1311      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1312      &bufSize);
1313     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1314      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1315     ok(!buf, "Expected buf to be set to NULL\n");
1316     /* Check with a non-DER bool */
1317     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1318      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1319      (BYTE *)&buf, &bufSize);
1320     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1321     if (buf)
1322     {
1323         CERT_BASIC_CONSTRAINTS2_INFO *info =
1324          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1325
1326         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
1327         LocalFree(buf);
1328     }
1329     /* Check with a non-basic constraints value */
1330     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1331      names[0].encoded, names[0].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1332      (BYTE *)&buf, &bufSize);
1333     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1334      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1335 }
1336
1337 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
1338  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
1339  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1340
1341 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
1342  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
1343  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
1344  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1345
1346 static void test_encodeSequenceOfAny(DWORD dwEncoding)
1347 {
1348     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
1349     CRYPT_SEQUENCE_OF_ANY seq;
1350     DWORD i;
1351     BOOL ret;
1352     BYTE *buf = NULL;
1353     DWORD bufSize = 0;
1354
1355     /* Encode a homogenous sequence */
1356     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
1357     {
1358         blobs[i].cbData = ints[i].encoded[1] + 2;
1359         blobs[i].pbData = (BYTE *)ints[i].encoded;
1360     }
1361     seq.cValue = sizeof(ints) / sizeof(ints[0]);
1362     seq.rgValue = blobs;
1363
1364     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1365      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1366     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1367     if (buf)
1368     {
1369         ok(bufSize == sizeof(intSequence), "Expected %d bytes, got %ld\n",
1370          sizeof(intSequence), bufSize);
1371         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
1372         LocalFree(buf);
1373     }
1374     /* Change the type of the first element in the sequence, and give it
1375      * another go
1376      */
1377     blobs[0].cbData = times[0].encodedTime[1] + 2;
1378     blobs[0].pbData = (BYTE *)times[0].encodedTime;
1379     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1380      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1381     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1382     if (buf)
1383     {
1384         ok(bufSize == sizeof(mixedSequence), "Expected %d bytes, got %ld\n",
1385          sizeof(mixedSequence), bufSize);
1386         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
1387          "Unexpected value\n");
1388         LocalFree(buf);
1389     }
1390 }
1391
1392 static void test_decodeSequenceOfAny(DWORD dwEncoding)
1393 {
1394     BOOL ret;
1395     BYTE *buf = NULL;
1396     DWORD bufSize = 0;
1397
1398     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
1399      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1400     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1401     if (buf)
1402     {
1403         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1404         DWORD i;
1405
1406         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1407          "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1408          seq->cValue);
1409         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
1410         {
1411             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
1412              "Expected %d bytes, got %ld\n", ints[i].encoded[1] + 2,
1413              seq->rgValue[i].cbData);
1414             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
1415              ints[i].encoded[1] + 2), "Unexpected value\n");
1416         }
1417         LocalFree(buf);
1418     }
1419     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
1420      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1421      &bufSize);
1422     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1423     if (buf)
1424     {
1425         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1426
1427         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1428          "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1429          seq->cValue);
1430         /* Just check the first element since it's all that changed */
1431         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
1432          "Expected %d bytes, got %ld\n", times[0].encodedTime[1] + 2,
1433          seq->rgValue[0].cbData);
1434         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
1435          times[0].encodedTime[1] + 2), "Unexpected value\n");
1436         LocalFree(buf);
1437     }
1438 }
1439
1440 struct encodedExtensions
1441 {
1442     CERT_EXTENSIONS exts;
1443     const BYTE *encoded;
1444 };
1445
1446 static CERT_EXTENSION criticalExt =
1447  { szOID_BASIC_CONSTRAINTS2, TRUE, { 8, "\x30\x06\x01\x01\xff\x02\x01\x01" } };
1448 static CERT_EXTENSION nonCriticalExt =
1449  { szOID_BASIC_CONSTRAINTS2, FALSE, { 8, "\x30\x06\x01\x01\xff\x02\x01\x01" } };
1450
1451 static const struct encodedExtensions exts[] = {
1452  { { 0, NULL }, "\x30\x00" },
1453  { { 1, &criticalExt }, "\x30\x14\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff"
1454   "\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01" },
1455  { { 1, &nonCriticalExt }, "\x30\x11\x30\x0f\x06\x03\x55\x1d\x13"
1456   "\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01" },
1457 };
1458
1459 static void test_encodeExtensions(DWORD dwEncoding)
1460 {
1461     DWORD i;
1462
1463     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1464     {
1465         BOOL ret;
1466         BYTE *buf = NULL;
1467         DWORD bufSize = 0;
1468
1469         ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
1470          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1471         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1472         if (buf)
1473         {
1474             ok(bufSize == exts[i].encoded[1] + 2,
1475              "Expected %d bytes, got %ld\n", exts[i].encoded[1] + 2, bufSize);
1476             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
1477              "Unexpected value\n");
1478             LocalFree(buf);
1479         }
1480     }
1481 }
1482
1483 static void test_decodeExtensions(DWORD dwEncoding)
1484 {
1485     DWORD i;
1486
1487     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1488     {
1489         BOOL ret;
1490         BYTE *buf = NULL;
1491         DWORD bufSize = 0;
1492
1493         ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
1494          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1495          NULL, (BYTE *)&buf, &bufSize);
1496         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1497         if (buf)
1498         {
1499             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
1500             DWORD j;
1501
1502             ok(ext->cExtension == exts[i].exts.cExtension,
1503              "Expected %ld extensions, see %ld\n", exts[i].exts.cExtension,
1504              ext->cExtension);
1505             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
1506             {
1507                 ok(!strcmp(ext->rgExtension[j].pszObjId,
1508                  exts[i].exts.rgExtension[j].pszObjId),
1509                  "Expected OID %s, got %s\n",
1510                  exts[i].exts.rgExtension[j].pszObjId,
1511                  ext->rgExtension[j].pszObjId);
1512                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
1513                  exts[i].exts.rgExtension[j].Value.pbData,
1514                  exts[i].exts.rgExtension[j].Value.cbData),
1515                  "Unexpected value\n");
1516             }
1517             LocalFree(buf);
1518         }
1519     }
1520 }
1521
1522 /* MS encodes public key info with a NULL if the algorithm identifier's
1523  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
1524  * it encodes them by omitting the algorithm parameters.  This latter approach
1525  * seems more correct, so accept either form.
1526  */
1527 struct encodedPublicKey
1528 {
1529     CERT_PUBLIC_KEY_INFO info;
1530     const BYTE *encoded;
1531     const BYTE *encodedNoNull;
1532     CERT_PUBLIC_KEY_INFO decoded;
1533 };
1534
1535 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
1536  0xe, 0xf };
1537 static const BYTE params[] = { 0x02, 0x01, 0x01 };
1538
1539 static const struct encodedPublicKey pubKeys[] = {
1540  /* with a bogus OID */
1541  { { { "1.2.3", { 0, NULL } }, { 0, NULL, 0 } },
1542   "\x30\x0b\x30\x06\x06\x02\x2a\x03\x05\x00\x03\x01\x00",
1543   "\x30\x09\x30\x04\x06\x02\x2a\x03\x03\x01\x00",
1544   { { "1.2.3", { 2, "\x05\x00" } }, { 0, NULL, 0 } } },
1545  /* some normal keys */
1546  { { { szOID_RSA, { 0, NULL } }, { 0, NULL, 0} },
1547   "\x30\x0f\x30\x0a\x06\x06\x2a\x86\x48\x86\xf7\x0d\x05\x00\x03\x01\x00",
1548   "\x30\x0d\x30\x08\x06\x06\x2a\x86\x48\x86\xf7\x0d\x03\x01\x00",
1549   { { szOID_RSA, { 2, "\x05\x00" } }, { 0, NULL, 0 } } },
1550  { { { szOID_RSA, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
1551   "\x30\x1f\x30\x0a\x06\x06\x2a\x86\x48\x86\xf7\x0d\x05\x00\x03\x11\x00\x00\x01"
1552   "\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
1553   "\x30\x1d\x30\x08\x06\x06\x2a\x86\x48\x86\xf7\x0d\x03\x11\x00\x00\x01"
1554   "\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f",
1555   { { szOID_RSA, { 2, "\x05\x00" } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
1556  /* with add'l parameters--note they must be DER-encoded */
1557  { { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
1558   (BYTE *)aKey, 0 } },
1559   "\x30\x20\x30\x0b\x06\x06\x2a\x86\x48\x86\xf7\x0d\x02\x01\x01"
1560   "\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
1561   "\x0f",
1562   "\x30\x20\x30\x0b\x06\x06\x2a\x86\x48\x86\xf7\x0d\x02\x01\x01"
1563   "\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
1564   "\x0f",
1565   { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
1566   (BYTE *)aKey, 0 } } },
1567 };
1568
1569 static void test_encodePublicKeyInfo(DWORD dwEncoding)
1570 {
1571     DWORD i;
1572
1573     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
1574     {
1575         BOOL ret;
1576         BYTE *buf = NULL;
1577         DWORD bufSize = 0;
1578
1579         ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1580          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1581          &bufSize);
1582         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1583         if (buf)
1584         {
1585             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
1586              bufSize == pubKeys[i].encodedNoNull[1] + 2,
1587              "Expected %d or %d bytes, got %ld\n", pubKeys[i].encoded[1] + 2,
1588              pubKeys[i].encodedNoNull[1] + 2, bufSize);
1589             if (bufSize == pubKeys[i].encoded[1] + 2)
1590                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
1591                  "Unexpected value\n");
1592             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
1593                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
1594                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
1595             LocalFree(buf);
1596         }
1597     }
1598 }
1599
1600 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
1601  const CERT_PUBLIC_KEY_INFO *got)
1602 {
1603     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
1604      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
1605      got->Algorithm.pszObjId);
1606     ok(expected->Algorithm.Parameters.cbData ==
1607      got->Algorithm.Parameters.cbData,
1608      "Expected parameters of %ld bytes, got %ld\n",
1609      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
1610     if (expected->Algorithm.Parameters.cbData)
1611         ok(!memcmp(expected->Algorithm.Parameters.pbData,
1612          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
1613          "Unexpected algorithm parameters\n");
1614     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
1615      "Expected public key of %ld bytes, got %ld\n",
1616      expected->PublicKey.cbData, got->PublicKey.cbData);
1617     if (expected->PublicKey.cbData)
1618         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
1619          got->PublicKey.cbData), "Unexpected public key value\n");
1620 }
1621
1622 static void test_decodePublicKeyInfo(DWORD dwEncoding)
1623 {
1624     static const BYTE bogusPubKeyInfo[] =
1625      "\x30\x22\x30\x0d\x06\x06\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x01\x01"
1626      "\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
1627      "\x0f";
1628     DWORD i;
1629     BOOL ret;
1630     BYTE *buf = NULL;
1631     DWORD bufSize = 0;
1632
1633     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
1634     {
1635         /* The NULL form decodes to the decoded member */
1636         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1637          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1638          NULL, (BYTE *)&buf, &bufSize);
1639         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1640         if (buf)
1641         {
1642             comparePublicKeyInfo(&pubKeys[i].decoded,
1643              (CERT_PUBLIC_KEY_INFO *)buf);
1644             LocalFree(buf);
1645         }
1646         /* The non-NULL form decodes to the original */
1647         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1648          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
1649          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1650         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1651         if (buf)
1652         {
1653             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
1654             LocalFree(buf);
1655         }
1656     }
1657     /* Test with bogus (not valid DER) parameters */
1658     ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1659      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1660      NULL, (BYTE *)&buf, &bufSize);
1661     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1662      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1663 }
1664
1665 static const BYTE v1Cert[] = "\x30\x33\x02\x00\x30\x02\x06\x00\x30\x22\x18"
1666  "\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x18\x0f\x31"
1667  "\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x30\x07\x30\x02\x06"
1668  "\x00\x03\x01\x00";
1669 static const BYTE v2Cert[] = "\x30\x38\xa0\x03\x02\x01\x01\x02\x00\x30\x02\x06"
1670  "\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30"
1671  "\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x30"
1672  "\x07\x30\x02\x06\x00\x03\x01\x00";
1673 static const BYTE v3Cert[] = "\x30\x38\xa0\x03\x02\x01\x02\x02\x00\x30\x02\x06"
1674  "\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30"
1675  "\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x30"
1676  "\x07\x30\x02\x06\x00\x03\x01\x00";
1677 static const BYTE v1CertWithConstraints[] = "\x30\x4b\x02\x00\x30\x02\x06\x00"
1678  "\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a"
1679  "\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x30\x07"
1680  "\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14\x30\x12\x06\x03\x55\x1d\x13\x01"
1681  "\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01";
1682 static const BYTE v1CertWithSerial[] = "\x30\x4c\x02\x01\x01\x30\x02\x06\x00"
1683  "\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a"
1684  "\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30\x30\x5a\x30\x07"
1685  "\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14\x30\x12\x06\x03\x55\x1d\x13\x01"
1686  "\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01\x01";
1687 static const BYTE bigCert[] = "\x30\x7a\x02\x01\x01\x30\x02\x06\x00"
1688  "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e\x20\x4c"
1689  "\x61\x6e\x67\x00\x30\x22\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30"
1690  "\x30\x30\x30\x5a\x18\x0f\x31\x36\x30\x31\x30\x31\x30\x31\x30\x30\x30\x30\x30"
1691  "\x30\x5a\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x13\x0a\x4a\x75\x61\x6e"
1692  "\x20\x4c\x61\x6e\x67\x00\x30\x07\x30\x02\x06\x00\x03\x01\x00\xa3\x16\x30\x14"
1693  "\x30\x12\x06\x03\x55\x1d\x13\x01\x01\xff\x04\x08\x30\x06\x01\x01\xff\x02\x01"
1694  "\x01";
1695 /* This is the encoded form of the printable string "Juan Lang" */
1696 static const BYTE encodedCommonName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11,
1697  0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c,
1698  0x61, 0x6e, 0x67, 0x00 };
1699 static const BYTE serialNum[] = { 0x01 };
1700
1701 static void test_encodeCertToBeSigned(DWORD dwEncoding)
1702 {
1703     BOOL ret;
1704     BYTE *buf = NULL;
1705     DWORD size = 0;
1706     CERT_INFO info = { 0 };
1707
1708     /* Test with NULL pvStructInfo */
1709     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
1710      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1711     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1712      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1713     /* Test with a V1 cert */
1714     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1715      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1716     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1717     if (buf)
1718     {
1719         ok(size == v1Cert[1] + 2, "Expected size %d, got %ld\n",
1720          v1Cert[1] + 2, size);
1721         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
1722         LocalFree(buf);
1723     }
1724     /* Test v2 cert */
1725     info.dwVersion = CERT_V2;
1726     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1727      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1728     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1729     if (buf)
1730     {
1731         ok(size == v2Cert[1] + 2, "Expected size %d, got %ld\n",
1732          v3Cert[1] + 2, size);
1733         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
1734         LocalFree(buf);
1735     }
1736     /* Test v3 cert */
1737     info.dwVersion = CERT_V3;
1738     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1739      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1740     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1741     if (buf)
1742     {
1743         ok(size == v3Cert[1] + 2, "Expected size %d, got %ld\n",
1744          v3Cert[1] + 2, size);
1745         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
1746         LocalFree(buf);
1747     }
1748     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
1749      * API doesn't prevent it)
1750      */
1751     info.dwVersion = CERT_V1;
1752     info.cExtension = 1;
1753     info.rgExtension = &criticalExt;
1754     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1755      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1756     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1757     if (buf)
1758     {
1759         ok(size == v1CertWithConstraints[1] + 2, "Expected size %d, got %ld\n",
1760          v1CertWithConstraints[1] + 2, size);
1761         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
1762         LocalFree(buf);
1763     }
1764     /* test v1 cert with a serial number */
1765     info.SerialNumber.cbData = sizeof(serialNum);
1766     info.SerialNumber.pbData = (BYTE *)serialNum;
1767     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1768      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1769     if (buf)
1770     {
1771         ok(size == v1CertWithSerial[1] + 2, "Expected size %d, got %ld\n",
1772          v1CertWithSerial[1] + 2, size);
1773         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
1774         LocalFree(buf);
1775     }
1776     /* Test v1 cert with an issuer name, a subject name, and a serial number */
1777     info.Issuer.cbData = sizeof(encodedCommonName);
1778     info.Issuer.pbData = (BYTE *)encodedCommonName;
1779     info.Subject.cbData = sizeof(encodedCommonName);
1780     info.Subject.pbData = (BYTE *)encodedCommonName;
1781     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
1782      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1783     if (buf)
1784     {
1785         ok(size == bigCert[1] + 2, "Expected size %d, got %ld\n",
1786          bigCert[1] + 2, size);
1787         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
1788         LocalFree(buf);
1789     }
1790     /* for now, I let more interesting tests be done for each subcomponent,
1791      * rather than retesting them all here.
1792      */
1793 }
1794
1795 static void test_decodeCertToBeSigned(DWORD dwEncoding)
1796 {
1797     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
1798      v1CertWithConstraints, v1CertWithSerial };
1799     BOOL ret;
1800     BYTE *buf = NULL;
1801     DWORD size = 0, i;
1802
1803     /* Test with NULL pbEncoded */
1804     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
1805      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1806     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1807      "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
1808     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
1809      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1810     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1811      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1812     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
1813      * minimum a cert must have a non-zero serial number, an issuer, and a
1814      * subject.
1815      * It's hard to match the errors precisely sometimes, so accept one
1816      * that only wine gives as long as it fails
1817      */
1818     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
1819     {
1820         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
1821          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1822          (BYTE *)&buf, &size);
1823         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1824          GetLastError() == CRYPT_E_ASN1_BADTAG),
1825          "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1826     }
1827     /* Now check with serial number, subject and issuer specified */
1828     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
1829      bigCert[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1830     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1831     if (buf)
1832     {
1833         CERT_INFO *info = (CERT_INFO *)buf;
1834
1835         ok(size >= sizeof(CERT_INFO), "Expected size at least %d, got %ld\n",
1836          sizeof(CERT_INFO), size);
1837         ok(info->SerialNumber.cbData == 1,
1838          "Expected serial number size 1, got %ld\n", info->SerialNumber.cbData);
1839         ok(*info->SerialNumber.pbData == *serialNum,
1840          "Expected serial number %d, got %d\n", *serialNum,
1841          *info->SerialNumber.pbData);
1842         ok(info->Issuer.cbData == sizeof(encodedCommonName),
1843          "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
1844          info->Issuer.cbData);
1845         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
1846          "Unexpected issuer\n");
1847         ok(info->Subject.cbData == sizeof(encodedCommonName),
1848          "Expected subject of %d bytes, got %ld\n", sizeof(encodedCommonName),
1849          info->Subject.cbData);
1850         ok(!memcmp(info->Subject.pbData, encodedCommonName,
1851          info->Subject.cbData), "Unexpected subject\n");
1852         LocalFree(buf);
1853     }
1854 }
1855
1856 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
1857  0xe, 0xf };
1858
1859 static const BYTE signedBigCert[] = {
1860  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
1861  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
1862  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
1863  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
1864  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
1865  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
1866  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
1867  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
1868  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
1869  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
1870  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
1871  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
1872
1873 static void test_encodeCert(DWORD dwEncoding)
1874 {
1875     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
1876      * also that bigCert is a NULL-terminated string, so don't count its
1877      * last byte (otherwise the signed cert won't decode.)
1878      */
1879     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert) - 1, (BYTE *)bigCert },
1880      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
1881     BOOL ret;
1882     BYTE *buf = NULL;
1883     DWORD bufSize = 0;
1884
1885     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
1886      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1887     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1888     if (buf)
1889     {
1890         ok(bufSize == sizeof(signedBigCert), "Expected size %d, got %ld\n",
1891          sizeof(signedBigCert), bufSize);
1892         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
1893         LocalFree(buf);
1894     }
1895 }
1896
1897 static void test_decodeCert(DWORD dwEncoding)
1898 {
1899     BOOL ret;
1900     BYTE *buf = NULL;
1901     DWORD size = 0;
1902
1903     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
1904      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1905     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1906     if (buf)
1907     {
1908         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
1909
1910         ok(info->ToBeSigned.cbData == sizeof(bigCert) - 1,
1911          "Expected cert to be %d bytes, got %ld\n", sizeof(bigCert) - 1,
1912          info->ToBeSigned.cbData);
1913         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
1914          "Unexpected cert\n");
1915         ok(info->Signature.cbData == sizeof(hash),
1916          "Expected signature size %d, got %ld\n", sizeof(hash),
1917          info->Signature.cbData);
1918         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
1919          "Unexpected signature\n");
1920         LocalFree(buf);
1921     }
1922 }
1923
1924 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
1925  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
1926  0x30, 0x5a };
1927 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
1928  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
1929  0x30, 0x30, 0x30, 0x30, 0x5a };
1930 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
1931  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
1932  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
1933  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
1934  0x5a };
1935 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
1936  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
1937  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
1938  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
1939  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
1940  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
1941 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
1942  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
1943  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
1944  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
1945  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
1946  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
1947 static const BYTE v1CRLWithExt[] = { 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x30,
1948  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
1949  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31, 0x36,
1950  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
1951  0x30, 0x2c, 0x30, 0x2a, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
1952  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14,
1953  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
1954  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
1955
1956 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
1957 {
1958     BOOL ret;
1959     BYTE *buf = NULL;
1960     DWORD size = 0;
1961     CRL_INFO info = { 0 };
1962     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
1963
1964     /* Test with a V1 CRL */
1965     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
1966      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1967     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1968     if (buf)
1969     {
1970         ok(size == sizeof(v1CRL), "Expected size %d, got %ld\n",
1971          sizeof(v1CRL), size);
1972         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
1973         LocalFree(buf);
1974     }
1975     /* Test v2 CRL */
1976     info.dwVersion = CRL_V2;
1977     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
1978      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1979     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1980     if (buf)
1981     {
1982         ok(size == v2CRL[1] + 2, "Expected size %d, got %ld\n",
1983          v2CRL[1] + 2, size);
1984         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
1985         LocalFree(buf);
1986     }
1987     /* v1 CRL with a name */
1988     info.dwVersion = CRL_V1;
1989     info.Issuer.cbData = sizeof(encodedCommonName);
1990     info.Issuer.pbData = (BYTE *)encodedCommonName;
1991     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
1992      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1993     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1994     if (buf)
1995     {
1996         ok(size == sizeof(v1CRLWithIssuer), "Expected size %d, got %ld\n",
1997          sizeof(v1CRLWithIssuer), size);
1998         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
1999         LocalFree(buf);
2000     }
2001     /* v1 CRL with a name and a NULL entry pointer */
2002     info.cCRLEntry = 1;
2003     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2004      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2005     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2006      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2007     /* now set an empty entry */
2008     info.rgCRLEntry = &entry;
2009     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2010      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2011     if (buf)
2012     {
2013         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
2014          "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEmptyEntry),
2015          size);
2016         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
2017          "Got unexpected value\n");
2018         LocalFree(buf);
2019     }
2020     /* an entry with a serial number */
2021     entry.SerialNumber.cbData = sizeof(serialNum);
2022     entry.SerialNumber.pbData = (BYTE *)serialNum;
2023     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2024      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2025     if (buf)
2026     {
2027         ok(size == sizeof(v1CRLWithIssuerAndEntry),
2028          "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEntry), size);
2029         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
2030          "Got unexpected value\n");
2031         LocalFree(buf);
2032     }
2033     /* and finally, an entry with an extension */
2034     entry.cExtension = 1;
2035     entry.rgExtension = &criticalExt;
2036     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2037      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2038     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2039     if (buf)
2040     {
2041         ok(size == sizeof(v1CRLWithExt), "Expected size %d, got %ld\n",
2042          sizeof(v1CRLWithExt), size);
2043         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
2044         LocalFree(buf);
2045     }
2046 }
2047
2048 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
2049 {
2050     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
2051     BOOL ret;
2052     BYTE *buf = NULL;
2053     DWORD size = 0, i;
2054
2055     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
2056     {
2057         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2058          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2059          (BYTE *)&buf, &size);
2060         /* It's hard to match the errors precisely sometimes, so accept one
2061          * that only wine gives as long as it fails
2062          */
2063         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2064          GetLastError() == CRYPT_E_ASN1_BADTAG),
2065          "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2066     }
2067     /* at a minimum, a CRL must contain an issuer: */
2068     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2069      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2070      (BYTE *)&buf, &size);
2071     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2072     if (buf)
2073     {
2074         CRL_INFO *info = (CRL_INFO *)buf;
2075
2076         ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2077          sizeof(CRL_INFO), size);
2078         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %ld\n",
2079          info->cCRLEntry);
2080         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2081          "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2082          info->Issuer.cbData);
2083         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2084          "Unexpected issuer\n");
2085         LocalFree(buf);
2086     }
2087     /* check decoding with an empty CRL entry */
2088     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2089      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
2090      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2091     todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2092      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2093     /* with a real CRL entry */
2094     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2095      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
2096      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2097     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2098     if (buf)
2099     {
2100         CRL_INFO *info = (CRL_INFO *)buf;
2101         CRL_ENTRY *entry;
2102
2103         ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2104          sizeof(CRL_INFO), size);
2105         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2106          info->cCRLEntry);
2107         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2108         entry = info->rgCRLEntry;
2109         ok(entry->SerialNumber.cbData == 1,
2110          "Expected serial number size 1, got %ld\n",
2111          entry->SerialNumber.cbData);
2112         ok(*entry->SerialNumber.pbData == *serialNum,
2113          "Expected serial number %d, got %d\n", *serialNum,
2114          *entry->SerialNumber.pbData);
2115         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2116          "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2117          info->Issuer.cbData);
2118         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2119          "Unexpected issuer\n");
2120         if (memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData))
2121         {
2122             printBytes("Expected", encodedCommonName,
2123              sizeof(encodedCommonName));
2124             printBytes("Got", info->Issuer.pbData, info->Issuer.cbData);
2125         }
2126     }
2127     /* and finally, with an extension */
2128     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2129      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
2130      NULL, (BYTE *)&buf, &size);
2131     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2132     if (buf)
2133     {
2134         CRL_INFO *info = (CRL_INFO *)buf;
2135         CRL_ENTRY *entry;
2136
2137         ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2138          sizeof(CRL_INFO), size);
2139         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2140          info->cCRLEntry);
2141         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2142         entry = info->rgCRLEntry;
2143         ok(entry->SerialNumber.cbData == 1,
2144          "Expected serial number size 1, got %ld\n",
2145          entry->SerialNumber.cbData);
2146         ok(*entry->SerialNumber.pbData == *serialNum,
2147          "Expected serial number %d, got %d\n", *serialNum,
2148          *entry->SerialNumber.pbData);
2149         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2150          "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2151          info->Issuer.cbData);
2152         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2153          "Unexpected issuer\n");
2154         /* Oddly, the extensions don't seem to be decoded. Is this just an MS
2155          * bug, or am I missing something?
2156          */
2157         ok(info->cExtension == 0, "Expected 0 extensions, got %ld\n",
2158          info->cExtension);
2159     }
2160 }
2161
2162 static void test_registerOIDFunction(void)
2163 {
2164     static const WCHAR bogusDll[] = { 'b','o','g','u','s','.','d','l','l',0 };
2165     BOOL ret;
2166
2167     /* oddly, this succeeds under WinXP; the function name key is merely
2168      * omitted.  This may be a side effect of the registry code, I don't know.
2169      * I don't check it because I doubt anyone would depend on it.
2170     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, NULL,
2171      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2172      */
2173     /* On windows XP, GetLastError is incorrectly being set with an HRESULT,
2174      * HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)
2175      */
2176     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo", NULL, bogusDll,
2177      NULL);
2178     ok(!ret && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() ==
2179      HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER)),
2180      "Expected ERROR_INVALID_PARAMETER: %ld\n", GetLastError());
2181     /* This has no effect, but "succeeds" on XP */
2182     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo",
2183      "1.2.3.4.5.6.7.8.9.10", NULL, NULL);
2184     ok(ret, "Expected pseudo-success, got %ld\n", GetLastError());
2185     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
2186      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2187     ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2188     ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject",
2189      "1.2.3.4.5.6.7.8.9.10");
2190     ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
2191     ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "bogus",
2192      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2193     ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2194     ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "bogus",
2195      "1.2.3.4.5.6.7.8.9.10");
2196     ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
2197     /* This has no effect */
2198     ret = CryptRegisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject",
2199      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2200     ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2201     /* Check with bogus encoding type: */
2202     ret = CryptRegisterOIDFunction(0, "CryptDllEncodeObject",
2203      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2204     ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2205     /* This is written with value 3 verbatim.  Thus, the encoding type isn't
2206      * (for now) treated as a mask.
2207      */
2208     ret = CryptRegisterOIDFunction(3, "CryptDllEncodeObject",
2209      "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL);
2210     ok(ret, "CryptRegisterOIDFunction failed: %ld\n", GetLastError());
2211     ret = CryptUnregisterOIDFunction(3, "CryptDllEncodeObject",
2212      "1.2.3.4.5.6.7.8.9.10");
2213     ok(ret, "CryptUnregisterOIDFunction failed: %ld\n", GetLastError());
2214 }
2215
2216 START_TEST(encode)
2217 {
2218     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
2219      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
2220     DWORD i;
2221
2222     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
2223     {
2224         test_encodeInt(encodings[i]);
2225         test_decodeInt(encodings[i]);
2226         test_encodeEnumerated(encodings[i]);
2227         test_decodeEnumerated(encodings[i]);
2228         test_encodeFiletime(encodings[i]);
2229         test_decodeFiletime(encodings[i]);
2230         test_encodeName(encodings[i]);
2231         test_decodeName(encodings[i]);
2232         test_encodeAltName(encodings[i]);
2233         test_decodeAltName(encodings[i]);
2234         test_encodeOctets(encodings[i]);
2235         test_decodeOctets(encodings[i]);
2236         test_encodeBits(encodings[i]);
2237         test_decodeBits(encodings[i]);
2238         test_encodeBasicConstraints(encodings[i]);
2239         test_decodeBasicConstraints(encodings[i]);
2240         test_encodeSequenceOfAny(encodings[i]);
2241         test_decodeSequenceOfAny(encodings[i]);
2242         test_encodeExtensions(encodings[i]);
2243         test_decodeExtensions(encodings[i]);
2244         test_encodePublicKeyInfo(encodings[i]);
2245         test_decodePublicKeyInfo(encodings[i]);
2246         test_encodeCertToBeSigned(encodings[i]);
2247         test_decodeCertToBeSigned(encodings[i]);
2248         test_encodeCert(encodings[i]);
2249         test_decodeCert(encodings[i]);
2250         test_encodeCRLToBeSigned(encodings[i]);
2251         test_decodeCRLToBeSigned(encodings[i]);
2252     }
2253     test_registerOIDFunction();
2254 }