ole32: Add a test for CoCreateInstance doing object hosting by
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29 struct encodedInt
30 {
31     int val;
32     const BYTE *encoded;
33 };
34
35 static const BYTE bin1[] = {0x02,0x01,0x01};
36 static const BYTE bin2[] = {0x02,0x01,0x7f};
37 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
38 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
39 static const BYTE bin5[] = {0x02,0x01,0x80};
40 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
41 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
42
43 static const struct encodedInt ints[] = {
44  { 1,          bin1 },
45  { 127,        bin2 },
46  { 128,        bin3 },
47  { 256,        bin4 },
48  { -128,       bin5 },
49  { -129,       bin6 },
50  { 0xbaddf00d, bin7 },
51 };
52
53 struct encodedBigInt
54 {
55     const BYTE *val;
56     const BYTE *encoded;
57     const BYTE *decoded;
58 };
59
60 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
61 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
62 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
63
64 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
65 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
66 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
67
68 static const struct encodedBigInt bigInts[] = {
69  { bin8, bin9, bin10 },
70  { bin11, bin12, bin13 },
71 };
72
73 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
74 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
75 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
76 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
77
78 /* Decoded is the same as original, so don't bother storing a separate copy */
79 static const struct encodedBigInt bigUInts[] = {
80  { bin14, bin15, NULL },
81  { bin16, bin17, NULL },
82 };
83
84 static void test_encodeInt(DWORD dwEncoding)
85 {
86     DWORD bufSize = 0;
87     int i;
88     BOOL ret;
89     CRYPT_INTEGER_BLOB blob;
90     BYTE *buf = NULL;
91
92     /* CryptEncodeObjectEx with NULL bufSize crashes..
93     ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
94      NULL);
95      */
96     /* check bogus encoding */
97     ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98      &bufSize);
99     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
100      "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
101     /* check with NULL integer buffer.  Windows XP incorrectly returns an
102      * NTSTATUS.
103      */
104     ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
105      &bufSize);
106     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
107      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
108     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
109     {
110         /* encode as normal integer */
111         ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
112          NULL, NULL, &bufSize);
113         ok(ret, "Expected success, got %ld\n", GetLastError());
114         ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
115          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
116         ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
117         if (buf)
118         {
119             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
120              buf[0]);
121             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
122              buf[1], ints[i].encoded[1]);
123             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
124              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
125             LocalFree(buf);
126         }
127         /* encode as multibyte integer */
128         blob.cbData = sizeof(ints[i].val);
129         blob.pbData = (BYTE *)&ints[i].val;
130         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
131          0, NULL, NULL, &bufSize);
132         ok(ret, "Expected success, got %ld\n", GetLastError());
133         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
134          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
135         ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
136         if (buf)
137         {
138             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
139              buf[0]);
140             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
141              buf[1], ints[i].encoded[1]);
142             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
143              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
144             LocalFree(buf);
145         }
146     }
147     /* encode a couple bigger ints, just to show it's little-endian and leading
148      * sign bytes are dropped
149      */
150     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
151     {
152         blob.cbData = strlen((const char*)bigInts[i].val);
153         blob.pbData = (BYTE *)bigInts[i].val;
154         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
155          0, NULL, NULL, &bufSize);
156         ok(ret, "Expected success, got %ld\n", GetLastError());
157         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
158          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
159         ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
160         if (buf)
161         {
162             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
163              buf[0]);
164             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
165              buf[1], bigInts[i].encoded[1]);
166             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
167              bigInts[i].encoded[1] + 1),
168              "Encoded value didn't match expected\n");
169             LocalFree(buf);
170         }
171     }
172     /* and, encode some uints */
173     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
174     {
175         blob.cbData = strlen((const char*)bigUInts[i].val);
176         blob.pbData = (BYTE*)bigUInts[i].val;
177         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
178          0, NULL, NULL, &bufSize);
179         ok(ret, "Expected success, got %ld\n", GetLastError());
180         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
181          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
182         ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
183         if (buf)
184         {
185             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
186              buf[0]);
187             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
188              buf[1], bigUInts[i].encoded[1]);
189             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
190              bigUInts[i].encoded[1] + 1),
191              "Encoded value didn't match expected\n");
192             LocalFree(buf);
193         }
194     }
195 }
196
197 static void test_decodeInt(DWORD dwEncoding)
198 {
199     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
200     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
201     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
202     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
203     BYTE *buf = NULL;
204     DWORD bufSize = 0;
205     int i;
206     BOOL ret;
207
208     /* CryptDecodeObjectEx with NULL bufSize crashes..
209     ret = CryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded, 
210      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
211      */
212     /* check bogus encoding */
213     ret = CryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded, 
214      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
215     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
216      "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
217     /* check with NULL integer buffer */
218     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
219      &bufSize);
220     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
221      "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
222     /* check with a valid, but too large, integer */
223     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
224      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
225     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
226      "Expected CRYPT_E_ASN1_LARGE, got %ld\n", GetLastError());
227     /* check with a DER-encoded string */
228     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
229      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
230     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
231      "Expected CRYPT_E_ASN1_BADTAG, got %ld\n", GetLastError());
232     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
233     {
234         /* When the output buffer is NULL, this always succeeds */
235         SetLastError(0xdeadbeef);
236         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
237          (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
238          &bufSize);
239         ok(ret && GetLastError() == NOERROR,
240          "Expected success and NOERROR, got %ld\n", GetLastError());
241         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242          (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2,
243          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
244         ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
245         ok(bufSize == sizeof(int), "Wrong size %ld\n", bufSize);
246         ok(buf != NULL, "Expected allocated buffer\n");
247         if (buf)
248         {
249             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
250              ints[i].val, *(int *)buf);
251             LocalFree(buf);
252         }
253     }
254     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
255     {
256         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
257          (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
258          &bufSize);
259         ok(ret && GetLastError() == NOERROR,
260          "Expected success and NOERROR, got %ld\n", GetLastError());
261         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
262          (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2,
263          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
264         ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
265         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %ld\n", bufSize);
266         ok(buf != NULL, "Expected allocated buffer\n");
267         if (buf)
268         {
269             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
270
271             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
272              "Expected len %d, got %ld\n", lstrlenA((const char*)bigInts[i].decoded),
273              blob->cbData);
274             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
275              "Unexpected value\n");
276             LocalFree(buf);
277         }
278     }
279     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
280     {
281         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
282          (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
283          &bufSize);
284         ok(ret && GetLastError() == NOERROR,
285          "Expected success and NOERROR, got %ld\n", GetLastError());
286         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
287          (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
288          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
289         ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
290         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %ld\n", bufSize);
291         ok(buf != NULL, "Expected allocated buffer\n");
292         if (buf)
293         {
294             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
295
296             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
297              "Expected len %d, got %ld\n", lstrlenA((const char*)bigUInts[i].val),
298              blob->cbData);
299             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
300              "Unexpected value\n");
301             LocalFree(buf);
302         }
303     }
304     /* Decode the value 1 with long-form length */
305     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
306      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
307     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
308     if (buf)
309     {
310         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
311         LocalFree(buf);
312     }
313     /* Try to decode some bogus large items */
314     /* The buffer size is smaller than the encoded length, so this should fail
315      * with CRYPT_E_ASN1_EOD if it's being decoded.
316      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
317      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
318      * So this test unfortunately isn't useful.
319     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
320      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
321     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
322      "Expected CRYPT_E_ASN1_LARGE, got %08lx\n", GetLastError());
323      */
324     /* This will try to decode the buffer and overflow it, check that it's
325      * caught.
326      */
327     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
328      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
329     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
330      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
331 }
332
333 static const BYTE bin18[] = {0x0a,0x01,0x01};
334 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
335
336 /* These are always encoded unsigned, and aren't constrained to be any
337  * particular value
338  */
339 static const struct encodedInt enums[] = {
340  { 1,    bin18 },
341  { -128, bin19 },
342 };
343
344 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
345  * X509_ENUMERATED.
346  */
347 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
348  szOID_CRL_REASON_CODE };
349
350 static void test_encodeEnumerated(DWORD dwEncoding)
351 {
352     DWORD i, j;
353
354     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
355     {
356         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
357         {
358             BOOL ret;
359             BYTE *buf = NULL;
360             DWORD bufSize = 0;
361
362             ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
363              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
364              &bufSize);
365             ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
366             if (buf)
367             {
368                 ok(buf[0] == 0xa,
369                  "Got unexpected type %d for enumerated (expected 0xa)\n",
370                  buf[0]);
371                 ok(buf[1] == enums[j].encoded[1],
372                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
373                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
374                  enums[j].encoded[1] + 1),
375                  "Encoded value of 0x%08x didn't match expected\n",
376                  enums[j].val);
377                 LocalFree(buf);
378             }
379         }
380     }
381 }
382
383 static void test_decodeEnumerated(DWORD dwEncoding)
384 {
385     DWORD i, j;
386
387     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
388     {
389         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
390         {
391             BOOL ret;
392             DWORD bufSize = sizeof(int);
393             int val;
394
395             ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
396              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
397              (BYTE *)&val, &bufSize);
398             ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
399             ok(bufSize == sizeof(int),
400              "Got unexpected size %ld for enumerated\n", bufSize);
401             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
402              val, enums[j].val);
403         }
404     }
405 }
406
407 struct encodedFiletime
408 {
409     SYSTEMTIME sysTime;
410     const BYTE *encodedTime;
411 };
412
413 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
414  const struct encodedFiletime *time)
415 {
416     FILETIME ft = { 0 };
417     BYTE *buf = NULL;
418     DWORD bufSize = 0;
419     BOOL ret;
420
421     ret = SystemTimeToFileTime(&time->sysTime, &ft);
422     ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
423     ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
424      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
425     /* years other than 1950-2050 are not allowed for encodings other than
426      * X509_CHOICE_OF_TIME.
427      */
428     if (structType == X509_CHOICE_OF_TIME ||
429      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
430     {
431         ok(ret, "CryptEncodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
432          GetLastError());
433         ok(buf != NULL, "Expected an allocated buffer\n");
434         if (buf)
435         {
436             ok(buf[0] == time->encodedTime[0],
437              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
438              buf[0]);
439             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %ld\n",
440              time->encodedTime[1], bufSize);
441             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
442              "Got unexpected value for time encoding\n");
443             LocalFree(buf);
444         }
445     }
446     else
447         ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
448          "Expected CRYPT_E_BAD_ENCODE, got 0x%08lx\n", GetLastError());
449 }
450
451 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
452  const struct encodedFiletime *time)
453 {
454     FILETIME ft1 = { 0 }, ft2 = { 0 };
455     DWORD size = sizeof(ft2);
456     BOOL ret;
457
458     ret = SystemTimeToFileTime(&time->sysTime, &ft1);
459     ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
460     ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
461      time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
462     /* years other than 1950-2050 are not allowed for encodings other than
463      * X509_CHOICE_OF_TIME.
464      */
465     if (structType == X509_CHOICE_OF_TIME ||
466      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
467     {
468         ok(ret, "CryptDecodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
469          GetLastError());
470         ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
471          "Got unexpected value for time decoding\n");
472     }
473     else
474         ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
475          "Expected CRYPT_E_ASN1_BADTAG, got 0x%08lx\n", GetLastError());
476 }
477
478 static const BYTE bin20[] = {
479     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
480 static const BYTE bin21[] = {
481     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
482 static const BYTE bin22[] = {
483     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
484
485 static const struct encodedFiletime times[] = {
486  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
487  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
488  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
489 };
490
491 static void test_encodeFiletime(DWORD dwEncoding)
492 {
493     DWORD i;
494
495     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
496     {
497         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
498         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
499         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
500     }
501 }
502
503 static const BYTE bin23[] = {
504     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
505 static const BYTE bin24[] = {
506     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
507 static const BYTE bin25[] = {
508     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
509 static const BYTE bin26[] = {
510     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
511 static const BYTE bin27[] = {
512     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
513 static const BYTE bin28[] = {
514     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
515 static const BYTE bin29[] = {
516     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
517 static const BYTE bin30[] = {
518     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
519 static const BYTE bin31[] = {
520     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
521 static const BYTE bin32[] = {
522     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
523 static const BYTE bin33[] = {
524     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
525 static const BYTE bin34[] = {
526     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
527 static const BYTE bin35[] = {
528     0x17,0x08, '4','5','0','6','0','6','1','6'};
529 static const BYTE bin36[] = {
530     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
531 static const BYTE bin37[] = {
532     0x18,0x04, '2','1','4','5'};
533 static const BYTE bin38[] = {
534     0x18,0x08, '2','1','4','5','0','6','0','6'};
535
536 static void test_decodeFiletime(DWORD dwEncoding)
537 {
538     static const struct encodedFiletime otherTimes[] = {
539      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
540      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
541      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
542      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
543      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
544      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
545      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
546      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
547      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
548      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
549      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
550      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
551     };
552     /* An oddball case that succeeds in Windows, but doesn't seem correct
553      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
554      */
555     static const unsigned char *bogusTimes[] = {
556      /* oddly, this succeeds on Windows, with year 2765
557      "\x18" "\x0f" "21r50606161000Z",
558       */
559      bin35,
560      bin36,
561      bin37,
562      bin38,
563     };
564     DWORD i, size;
565     FILETIME ft1 = { 0 }, ft2 = { 0 };
566     BOOL ret;
567
568     /* Check bogus length with non-NULL buffer */
569     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
570     ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
571     size = 1;
572     ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
573      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
574     ok(!ret && GetLastError() == ERROR_MORE_DATA,
575      "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
576     /* Normal tests */
577     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
578     {
579         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
580         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
581         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
582     }
583     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
584     {
585         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
586         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
587         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
588     }
589     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
590     {
591         size = sizeof(ft1);
592         ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
593          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
594         ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
595          "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
596     }
597 }
598
599 static const char commonName[] = "Juan Lang";
600 static const char surName[] = "Lang";
601
602 static const BYTE emptySequence[] = { 0x30, 0 };
603 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
604 static const BYTE twoRDNs[] = {
605     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
606     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
607     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
608
609 static const BYTE us[] = { 0x55, 0x53 };
610 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
611  0x74, 0x61 };
612 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
613  0x6f, 0x6c, 0x69, 0x73 };
614 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
615  0x76, 0x65, 0x72, 0x73 };
616 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
617  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
618 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
619  0x73, 0x74 };
620 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
621  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
622
623 #define _blob_of(arr) { sizeof(arr), (LPBYTE)arr }
624 const CERT_RDN_ATTR rdnAttrs[] = {
625  { "2.5.4.6", CERT_RDN_PRINTABLE_STRING,        _blob_of(us) },
626  { "2.5.4.8", CERT_RDN_PRINTABLE_STRING,        _blob_of(minnesota) },
627  { "2.5.4.7", CERT_RDN_PRINTABLE_STRING,        _blob_of(minneapolis) },
628  { "2.5.4.10", CERT_RDN_PRINTABLE_STRING,       _blob_of(codeweavers) },
629  { "2.5.4.11", CERT_RDN_PRINTABLE_STRING,       _blob_of(wine) },
630  { "2.5.4.3", CERT_RDN_PRINTABLE_STRING,        _blob_of(localhostAttr) },
631  { "1.2.840.113549.1.9.1", CERT_RDN_IA5_STRING, _blob_of(aric) },
632 };
633 const CERT_RDN_ATTR decodedRdnAttrs[] = {
634  { "2.5.4.6", CERT_RDN_PRINTABLE_STRING,        _blob_of(us) },
635  { "2.5.4.3", CERT_RDN_PRINTABLE_STRING,        _blob_of(localhostAttr) },
636  { "2.5.4.8", CERT_RDN_PRINTABLE_STRING,        _blob_of(minnesota) },
637  { "2.5.4.7", CERT_RDN_PRINTABLE_STRING,        _blob_of(minneapolis) },
638  { "2.5.4.10", CERT_RDN_PRINTABLE_STRING,       _blob_of(codeweavers) },
639  { "2.5.4.11", CERT_RDN_PRINTABLE_STRING,       _blob_of(wine) },
640  { "1.2.840.113549.1.9.1", CERT_RDN_IA5_STRING, _blob_of(aric) },
641 };
642 #undef _blob_of
643
644 static const BYTE encodedRDNAttrs[] = {
645 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
646 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
647 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
648 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
649 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
650 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
651 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
652 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
653 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
654 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
655 };
656
657 static void test_encodeName(DWORD dwEncoding)
658 {
659     CERT_RDN_ATTR attrs[2];
660     CERT_RDN rdn;
661     CERT_NAME_INFO info;
662     BYTE *buf = NULL;
663     DWORD size = 0;
664     BOOL ret;
665
666     /* Test with NULL pvStructInfo */
667     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
668      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
669     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
670      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
671     /* Test with empty CERT_NAME_INFO */
672     info.cRDN = 0;
673     info.rgRDN = NULL;
674     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
675      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
676     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
677     if (buf)
678     {
679         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
680          "Got unexpected encoding for empty name\n");
681         LocalFree(buf);
682     }
683     /* Test with bogus CERT_RDN */
684     info.cRDN = 1;
685     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
686      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
687     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
688      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
689     /* Test with empty CERT_RDN */
690     rdn.cRDNAttr = 0;
691     rdn.rgRDNAttr = NULL;
692     info.cRDN = 1;
693     info.rgRDN = &rdn;
694     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
695      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
696     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
697     if (buf)
698     {
699         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
700          "Got unexpected encoding for empty RDN array\n");
701         LocalFree(buf);
702     }
703     /* Test with bogus attr array */
704     rdn.cRDNAttr = 1;
705     rdn.rgRDNAttr = NULL;
706     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
707      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
708     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
709      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
710     /* oddly, a bogus OID is accepted by Windows XP; not testing.
711     attrs[0].pszObjId = "bogus";
712     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
713     attrs[0].Value.cbData = sizeof(commonName);
714     attrs[0].Value.pbData = (BYTE *)commonName;
715     rdn.cRDNAttr = 1;
716     rdn.rgRDNAttr = attrs;
717     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
718      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
719     ok(!ret, "Expected failure, got success\n");
720      */
721     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
722      * the encoded attributes to be swapped.
723      */
724     attrs[0].pszObjId = szOID_COMMON_NAME;
725     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
726     attrs[0].Value.cbData = sizeof(commonName);
727     attrs[0].Value.pbData = (BYTE *)commonName;
728     attrs[1].pszObjId = szOID_SUR_NAME;
729     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
730     attrs[1].Value.cbData = sizeof(surName);
731     attrs[1].Value.pbData = (BYTE *)surName;
732     rdn.cRDNAttr = 2;
733     rdn.rgRDNAttr = attrs;
734     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
735      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
736     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
737     if (buf)
738     {
739         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
740          "Got unexpected encoding for two RDN array\n");
741         LocalFree(buf);
742     }
743     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
744     rdn.cRDNAttr = 1;
745     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
746     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
747      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
748     ok(!ret && GetLastError() == E_INVALIDARG,
749      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
750     /* Test a more complex name */
751     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
752     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
753     info.cRDN = 1;
754     info.rgRDN = &rdn;
755     buf = NULL;
756     size = 0;
757     ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
758      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
759     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
760     if (ret)
761     {
762         ok(size == sizeof(encodedRDNAttrs), "Wrong size %ld\n", size);
763         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
764         LocalFree(buf);
765     }
766 }
767
768 static void compareNameValues(const CERT_NAME_VALUE *expected,
769  const CERT_NAME_VALUE *got)
770 {
771     ok(got->dwValueType == expected->dwValueType,
772      "Expected string type %ld, got %ld\n", expected->dwValueType,
773      got->dwValueType);
774     ok(got->Value.cbData == expected->Value.cbData,
775      "Unexpected data size, got %ld, expected %ld\n", got->Value.cbData,
776      expected->Value.cbData);
777     if (got->Value.cbData && got->Value.pbData)
778         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
779          min(got->Value.cbData, expected->Value.cbData)), "Unexpected value\n");
780 }
781
782 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
783  const CERT_RDN_ATTR *got)
784 {
785     if (expected->pszObjId && strlen(expected->pszObjId))
786     {
787         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
788          expected->pszObjId);
789         if (got->pszObjId)
790         {
791             ok(!strcmp(got->pszObjId, expected->pszObjId),
792              "Got unexpected OID %s, expected %s\n", got->pszObjId,
793              expected->pszObjId);
794         }
795     }
796     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
797      (const CERT_NAME_VALUE *)&got->dwValueType);
798 }
799
800 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
801 {
802     ok(got->cRDNAttr == expected->cRDNAttr,
803      "Expected %ld RDN attrs, got %ld\n", expected->cRDNAttr, got->cRDNAttr);
804     if (got->cRDNAttr)
805     {
806         DWORD i;
807
808         for (i = 0; i < got->cRDNAttr; i++)
809             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
810     }
811 }
812
813 static void compareNames(const CERT_NAME_INFO *expected,
814  const CERT_NAME_INFO *got)
815 {
816     ok(got->cRDN == expected->cRDN, "Expected %ld RDNs, got %ld\n",
817      expected->cRDN, got->cRDN);
818     if (got->cRDN)
819     {
820         DWORD i;
821
822         for (i = 0; i < got->cRDN; i++)
823             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
824     }
825 }
826
827 static void test_decodeName(DWORD dwEncoding)
828 {
829     BYTE *buf = NULL;
830     DWORD bufSize = 0;
831     BOOL ret;
832     CERT_RDN rdn;
833     CERT_NAME_INFO info = { 1, &rdn };
834
835     /* test empty name */
836     bufSize = 0;
837     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
838      emptySequence[1] + 2,
839      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
840      (BYTE *)&buf, &bufSize);
841     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
842     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
843      * decoder works the same way, so only test the count.
844      */
845     if (buf)
846     {
847         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %ld\n", bufSize);
848         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
849          "Expected 0 RDNs in empty info, got %ld\n",
850          ((CERT_NAME_INFO *)buf)->cRDN);
851         LocalFree(buf);
852     }
853     /* test empty RDN */
854     bufSize = 0;
855     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
856      emptyRDNs[1] + 2,
857      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
858      (BYTE *)&buf, &bufSize);
859     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
860     if (buf)
861     {
862         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
863
864         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
865          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
866          "Got unexpected value for empty RDN\n");
867         LocalFree(buf);
868     }
869     /* test two RDN attrs */
870     bufSize = 0;
871     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
872      twoRDNs[1] + 2,
873      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
874      (BYTE *)&buf, &bufSize);
875     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
876     if (buf)
877     {
878         CERT_RDN_ATTR attrs[] = {
879          { szOID_SUR_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
880           (BYTE *)surName } },
881          { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
882           (BYTE *)commonName } },
883         };
884
885         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
886         rdn.rgRDNAttr = attrs;
887         compareNames(&info, (CERT_NAME_INFO *)buf);
888         LocalFree(buf);
889     }
890     /* And, a slightly more complicated name */
891     buf = NULL;
892     bufSize = 0;
893     ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
894      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
895     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
896     if (ret)
897     {
898         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
899         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
900         compareNames(&info, (CERT_NAME_INFO *)buf);
901         LocalFree(buf);
902     }
903 }
904
905 struct EncodedNameValue
906 {
907     CERT_NAME_VALUE value;
908     const BYTE *encoded;
909 };
910
911 static const char bogusIA5[] = "\x80";
912 static const char bogusPrintable[] = "~";
913 static const char bogusNumeric[] = "A";
914 static const char bogusT61[] = "\xff";
915 static const BYTE bin39[] = { 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
916  0x67,0x00 };
917 static const BYTE bin40[] = { 0x16,0x05,0x4c,0x61,0x6e,0x67,0x00 };
918 static const BYTE bin41[] = { 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
919  0x67,0x00 };
920 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
921 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
922 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
923 static const BYTE bin45[] = { 0x14,0x02,0xff,0x00 };
924
925 struct EncodedNameValue nameValues[] = {
926  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
927      bin39 },
928  { { CERT_RDN_IA5_STRING, { sizeof(surName), (BYTE *)surName } }, bin40 },
929  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } }, bin41 },
930  /* The following tests succeed under Windows, but really should fail,
931   * they contain characters that are illegal for the encoding.  I'm
932   * including them to justify my lazy encoding.
933   */
934  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42 },
935  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
936      (BYTE *)bogusPrintable } }, bin43 },
937  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
938      bin44 },
939  { { CERT_RDN_T61_STRING, { sizeof(bogusT61), (BYTE *)bogusT61 } }, bin45 },
940 };
941
942
943 static void test_encodeNameValue(DWORD dwEncoding)
944 {
945     BYTE *buf = NULL;
946     DWORD size = 0, i;
947     BOOL ret;
948
949     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
950     {
951         ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
952          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
953          &size);
954         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
955         if (buf)
956         {
957             ok(size == nameValues[i].encoded[1] + 2,
958              "Expected size %d, got %ld\n", nameValues[i].encoded[1] + 2, size);
959             ok(!memcmp(buf, nameValues[i].encoded, size),
960              "Got unexpected encoding\n");
961             LocalFree(buf);
962         }
963     }
964 }
965
966 static void test_decodeNameValue(DWORD dwEncoding)
967 {
968     int i;
969     BYTE *buf = NULL;
970     DWORD bufSize = 0;
971     BOOL ret;
972
973     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
974     {
975         ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
976          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
977          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
978          (BYTE *)&buf, &bufSize);
979         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
980         if (buf)
981         {
982             compareNameValues(&nameValues[i].value,
983              (const CERT_NAME_VALUE *)buf);
984             LocalFree(buf);
985         }
986     }
987 }
988
989 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
990 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
991  'h','q','.','o','r','g',0 };
992 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
993  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
994  0x6f, 0x72, 0x67 };
995 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
996  0x575b, 0 };
997 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
998 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
999  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1000 static const BYTE localhost[] = { 127, 0, 0, 1 };
1001 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1002  0x01 };
1003
1004 static void test_encodeAltName(DWORD dwEncoding)
1005 {
1006     CERT_ALT_NAME_INFO info = { 0 };
1007     CERT_ALT_NAME_ENTRY entry = { 0 };
1008     BYTE *buf = NULL;
1009     DWORD size = 0;
1010     BOOL ret;
1011
1012     /* Test with empty info */
1013     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1014      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1015     if (buf)
1016     {
1017         ok(size == sizeof(emptySequence), "Wrong size %ld\n", size);
1018         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1019         LocalFree(buf);
1020     }
1021     /* Test with an empty entry */
1022     info.cAltEntry = 1;
1023     info.rgAltEntry = &entry;
1024     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1025      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1026     ok(!ret && GetLastError() == E_INVALIDARG,
1027      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1028     /* Test with an empty pointer */
1029     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1030     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1031      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1032     if (buf)
1033     {
1034         ok(size == sizeof(emptyURL), "Wrong size %ld\n", size);
1035         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1036         LocalFree(buf);
1037     }
1038     /* Test with a real URL */
1039     U(entry).pwszURL = (LPWSTR)url;
1040     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1041      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1042     if (buf)
1043     {
1044         ok(size == sizeof(encodedURL), "Wrong size %ld\n", size);
1045         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1046         LocalFree(buf);
1047     }
1048     /* Now with the URL containing an invalid IA5 char */
1049     U(entry).pwszURL = (LPWSTR)nihongoURL;
1050     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1051      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1052     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1053      "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
1054     /* The first invalid character is at index 7 */
1055     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1056      "Expected invalid char at index 7, got %ld\n",
1057      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1058     /* Now with the URL missing a scheme */
1059     U(entry).pwszURL = (LPWSTR)dnsName;
1060     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1061      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1062     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1063     if (buf)
1064     {
1065         /* This succeeds, but it shouldn't, so don't worry about conforming */
1066         LocalFree(buf);
1067     }
1068     /* Now with a DNS name */
1069     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1070     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1071      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1072     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1073     if (buf)
1074     {
1075         ok(size == sizeof(encodedDnsName), "Wrong size %ld\n", size);
1076         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1077         LocalFree(buf);
1078     }
1079     /* Test with an IP address */
1080     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1081     U(entry).IPAddress.cbData = sizeof(localhost);
1082     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1083     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1084      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1085     if (buf)
1086     {
1087         ok(size == sizeof(encodedIPAddr), "Wrong size %ld\n", size);
1088         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1089         LocalFree(buf);
1090     }
1091 }
1092
1093 static void test_decodeAltName(DWORD dwEncoding)
1094 {
1095     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1096      0x00, 0x00, 0x01 };
1097     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1098      0x01 };
1099     BOOL ret;
1100     BYTE *buf = NULL;
1101     DWORD bufSize = 0;
1102     CERT_ALT_NAME_INFO *info;
1103
1104     /* Test some bogus ones first */
1105     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1106      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1107      NULL, (BYTE *)&buf, &bufSize);
1108     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1109      "Expected CRYPT_E_ASN1_BADTAG, got %08lx\n", GetLastError());
1110     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1111      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1112      &bufSize);
1113     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1114      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1115     /* Now expected cases */
1116     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1117      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1118      &bufSize);
1119     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1120     if (buf)
1121     {
1122         info = (CERT_ALT_NAME_INFO *)buf;
1123
1124         ok(info->cAltEntry == 0, "Expected 0 entries, got %ld\n",
1125          info->cAltEntry);
1126         LocalFree(buf);
1127     }
1128     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1129      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1130      &bufSize);
1131     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1132     if (buf)
1133     {
1134         info = (CERT_ALT_NAME_INFO *)buf;
1135
1136         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1137          info->cAltEntry);
1138         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1139          "Expected CERT_ALT_NAME_URL, got %ld\n",
1140          info->rgAltEntry[0].dwAltNameChoice);
1141         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1142          "Expected empty URL\n");
1143         LocalFree(buf);
1144     }
1145     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1146      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1147      &bufSize);
1148     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1149     if (buf)
1150     {
1151         info = (CERT_ALT_NAME_INFO *)buf;
1152
1153         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1154          info->cAltEntry);
1155         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1156          "Expected CERT_ALT_NAME_URL, got %ld\n",
1157          info->rgAltEntry[0].dwAltNameChoice);
1158         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1159         LocalFree(buf);
1160     }
1161     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1162      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1163      &bufSize);
1164     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1165     if (buf)
1166     {
1167         info = (CERT_ALT_NAME_INFO *)buf;
1168
1169         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1170          info->cAltEntry);
1171         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1172          "Expected CERT_ALT_NAME_DNS_NAME, got %ld\n",
1173          info->rgAltEntry[0].dwAltNameChoice);
1174         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1175          "Unexpected DNS name\n");
1176         LocalFree(buf);
1177     }
1178     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1179      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1180      &bufSize);
1181     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1182     if (buf)
1183     {
1184         info = (CERT_ALT_NAME_INFO *)buf;
1185
1186         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1187          info->cAltEntry);
1188         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1189          "Expected CERT_ALT_NAME_IP_ADDRESS, got %ld\n",
1190          info->rgAltEntry[0].dwAltNameChoice);
1191         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1192          "Unexpected IP address length %ld\n",
1193           U(info->rgAltEntry[0]).IPAddress.cbData);
1194         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1195          sizeof(localhost)), "Unexpected IP address value\n");
1196         LocalFree(buf);
1197     }
1198 }
1199
1200 struct encodedOctets
1201 {
1202     const BYTE *val;
1203     const BYTE *encoded;
1204 };
1205
1206 static const unsigned char bin46[] = { 'h','i',0 };
1207 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1208 static const unsigned char bin48[] = {
1209      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1210 static const unsigned char bin49[] = {
1211      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1212 static const unsigned char bin50[] = { 0 };
1213 static const unsigned char bin51[] = { 0x04,0x00,0 };
1214
1215 static const struct encodedOctets octets[] = {
1216     { bin46, bin47 },
1217     { bin48, bin49 },
1218     { bin50, bin51 },
1219 };
1220
1221 static void test_encodeOctets(DWORD dwEncoding)
1222 {
1223     CRYPT_DATA_BLOB blob;
1224     DWORD i;
1225
1226     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1227     {
1228         BYTE *buf = NULL;
1229         BOOL ret;
1230         DWORD bufSize = 0;
1231
1232         blob.cbData = strlen((const char*)octets[i].val);
1233         blob.pbData = (BYTE*)octets[i].val;
1234         ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1235          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1236         ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
1237         if (buf)
1238         {
1239             ok(buf[0] == 4,
1240              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1241             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1242              buf[1], octets[i].encoded[1]);
1243             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1244              octets[i].encoded[1] + 1), "Got unexpected value\n");
1245             LocalFree(buf);
1246         }
1247     }
1248 }
1249
1250 static void test_decodeOctets(DWORD dwEncoding)
1251 {
1252     DWORD i;
1253
1254     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1255     {
1256         BYTE *buf = NULL;
1257         BOOL ret;
1258         DWORD bufSize = 0;
1259
1260         ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1261          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1262          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1263         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1264         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1265          "Expected size >= %d, got %ld\n",
1266            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1267         ok(buf != NULL, "Expected allocated buffer\n");
1268         if (buf)
1269         {
1270             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1271
1272             if (blob->cbData)
1273                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1274                  "Unexpected value\n");
1275             LocalFree(buf);
1276         }
1277     }
1278 }
1279
1280 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1281
1282 struct encodedBits
1283 {
1284     DWORD cUnusedBits;
1285     const BYTE *encoded;
1286     DWORD cbDecoded;
1287     const BYTE *decoded;
1288 };
1289
1290 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1291 static const unsigned char bin53[] = { 0xff,0xff };
1292 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1293 static const unsigned char bin55[] = { 0xff,0xfe };
1294 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1295 static const unsigned char bin57[] = { 0xfe };
1296 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1297
1298 static const struct encodedBits bits[] = {
1299     /* normal test cases */
1300     { 0, bin52, 2, bin53 },
1301     { 1, bin54, 2, bin55 },
1302     /* strange test case, showing cUnusedBits >= 8 is allowed */
1303     { 9, bin56, 1, bin57 },
1304     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1305     { 17, bin58, 0, NULL },
1306 };
1307
1308 static void test_encodeBits(DWORD dwEncoding)
1309 {
1310     DWORD i;
1311
1312     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1313     {
1314         CRYPT_BIT_BLOB blob;
1315         BOOL ret;
1316         BYTE *buf = NULL;
1317         DWORD bufSize = 0;
1318
1319         blob.cbData = sizeof(bytesToEncode);
1320         blob.pbData = (BYTE *)bytesToEncode;
1321         blob.cUnusedBits = bits[i].cUnusedBits;
1322         ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1323          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1324         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1325         if (buf)
1326         {
1327             ok(bufSize == bits[i].encoded[1] + 2,
1328              "Got unexpected size %ld, expected %d\n", bufSize,
1329              bits[i].encoded[1] + 2);
1330             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1331              "Unexpected value\n");
1332             LocalFree(buf);
1333         }
1334     }
1335 }
1336
1337 static void test_decodeBits(DWORD dwEncoding)
1338 {
1339     static const BYTE ber[] = "\x03\x02\x01\xff";
1340     static const BYTE berDecoded = 0xfe;
1341     DWORD i;
1342     BOOL ret;
1343     BYTE *buf = NULL;
1344     DWORD bufSize = 0;
1345
1346     /* normal cases */
1347     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1348     {
1349         ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1350          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1351          &bufSize);
1352         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1353         if (buf)
1354         {
1355             CRYPT_BIT_BLOB *blob;
1356
1357             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1358              "Got unexpected size %ld, expected >= %ld\n", bufSize,
1359              sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded);
1360             blob = (CRYPT_BIT_BLOB *)buf;
1361             ok(blob->cbData == bits[i].cbDecoded,
1362              "Got unexpected length %ld, expected %ld\n", blob->cbData,
1363              bits[i].cbDecoded);
1364             if (blob->cbData && bits[i].cbDecoded)
1365                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1366                  "Unexpected value\n");
1367             LocalFree(buf);
1368         }
1369     }
1370     /* special case: check that something that's valid in BER but not in DER
1371      * decodes successfully
1372      */
1373     ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1374      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1375     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1376     if (buf)
1377     {
1378         CRYPT_BIT_BLOB *blob;
1379
1380         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1381            "Got unexpected size %ld\n", bufSize);
1382         blob = (CRYPT_BIT_BLOB *)buf;
1383         ok(blob->cbData == sizeof(berDecoded),
1384            "Got unexpected length %ld\n", blob->cbData);
1385         if (blob->cbData)
1386             ok(*blob->pbData == berDecoded, "Unexpected value\n");
1387         LocalFree(buf);
1388     }
1389 }
1390
1391 struct Constraints2
1392 {
1393     CERT_BASIC_CONSTRAINTS2_INFO info;
1394     const BYTE *encoded;
1395 };
1396
1397 static const unsigned char bin59[] = { 0x30,0x00 };
1398 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1399 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1400 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1401 static const struct Constraints2 constraints2[] = {
1402  /* empty constraints */
1403  { { FALSE, FALSE, 0}, bin59 },
1404  /* can be a CA */
1405  { { TRUE,  FALSE, 0}, bin60 },
1406  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1407   * but that's not the case
1408   */
1409  { { FALSE, TRUE,  0}, bin61 },
1410  /* can be a CA and has path length constraints set */
1411  { { TRUE,  TRUE,  1}, bin62 },
1412 };
1413
1414 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1415 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1416  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1417  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1418  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1419 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1420  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1421  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1422  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1423  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1424
1425 static void test_encodeBasicConstraints(DWORD dwEncoding)
1426 {
1427     DWORD i, bufSize = 0;
1428     CERT_BASIC_CONSTRAINTS_INFO info;
1429     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1430      (LPBYTE)encodedDomainName };
1431     BOOL ret;
1432     BYTE *buf = NULL;
1433
1434     /* First test with the simpler info2 */
1435     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1436     {
1437         ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1438          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1439          &bufSize);
1440         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1441         if (buf)
1442         {
1443             ok(bufSize == constraints2[i].encoded[1] + 2,
1444              "Expected %d bytes, got %ld\n", constraints2[i].encoded[1] + 2,
1445              bufSize);
1446             ok(!memcmp(buf, constraints2[i].encoded,
1447              constraints2[i].encoded[1] + 2), "Unexpected value\n");
1448             LocalFree(buf);
1449         }
1450     }
1451     /* Now test with more complex basic constraints */
1452     info.SubjectType.cbData = 0;
1453     info.fPathLenConstraint = FALSE;
1454     info.cSubtreesConstraint = 0;
1455     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1456      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1457     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1458     if (buf)
1459     {
1460         ok(bufSize == sizeof(emptyConstraint), "Wrong size %ld\n", bufSize);
1461         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1462          "Unexpected value\n");
1463         LocalFree(buf);
1464     }
1465     /* None of the certs I examined had any subtree constraint, but I test one
1466      * anyway just in case.
1467      */
1468     info.cSubtreesConstraint = 1;
1469     info.rgSubtreesConstraint = &nameBlob;
1470     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1471      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1472     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1473     if (buf)
1474     {
1475         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %ld\n", bufSize);
1476         ok(!memcmp(buf, constraintWithDomainName,
1477          sizeof(constraintWithDomainName)), "Unexpected value\n");
1478         LocalFree(buf);
1479     }
1480     /* FIXME: test encoding with subject type. */
1481 }
1482
1483 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1484 static const unsigned char encodedCommonName[] = {
1485     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1486
1487 static void test_decodeBasicConstraints(DWORD dwEncoding)
1488 {
1489     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1490      0xff };
1491     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1492     DWORD i;
1493     BOOL ret;
1494     BYTE *buf = NULL;
1495     DWORD bufSize = 0;
1496
1497     /* First test with simpler info2 */
1498     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1499     {
1500         ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1501          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1502          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1503         ok(ret, "CryptDecodeObjectEx failed for item %ld: %08lx\n", i,
1504          GetLastError());
1505         if (buf)
1506         {
1507             CERT_BASIC_CONSTRAINTS2_INFO *info =
1508              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1509
1510             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1511              "Unexpected value for item %ld\n", i);
1512             LocalFree(buf);
1513         }
1514     }
1515     /* Check with the order of encoded elements inverted */
1516     buf = (PBYTE)1;
1517     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1518      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1519      &bufSize);
1520     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1521      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1522     ok(!buf, "Expected buf to be set to NULL\n");
1523     /* Check with a non-DER bool */
1524     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1525      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1526      (BYTE *)&buf, &bufSize);
1527     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1528     if (buf)
1529     {
1530         CERT_BASIC_CONSTRAINTS2_INFO *info =
1531          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1532
1533         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
1534         LocalFree(buf);
1535     }
1536     /* Check with a non-basic constraints value */
1537     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1538      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
1539      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1540     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1541      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1542     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
1543     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
1544      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
1545      (BYTE *)&buf, &bufSize);
1546     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1547     if (buf)
1548     {
1549         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
1550
1551         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
1552         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
1553         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
1554         LocalFree(buf);
1555     }
1556     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
1557      constraintWithDomainName, sizeof(constraintWithDomainName),
1558      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1559     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1560     if (buf)
1561     {
1562         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
1563
1564         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
1565         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
1566         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
1567         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
1568         {
1569             ok(info->rgSubtreesConstraint[0].cbData ==
1570              sizeof(encodedDomainName), "Wrong size %ld\n",
1571              info->rgSubtreesConstraint[0].cbData);
1572             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
1573              sizeof(encodedDomainName)), "Unexpected value\n");
1574         }
1575         LocalFree(buf);
1576     }
1577 }
1578
1579 /* These are terrible public keys of course, I'm just testing encoding */
1580 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
1581 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
1582 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
1583 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
1584 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
1585 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1586 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
1587 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1588
1589 struct EncodedRSAPubKey
1590 {
1591     const BYTE *modulus;
1592     size_t modulusLen;
1593     const BYTE *encoded;
1594     size_t decodedModulusLen;
1595 };
1596
1597 struct EncodedRSAPubKey rsaPubKeys[] = {
1598     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
1599     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
1600     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
1601     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
1602 };
1603
1604 static void test_encodeRsaPublicKey(DWORD dwEncoding)
1605 {
1606     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
1607     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
1608     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
1609     BOOL ret;
1610     BYTE *buf = NULL;
1611     DWORD bufSize = 0, i;
1612
1613     /* Try with a bogus blob type */
1614     hdr->bType = 2;
1615     hdr->bVersion = CUR_BLOB_VERSION;
1616     hdr->reserved = 0;
1617     hdr->aiKeyAlg = CALG_RSA_KEYX;
1618     rsaPubKey->magic = 0x31415352;
1619     rsaPubKey->bitlen = sizeof(modulus1) * 8;
1620     rsaPubKey->pubexp = 65537;
1621     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
1622      sizeof(modulus1));
1623
1624     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1625      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1626      &bufSize);
1627     ok(!ret && GetLastError() == E_INVALIDARG,
1628      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1629     /* Now with a bogus reserved field */
1630     hdr->bType = PUBLICKEYBLOB;
1631     hdr->reserved = 1;
1632     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1633      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1634      &bufSize);
1635     if (buf)
1636     {
1637         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1638          "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1639         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1640         LocalFree(buf);
1641     }
1642     /* Now with a bogus blob version */
1643     hdr->reserved = 0;
1644     hdr->bVersion = 0;
1645     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1646      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1647      &bufSize);
1648     if (buf)
1649     {
1650         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1651          "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1652         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1653         LocalFree(buf);
1654     }
1655     /* And with a bogus alg ID */
1656     hdr->bVersion = CUR_BLOB_VERSION;
1657     hdr->aiKeyAlg = CALG_DES;
1658     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1659      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1660      &bufSize);
1661     if (buf)
1662     {
1663         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1664          "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1665         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1666         LocalFree(buf);
1667     }
1668     /* Check a couple of RSA-related OIDs */
1669     hdr->aiKeyAlg = CALG_RSA_KEYX;
1670     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
1671      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1672     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1673      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1674     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1675      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1676     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1677      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1678     /* Finally, all valid */
1679     hdr->aiKeyAlg = CALG_RSA_KEYX;
1680     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1681     {
1682         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1683          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
1684         ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1685          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1686         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1687         if (buf)
1688         {
1689             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
1690              "Expected size %d, got %ld\n", rsaPubKeys[i].encoded[1] + 2,
1691              bufSize);
1692             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
1693              "Unexpected value\n");
1694             LocalFree(buf);
1695         }
1696     }
1697 }
1698
1699 static void test_decodeRsaPublicKey(DWORD dwEncoding)
1700 {
1701     DWORD i;
1702     LPBYTE buf = NULL;
1703     DWORD bufSize = 0;
1704     BOOL ret;
1705
1706     /* Try with a bad length */
1707     ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1708      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
1709      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1710     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1711      "Expected CRYPT_E_ASN1_EOD, got %08lx\n", CRYPT_E_ASN1_EOD);
1712     /* Try with a couple of RSA-related OIDs */
1713     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
1714      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
1715      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1716     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1717      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1718     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1719      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
1720      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1721     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1722      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1723     /* Now try success cases */
1724     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1725     {
1726         bufSize = 0;
1727         ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1728          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
1729          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1730         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1731         if (buf)
1732         {
1733             BLOBHEADER *hdr = (BLOBHEADER *)buf;
1734             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
1735
1736             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1737              rsaPubKeys[i].decodedModulusLen,
1738              "Wrong size %ld\n", bufSize);
1739             ok(hdr->bType == PUBLICKEYBLOB,
1740              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
1741              hdr->bType);
1742             ok(hdr->bVersion == CUR_BLOB_VERSION,
1743              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
1744              CUR_BLOB_VERSION, hdr->bVersion);
1745             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
1746              hdr->reserved);
1747             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
1748              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
1749             ok(rsaPubKey->magic == 0x31415352,
1750              "Expected magic RSA1, got %08lx\n", rsaPubKey->magic);
1751             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
1752              "Wrong bit len %ld\n", rsaPubKey->bitlen);
1753             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %ld\n",
1754              rsaPubKey->pubexp);
1755             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1756              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
1757              "Unexpected modulus\n");
1758             LocalFree(buf);
1759         }
1760     }
1761 }
1762
1763 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
1764  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
1765  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1766
1767 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
1768  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
1769  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
1770  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1771
1772 static void test_encodeSequenceOfAny(DWORD dwEncoding)
1773 {
1774     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
1775     CRYPT_SEQUENCE_OF_ANY seq;
1776     DWORD i;
1777     BOOL ret;
1778     BYTE *buf = NULL;
1779     DWORD bufSize = 0;
1780
1781     /* Encode a homogenous sequence */
1782     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
1783     {
1784         blobs[i].cbData = ints[i].encoded[1] + 2;
1785         blobs[i].pbData = (BYTE *)ints[i].encoded;
1786     }
1787     seq.cValue = sizeof(ints) / sizeof(ints[0]);
1788     seq.rgValue = blobs;
1789
1790     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1791      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1792     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1793     if (buf)
1794     {
1795         ok(bufSize == sizeof(intSequence), "Wrong size %ld\n", bufSize);
1796         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
1797         LocalFree(buf);
1798     }
1799     /* Change the type of the first element in the sequence, and give it
1800      * another go
1801      */
1802     blobs[0].cbData = times[0].encodedTime[1] + 2;
1803     blobs[0].pbData = (BYTE *)times[0].encodedTime;
1804     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1805      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1806     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1807     if (buf)
1808     {
1809         ok(bufSize == sizeof(mixedSequence), "Wrong size %ld\n", bufSize);
1810         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
1811          "Unexpected value\n");
1812         LocalFree(buf);
1813     }
1814 }
1815
1816 static void test_decodeSequenceOfAny(DWORD dwEncoding)
1817 {
1818     BOOL ret;
1819     BYTE *buf = NULL;
1820     DWORD bufSize = 0;
1821
1822     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
1823      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1824     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1825     if (buf)
1826     {
1827         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1828         DWORD i;
1829
1830         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1831          "Wrong elements %ld\n", seq->cValue);
1832         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
1833         {
1834             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
1835              "Expected %d bytes, got %ld\n", ints[i].encoded[1] + 2,
1836              seq->rgValue[i].cbData);
1837             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
1838              ints[i].encoded[1] + 2), "Unexpected value\n");
1839         }
1840         LocalFree(buf);
1841     }
1842     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
1843      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1844      &bufSize);
1845     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1846     if (buf)
1847     {
1848         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1849
1850         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1851          "Wrong elements %ld\n", seq->cValue);
1852         /* Just check the first element since it's all that changed */
1853         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
1854          "Expected %d bytes, got %ld\n", times[0].encodedTime[1] + 2,
1855          seq->rgValue[0].cbData);
1856         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
1857          times[0].encodedTime[1] + 2), "Unexpected value\n");
1858         LocalFree(buf);
1859     }
1860 }
1861
1862 struct encodedExtensions
1863 {
1864     CERT_EXTENSIONS exts;
1865     const BYTE *encoded;
1866 };
1867
1868 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1869 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1870
1871 static CERT_EXTENSION criticalExt =
1872  { szOID_BASIC_CONSTRAINTS2, TRUE, { 8, crit_ext_data } };
1873 static CERT_EXTENSION nonCriticalExt =
1874  { szOID_BASIC_CONSTRAINTS2, FALSE, { 8, noncrit_ext_data } };
1875
1876 static const BYTE ext0[] = { 0x30,0x00 };
1877 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
1878                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1879 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
1880                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1881
1882 static const struct encodedExtensions exts[] = {
1883  { { 0, NULL }, ext0 },
1884  { { 1, &criticalExt }, ext1 },
1885  { { 1, &nonCriticalExt }, ext2 },
1886 };
1887
1888 static void test_encodeExtensions(DWORD dwEncoding)
1889 {
1890     DWORD i;
1891
1892     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1893     {
1894         BOOL ret;
1895         BYTE *buf = NULL;
1896         DWORD bufSize = 0;
1897
1898         ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
1899          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1900         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1901         if (buf)
1902         {
1903             ok(bufSize == exts[i].encoded[1] + 2,
1904              "Expected %d bytes, got %ld\n", exts[i].encoded[1] + 2, bufSize);
1905             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
1906              "Unexpected value\n");
1907             LocalFree(buf);
1908         }
1909     }
1910 }
1911
1912 static void test_decodeExtensions(DWORD dwEncoding)
1913 {
1914     DWORD i;
1915
1916     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1917     {
1918         BOOL ret;
1919         BYTE *buf = NULL;
1920         DWORD bufSize = 0;
1921
1922         ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
1923          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1924          NULL, (BYTE *)&buf, &bufSize);
1925         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1926         if (buf)
1927         {
1928             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
1929             DWORD j;
1930
1931             ok(ext->cExtension == exts[i].exts.cExtension,
1932              "Expected %ld extensions, see %ld\n", exts[i].exts.cExtension,
1933              ext->cExtension);
1934             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
1935             {
1936                 ok(!strcmp(ext->rgExtension[j].pszObjId,
1937                  exts[i].exts.rgExtension[j].pszObjId),
1938                  "Expected OID %s, got %s\n",
1939                  exts[i].exts.rgExtension[j].pszObjId,
1940                  ext->rgExtension[j].pszObjId);
1941                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
1942                  exts[i].exts.rgExtension[j].Value.pbData,
1943                  exts[i].exts.rgExtension[j].Value.cbData),
1944                  "Unexpected value\n");
1945             }
1946             LocalFree(buf);
1947         }
1948     }
1949 }
1950
1951 /* MS encodes public key info with a NULL if the algorithm identifier's
1952  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
1953  * it encodes them by omitting the algorithm parameters.  This latter approach
1954  * seems more correct, so accept either form.
1955  */
1956 struct encodedPublicKey
1957 {
1958     CERT_PUBLIC_KEY_INFO info;
1959     const BYTE *encoded;
1960     const BYTE *encodedNoNull;
1961     CERT_PUBLIC_KEY_INFO decoded;
1962 };
1963
1964 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
1965  0xe, 0xf };
1966 static const BYTE params[] = { 0x02, 0x01, 0x01 };
1967
1968 static const unsigned char bin64[] = {
1969     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
1970 static const unsigned char bin65[] = {
1971     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
1972 static const unsigned char bin66[] = {
1973     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
1974 static const unsigned char bin67[] = {
1975     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
1976 static const unsigned char bin68[] = {
1977     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
1978     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
1979 static const unsigned char bin69[] = {
1980     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
1981     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
1982 static const unsigned char bin70[] = {
1983     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
1984     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
1985     0x0f};
1986 static const unsigned char bin71[] = {
1987     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
1988     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
1989     0x0f};
1990 static unsigned char bin72[] = { 0x05,0x00};
1991
1992 static const struct encodedPublicKey pubKeys[] = {
1993  /* with a bogus OID */
1994  { { { "1.2.3", { 0, NULL } }, { 0, NULL, 0 } },
1995   bin64, bin65,
1996   { { "1.2.3", { 2, bin72 } }, { 0, NULL, 0 } } },
1997  /* some normal keys */
1998  { { { szOID_RSA, { 0, NULL } }, { 0, NULL, 0} },
1999   bin66, bin67,
2000   { { szOID_RSA, { 2, bin72 } }, { 0, NULL, 0 } } },
2001  { { { szOID_RSA, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2002   bin68, bin69,
2003   { { szOID_RSA, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2004  /* with add'l parameters--note they must be DER-encoded */
2005  { { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2006   (BYTE *)aKey, 0 } },
2007   bin70, bin71,
2008   { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2009   (BYTE *)aKey, 0 } } },
2010 };
2011
2012 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2013 {
2014     DWORD i;
2015
2016     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2017     {
2018         BOOL ret;
2019         BYTE *buf = NULL;
2020         DWORD bufSize = 0;
2021
2022         ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2023          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2024          &bufSize);
2025         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2026         if (buf)
2027         {
2028             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2029              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2030              "Expected %d or %d bytes, got %ld\n", pubKeys[i].encoded[1] + 2,
2031              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2032             if (bufSize == pubKeys[i].encoded[1] + 2)
2033                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2034                  "Unexpected value\n");
2035             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2036                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2037                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2038             LocalFree(buf);
2039         }
2040     }
2041 }
2042
2043 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2044  const CERT_PUBLIC_KEY_INFO *got)
2045 {
2046     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2047      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2048      got->Algorithm.pszObjId);
2049     ok(expected->Algorithm.Parameters.cbData ==
2050      got->Algorithm.Parameters.cbData,
2051      "Expected parameters of %ld bytes, got %ld\n",
2052      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2053     if (expected->Algorithm.Parameters.cbData)
2054         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2055          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2056          "Unexpected algorithm parameters\n");
2057     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2058      "Expected public key of %ld bytes, got %ld\n",
2059      expected->PublicKey.cbData, got->PublicKey.cbData);
2060     if (expected->PublicKey.cbData)
2061         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2062          got->PublicKey.cbData), "Unexpected public key value\n");
2063 }
2064
2065 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2066 {
2067     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2068      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2069      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2070      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2071     DWORD i;
2072     BOOL ret;
2073     BYTE *buf = NULL;
2074     DWORD bufSize = 0;
2075
2076     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2077     {
2078         /* The NULL form decodes to the decoded member */
2079         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2080          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2081          NULL, (BYTE *)&buf, &bufSize);
2082         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2083         if (buf)
2084         {
2085             comparePublicKeyInfo(&pubKeys[i].decoded,
2086              (CERT_PUBLIC_KEY_INFO *)buf);
2087             LocalFree(buf);
2088         }
2089         /* The non-NULL form decodes to the original */
2090         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2091          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2092          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2093         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2094         if (buf)
2095         {
2096             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2097             LocalFree(buf);
2098         }
2099     }
2100     /* Test with bogus (not valid DER) parameters */
2101     ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2102      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2103      NULL, (BYTE *)&buf, &bufSize);
2104     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2105      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2106 }
2107
2108 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2109  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2110  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2111  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2112  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2113 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2114  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2115  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2116  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2117  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2118 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2119  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2120  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2121  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2122  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2123 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2124  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2125  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2126  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2127  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2128  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2129  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2130 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2131  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2132  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2133  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2134  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2135  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2136  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2137 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2138  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2139  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2140  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2141  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2142  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2143  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2144  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2145  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2146  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2147
2148 static const BYTE serialNum[] = { 0x01 };
2149
2150 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2151 {
2152     BOOL ret;
2153     BYTE *buf = NULL;
2154     DWORD size = 0;
2155     CERT_INFO info = { 0 };
2156
2157     /* Test with NULL pvStructInfo */
2158     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2159      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2160     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2161      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2162     /* Test with a V1 cert */
2163     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2164      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2165     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2166     if (buf)
2167     {
2168         ok(size == v1Cert[1] + 2, "Expected size %d, got %ld\n",
2169          v1Cert[1] + 2, size);
2170         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2171         LocalFree(buf);
2172     }
2173     /* Test v2 cert */
2174     info.dwVersion = CERT_V2;
2175     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2176      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2177     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2178     if (buf)
2179     {
2180         ok(size == sizeof(v2Cert), "Wrong size %ld\n", size);
2181         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2182         LocalFree(buf);
2183     }
2184     /* Test v3 cert */
2185     info.dwVersion = CERT_V3;
2186     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2187      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2188     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2189     if (buf)
2190     {
2191         ok(size == sizeof(v3Cert), "Wrong size %ld\n", size);
2192         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2193         LocalFree(buf);
2194     }
2195     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2196      * API doesn't prevent it)
2197      */
2198     info.dwVersion = CERT_V1;
2199     info.cExtension = 1;
2200     info.rgExtension = &criticalExt;
2201     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2202      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2203     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2204     if (buf)
2205     {
2206         ok(size == sizeof(v1CertWithConstraints), "Wrong size %ld\n", size);
2207         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2208         LocalFree(buf);
2209     }
2210     /* test v1 cert with a serial number */
2211     info.SerialNumber.cbData = sizeof(serialNum);
2212     info.SerialNumber.pbData = (BYTE *)serialNum;
2213     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2214      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2215     if (buf)
2216     {
2217         ok(size == sizeof(v1CertWithSerial), "Wrong size %ld\n", size);
2218         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2219         LocalFree(buf);
2220     }
2221     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2222     info.Issuer.cbData = sizeof(encodedCommonName);
2223     info.Issuer.pbData = (BYTE *)encodedCommonName;
2224     info.Subject.cbData = sizeof(encodedCommonName);
2225     info.Subject.pbData = (BYTE *)encodedCommonName;
2226     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2227      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2228     if (buf)
2229     {
2230         ok(size == sizeof(bigCert), "Wrong size %ld\n", size);
2231         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2232         LocalFree(buf);
2233     }
2234     /* for now, I let more interesting tests be done for each subcomponent,
2235      * rather than retesting them all here.
2236      */
2237 }
2238
2239 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2240 {
2241     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2242      v1CertWithConstraints, v1CertWithSerial };
2243     BOOL ret;
2244     BYTE *buf = NULL;
2245     DWORD size = 0, i;
2246
2247     /* Test with NULL pbEncoded */
2248     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2249      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2250     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2251      "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
2252     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2253      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2254     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2255      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2256     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2257      * minimum a cert must have a non-zero serial number, an issuer, and a
2258      * subject.
2259      */
2260     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2261     {
2262         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2263          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2264          (BYTE *)&buf, &size);
2265         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2266          "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2267     }
2268     /* Now check with serial number, subject and issuer specified */
2269     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2270      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2271     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2272     if (buf)
2273     {
2274         CERT_INFO *info = (CERT_INFO *)buf;
2275
2276         ok(size >= sizeof(CERT_INFO), "Wrong size %ld\n", size);
2277         ok(info->SerialNumber.cbData == 1,
2278          "Expected serial number size 1, got %ld\n", info->SerialNumber.cbData);
2279         ok(*info->SerialNumber.pbData == *serialNum,
2280          "Expected serial number %d, got %d\n", *serialNum,
2281          *info->SerialNumber.pbData);
2282         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2283          "Wrong size %ld\n", info->Issuer.cbData);
2284         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2285          "Unexpected issuer\n");
2286         ok(info->Subject.cbData == sizeof(encodedCommonName),
2287          "Wrong size %ld\n", info->Subject.cbData);
2288         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2289          info->Subject.cbData), "Unexpected subject\n");
2290         LocalFree(buf);
2291     }
2292 }
2293
2294 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2295  0xe, 0xf };
2296
2297 static const BYTE signedBigCert[] = {
2298  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2299  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2300  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2301  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2302  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2303  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2304  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2305  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2306  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2307  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2308  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2309  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2310
2311 static void test_encodeCert(DWORD dwEncoding)
2312 {
2313     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
2314      * also that bigCert is a NULL-terminated string, so don't count its
2315      * last byte (otherwise the signed cert won't decode.)
2316      */
2317     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2318      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2319     BOOL ret;
2320     BYTE *buf = NULL;
2321     DWORD bufSize = 0;
2322
2323     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2324      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2325     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2326     if (buf)
2327     {
2328         ok(bufSize == sizeof(signedBigCert), "Wrong size %ld\n", bufSize);
2329         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2330         LocalFree(buf);
2331     }
2332 }
2333
2334 static void test_decodeCert(DWORD dwEncoding)
2335 {
2336     BOOL ret;
2337     BYTE *buf = NULL;
2338     DWORD size = 0;
2339
2340     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2341      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2342     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2343     if (buf)
2344     {
2345         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2346
2347         ok(info->ToBeSigned.cbData == sizeof(bigCert),
2348          "Wrong cert size %ld\n", info->ToBeSigned.cbData);
2349         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2350          "Unexpected cert\n");
2351         ok(info->Signature.cbData == sizeof(hash),
2352          "Wrong signature size %ld\n", info->Signature.cbData);
2353         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2354          "Unexpected signature\n");
2355         LocalFree(buf);
2356     }
2357     /* A signed cert decodes as a CERT_INFO too */
2358     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
2359      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2360     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2361     if (buf)
2362     {
2363         CERT_INFO *info = (CERT_INFO *)buf;
2364
2365         ok(size >= sizeof(CERT_INFO), "Wrong size %ld\n", size);
2366         ok(info->SerialNumber.cbData == 1,
2367          "Expected serial number size 1, got %ld\n", info->SerialNumber.cbData);
2368         ok(*info->SerialNumber.pbData == *serialNum,
2369          "Expected serial number %d, got %d\n", *serialNum,
2370          *info->SerialNumber.pbData);
2371         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2372          "Wrong size %ld\n", info->Issuer.cbData);
2373         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2374          "Unexpected issuer\n");
2375         ok(info->Subject.cbData == sizeof(encodedCommonName),
2376          "Wrong size %ld\n", info->Subject.cbData);
2377         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2378          info->Subject.cbData), "Unexpected subject\n");
2379         LocalFree(buf);
2380     }
2381 }
2382
2383 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2384 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2385  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2386  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2387 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2388  0x00, 0x03 };
2389 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2390  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2391  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2392 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2393  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2394  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2395  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2396  0x2e, 0x6f, 0x72, 0x67 };
2397 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2398  CRL_REASON_AFFILIATION_CHANGED;
2399
2400 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2401 {
2402     CRL_DIST_POINTS_INFO info = { 0 };
2403     CRL_DIST_POINT point = { { 0 } };
2404     CERT_ALT_NAME_ENTRY entry = { 0 };
2405     BOOL ret;
2406     BYTE *buf = NULL;
2407     DWORD size = 0;
2408
2409     /* Test with an empty info */
2410     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2411      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2412     ok(!ret && GetLastError() == E_INVALIDARG,
2413      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
2414     /* Test with one empty dist point */
2415     info.cDistPoint = 1;
2416     info.rgDistPoint = &point;
2417     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2418      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2419     if (buf)
2420     {
2421         ok(size == sizeof(emptyDistPoint), "Wrong size %ld\n", size);
2422         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2423         LocalFree(buf);
2424     }
2425     /* A dist point with an invalid name */
2426     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2427     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2428     U(entry).pwszURL = (LPWSTR)nihongoURL;
2429     U(point.DistPointName).FullName.cAltEntry = 1;
2430     U(point.DistPointName).FullName.rgAltEntry = &entry;
2431     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2432      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2433     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2434      "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
2435     /* The first invalid character is at index 7 */
2436     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2437      "Expected invalid char at index 7, got %ld\n",
2438      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2439     /* A dist point with (just) a valid name */
2440     U(entry).pwszURL = (LPWSTR)url;
2441     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2442      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2443     if (buf)
2444     {
2445         ok(size == sizeof(distPointWithUrl), "Wrong size %ld\n", size);
2446         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2447         LocalFree(buf);
2448     }
2449     /* A dist point with (just) reason flags */
2450     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2451     point.ReasonFlags.cbData = sizeof(crlReason);
2452     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2453     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2454      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2455     if (buf)
2456     {
2457         ok(size == sizeof(distPointWithReason), "Wrong size %ld\n", size);
2458         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2459         LocalFree(buf);
2460     }
2461     /* A dist point with just an issuer */
2462     point.ReasonFlags.cbData = 0;
2463     point.CRLIssuer.cAltEntry = 1;
2464     point.CRLIssuer.rgAltEntry = &entry;
2465     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2466      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2467     if (buf)
2468     {
2469         ok(size == sizeof(distPointWithIssuer), "Wrong size %ld\n", size);
2470         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2471         LocalFree(buf);
2472     }
2473     /* A dist point with both a name and an issuer */
2474     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2475     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2476      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2477     if (buf)
2478     {
2479         ok(size == sizeof(distPointWithUrlAndIssuer),
2480          "Wrong size %ld\n", size);
2481         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2482         LocalFree(buf);
2483     }
2484 }
2485
2486 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2487 {
2488     BOOL ret;
2489     BYTE *buf = NULL;
2490     DWORD size = 0;
2491     PCRL_DIST_POINTS_INFO info;
2492     PCRL_DIST_POINT point;
2493     PCERT_ALT_NAME_ENTRY entry;
2494
2495     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2496      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2497      (BYTE *)&buf, &size);
2498     if (ret)
2499     {
2500         info = (PCRL_DIST_POINTS_INFO)buf;
2501         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2502          "Wrong size %ld\n", size);
2503         ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2504          info->cDistPoint);
2505         point = info->rgDistPoint;
2506         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
2507          "Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
2508          point->DistPointName.dwDistPointNameChoice);
2509         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2510         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2511         LocalFree(buf);
2512     }
2513     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2514      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2515      (BYTE *)&buf, &size);
2516     if (ret)
2517     {
2518         info = (PCRL_DIST_POINTS_INFO)buf;
2519         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2520          "Wrong size %ld\n", size);
2521         ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2522          info->cDistPoint);
2523         point = info->rgDistPoint;
2524         ok(point->DistPointName.dwDistPointNameChoice ==
2525          CRL_DIST_POINT_FULL_NAME,
2526          "Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
2527          point->DistPointName.dwDistPointNameChoice);
2528         ok(U(point->DistPointName).FullName.cAltEntry == 1,
2529          "Expected 1 name entry, got %ld\n",
2530          U(point->DistPointName).FullName.cAltEntry);
2531         entry = U(point->DistPointName).FullName.rgAltEntry;
2532         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2533          "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2534         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2535         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2536         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2537         LocalFree(buf);
2538     }
2539     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2540      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2541      NULL, (BYTE *)&buf, &size);
2542     if (ret)
2543     {
2544         info = (PCRL_DIST_POINTS_INFO)buf;
2545         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2546          "Wrong size %ld\n", size);
2547         ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2548          info->cDistPoint);
2549         point = info->rgDistPoint;
2550         ok(point->DistPointName.dwDistPointNameChoice ==
2551          CRL_DIST_POINT_NO_NAME,
2552          "Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
2553          point->DistPointName.dwDistPointNameChoice);
2554         ok(point->ReasonFlags.cbData == sizeof(crlReason),
2555          "Expected reason length\n");
2556         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
2557          "Unexpected reason\n");
2558         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2559         LocalFree(buf);
2560     }
2561     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2562      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
2563      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2564     if (ret)
2565     {
2566         info = (PCRL_DIST_POINTS_INFO)buf;
2567         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2568          "Wrong size %ld\n", size);
2569         ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2570          info->cDistPoint);
2571         point = info->rgDistPoint;
2572         ok(point->DistPointName.dwDistPointNameChoice ==
2573          CRL_DIST_POINT_FULL_NAME,
2574          "Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
2575          point->DistPointName.dwDistPointNameChoice);
2576         ok(U(point->DistPointName).FullName.cAltEntry == 1,
2577          "Expected 1 name entry, got %ld\n",
2578          U(point->DistPointName).FullName.cAltEntry);
2579         entry = U(point->DistPointName).FullName.rgAltEntry;
2580         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2581          "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2582         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2583         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2584         ok(point->CRLIssuer.cAltEntry == 1,
2585          "Expected 1 issuer entry, got %ld\n", point->CRLIssuer.cAltEntry);
2586         entry = point->CRLIssuer.rgAltEntry;
2587         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2588          "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2589         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2590         LocalFree(buf);
2591     }
2592 }
2593
2594 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
2595 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
2596 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
2597  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
2598  0x67 };
2599
2600 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
2601 {
2602     BOOL ret;
2603     BYTE *buf = NULL;
2604     DWORD size = 0;
2605     CRL_ISSUING_DIST_POINT point = { { 0 } };
2606     CERT_ALT_NAME_ENTRY entry;
2607
2608     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
2609      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2610     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2611      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2612     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
2613      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2614     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2615     if (buf)
2616     {
2617         ok(size == sizeof(emptySequence), "Unexpected size %ld\n", size);
2618         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
2619         LocalFree(buf);
2620     }
2621     /* nonsensical flags */
2622     point.fOnlyContainsUserCerts = TRUE;
2623     point.fOnlyContainsCACerts = TRUE;
2624     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
2625      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2626     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2627     if (buf)
2628     {
2629         ok(size == sizeof(badFlagsIDP), "Unexpected size %ld\n", size);
2630         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
2631         LocalFree(buf);
2632     }
2633     /* unimplemented name type */
2634     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
2635     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
2636     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
2637      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2638     ok(!ret && GetLastError() == E_INVALIDARG,
2639      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
2640     /* empty name */
2641     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2642     U(point.DistPointName).FullName.cAltEntry = 0;
2643     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
2644      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2645     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2646     if (buf)
2647     {
2648         ok(size == sizeof(emptyNameIDP), "Unexpected size %ld\n", size);
2649         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
2650         LocalFree(buf);
2651     }
2652     /* name with URL entry */
2653     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2654     U(entry).pwszURL = (LPWSTR)url;
2655     U(point.DistPointName).FullName.cAltEntry = 1;
2656     U(point.DistPointName).FullName.rgAltEntry = &entry;
2657     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
2658      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2659     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2660     if (buf)
2661     {
2662         ok(size == sizeof(urlIDP), "Unexpected size %ld\n", size);
2663         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
2664         LocalFree(buf);
2665     }
2666 }
2667
2668 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
2669  const CERT_ALT_NAME_ENTRY *got)
2670 {
2671     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
2672      "Expected name choice %ld, got %ld\n", expected->dwAltNameChoice,
2673      got->dwAltNameChoice);
2674     if (expected->dwAltNameChoice == got->dwAltNameChoice)
2675     {
2676         switch (got->dwAltNameChoice)
2677         {
2678         case CERT_ALT_NAME_RFC822_NAME:
2679         case CERT_ALT_NAME_DNS_NAME:
2680         case CERT_ALT_NAME_EDI_PARTY_NAME:
2681         case CERT_ALT_NAME_URL:
2682         case CERT_ALT_NAME_REGISTERED_ID:
2683             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
2684                !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), "Unexpected name\n");
2685             break;
2686         case CERT_ALT_NAME_X400_ADDRESS:
2687         case CERT_ALT_NAME_DIRECTORY_NAME:
2688         case CERT_ALT_NAME_IP_ADDRESS:
2689             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
2690                "Unexpected IP address length %ld\n", U(*got).IPAddress.cbData);
2691             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
2692                        U(*got).IPAddress.cbData), "Unexpected value\n");
2693             break;
2694         }
2695     }
2696 }
2697
2698 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
2699  const CERT_ALT_NAME_INFO *got)
2700 {
2701     DWORD i;
2702
2703     ok(expected->cAltEntry == got->cAltEntry, "Expected %ld entries, got %ld\n",
2704      expected->cAltEntry, got->cAltEntry);
2705     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
2706         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
2707 }
2708
2709 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
2710  const CRL_DIST_POINT_NAME *got)
2711 {
2712     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
2713      "Unexpected name choice %ld\n", got->dwDistPointNameChoice);
2714     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
2715         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
2716 }
2717
2718 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
2719  const CRL_ISSUING_DIST_POINT *got)
2720 {
2721     compareDistPointName(&expected->DistPointName, &got->DistPointName);
2722     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
2723      "Unexpected fOnlyContainsUserCerts\n");
2724     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
2725      "Unexpected fOnlyContainsCACerts\n");
2726     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
2727      "Unexpected reason flags\n");
2728     ok(got->fIndirectCRL == expected->fIndirectCRL,
2729      "Unexpected fIndirectCRL\n");
2730 }
2731
2732 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
2733 {
2734     BOOL ret;
2735     BYTE *buf = NULL;
2736     DWORD size = 0;
2737     CRL_ISSUING_DIST_POINT point = { { 0 } };
2738
2739     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
2740      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2741      (BYTE *)&buf, &size);
2742     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2743     if (ret)
2744     {
2745         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
2746         LocalFree(buf);
2747     }
2748     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
2749      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2750      (BYTE *)&buf, &size);
2751     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2752     if (ret)
2753     {
2754         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
2755         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
2756         LocalFree(buf);
2757     }
2758     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
2759      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2760      (BYTE *)&buf, &size);
2761     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2762     if (ret)
2763     {
2764         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
2765         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2766         U(point.DistPointName).FullName.cAltEntry = 0;
2767         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
2768         LocalFree(buf);
2769     }
2770     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
2771      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2772     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2773     if (ret)
2774     {
2775         CERT_ALT_NAME_ENTRY entry;
2776
2777         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2778         U(entry).pwszURL = (LPWSTR)url;
2779         U(point.DistPointName).FullName.cAltEntry = 1;
2780         U(point.DistPointName).FullName.rgAltEntry = &entry;
2781         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
2782         LocalFree(buf);
2783     }
2784 }
2785
2786 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
2787  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2788  0x30, 0x5a };
2789 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2790  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
2791  0x30, 0x30, 0x30, 0x30, 0x5a };
2792 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
2793  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
2794  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
2795  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
2796  0x5a };
2797 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
2798  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2799  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
2800  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
2801  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
2802  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2803 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
2804  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2805  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
2806  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2807  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
2808  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2809 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
2810  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
2811  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2812  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
2813  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
2814  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
2815  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2816 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
2817  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
2818  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2819  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
2820  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2821  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2822  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2823 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
2824  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
2825  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
2826  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
2827  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
2828  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
2829  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2830 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
2831  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
2832  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
2833  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
2834  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2835  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
2836  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2837
2838 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
2839 {
2840     BOOL ret;
2841     BYTE *buf = NULL;
2842     DWORD size = 0;
2843     CRL_INFO info = { 0 };
2844     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
2845     CERT_EXTENSION ext;
2846
2847     /* Test with a V1 CRL */
2848     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2849      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2850     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2851     if (buf)
2852     {
2853         ok(size == sizeof(v1CRL), "Wrong size %ld\n", size);
2854         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
2855         LocalFree(buf);
2856     }
2857     /* Test v2 CRL */
2858     info.dwVersion = CRL_V2;
2859     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2860      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2861     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2862     if (buf)
2863     {
2864         ok(size == v2CRL[1] + 2, "Expected size %d, got %ld\n",
2865          v2CRL[1] + 2, size);
2866         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
2867         LocalFree(buf);
2868     }
2869     /* v1 CRL with a name */
2870     info.dwVersion = CRL_V1;
2871     info.Issuer.cbData = sizeof(encodedCommonName);
2872     info.Issuer.pbData = (BYTE *)encodedCommonName;
2873     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2874      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2875     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2876     if (buf)
2877     {
2878         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %ld\n", size);
2879         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
2880         LocalFree(buf);
2881     }
2882     /* v1 CRL with a name and a NULL entry pointer */
2883     info.cCRLEntry = 1;
2884     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2885      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2886     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2887      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2888     /* now set an empty entry */
2889     info.rgCRLEntry = &entry;
2890     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2891      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2892     if (buf)
2893     {
2894         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
2895          "Wrong size %ld\n", size);
2896         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
2897          "Got unexpected value\n");
2898         LocalFree(buf);
2899     }
2900     /* an entry with a serial number */
2901     entry.SerialNumber.cbData = sizeof(serialNum);
2902     entry.SerialNumber.pbData = (BYTE *)serialNum;
2903     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2904      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2905     if (buf)
2906     {
2907         ok(size == sizeof(v1CRLWithIssuerAndEntry),
2908          "Wrong size %ld\n", size);
2909         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
2910          "Got unexpected value\n");
2911         LocalFree(buf);
2912     }
2913     /* an entry with an extension */
2914     entry.cExtension = 1;
2915     entry.rgExtension = &criticalExt;
2916     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2917      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2918     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2919     if (buf)
2920     {
2921         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %ld\n", size);
2922         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
2923         LocalFree(buf);
2924     }
2925     /* a CRL with an extension */
2926     entry.cExtension = 0;
2927     info.cExtension = 1;
2928     info.rgExtension = &criticalExt;
2929     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2930      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2931     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2932     if (buf)
2933     {
2934         ok(size == sizeof(v1CRLWithExt), "Wrong size %ld\n", size);
2935         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
2936         LocalFree(buf);
2937     }
2938     /* a v2 CRL with an extension, this time non-critical */
2939     info.dwVersion = CRL_V2;
2940     info.rgExtension = &nonCriticalExt;
2941     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2942      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2943     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2944     if (buf)
2945     {
2946         ok(size == sizeof(v2CRLWithExt), "Wrong size %ld\n", size);
2947         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
2948         LocalFree(buf);
2949     }
2950     /* a v2 CRL with an issuing dist point extension */
2951     ext.pszObjId = szOID_ISSUING_DIST_POINT;
2952     ext.fCritical = TRUE;
2953     ext.Value.cbData = sizeof(urlIDP);
2954     ext.Value.pbData = (LPBYTE)urlIDP;
2955     entry.rgExtension = &ext;
2956     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2957      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2958     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2959     if (buf)
2960     {
2961         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %ld\n", size);
2962         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
2963         LocalFree(buf);
2964     }
2965 }
2966
2967 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
2968  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
2969  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
2970  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
2971  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
2972  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
2973  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
2974  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
2975  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
2976  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
2977  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
2978  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
2979  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
2980  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
2981  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
2982  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
2983  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
2984  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
2985  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
2986  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
2987  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
2988  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
2989  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
2990  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
2991  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
2992  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
2993  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
2994  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
2995  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
2996  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
2997  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
2998  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
2999  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3000  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3001  0xcd };
3002
3003 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
3004 {
3005     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
3006     BOOL ret;
3007     BYTE *buf = NULL;
3008     DWORD size = 0, i;
3009
3010     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
3011     {
3012         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3013          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3014          (BYTE *)&buf, &size);
3015         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
3016          "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
3017     }
3018     /* at a minimum, a CRL must contain an issuer: */
3019     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3020      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3021      (BYTE *)&buf, &size);
3022     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3023     if (buf)
3024     {
3025         CRL_INFO *info = (CRL_INFO *)buf;
3026
3027         ok(size >= sizeof(CRL_INFO), "Wrong size %ld\n", size);
3028         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %ld\n",
3029          info->cCRLEntry);
3030         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3031          "Wrong issuer size %ld\n", info->Issuer.cbData);
3032         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3033          "Unexpected issuer\n");
3034         LocalFree(buf);
3035     }
3036     /* check decoding with an empty CRL entry */
3037     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3038      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
3039      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3040     todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
3041      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
3042     /* with a real CRL entry */
3043     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3044      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
3045      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3046     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3047     if (buf)
3048     {
3049         CRL_INFO *info = (CRL_INFO *)buf;
3050         CRL_ENTRY *entry;
3051
3052         ok(size >= sizeof(CRL_INFO), "Wrong size %ld\n", size);
3053         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
3054          info->cCRLEntry);
3055         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
3056         entry = info->rgCRLEntry;
3057         ok(entry->SerialNumber.cbData == 1,
3058          "Expected serial number size 1, got %ld\n",
3059          entry->SerialNumber.cbData);
3060         ok(*entry->SerialNumber.pbData == *serialNum,
3061          "Expected serial number %d, got %d\n", *serialNum,
3062          *entry->SerialNumber.pbData);
3063         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3064          "Wrong issuer size %ld\n", info->Issuer.cbData);
3065         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3066          "Unexpected issuer\n");
3067     }
3068     /* a real CRL from verisign that has extensions */
3069     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3070      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
3071      NULL, (BYTE *)&buf, &size);
3072     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3073     if (buf)
3074     {
3075         CRL_INFO *info = (CRL_INFO *)buf;
3076         CRL_ENTRY *entry;
3077
3078         ok(size >= sizeof(CRL_INFO), "Wrong size %ld\n", size);
3079         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %ld\n",
3080          info->cCRLEntry);
3081         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
3082         entry = info->rgCRLEntry;
3083         ok(info->cExtension == 2, "Expected 2 extensions, got %ld\n",
3084          info->cExtension);
3085     }
3086     /* and finally, with an extension */
3087     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3088      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
3089      NULL, (BYTE *)&buf, &size);
3090     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3091     if (buf)
3092     {
3093         CRL_INFO *info = (CRL_INFO *)buf;
3094         CRL_ENTRY *entry;
3095
3096         ok(size >= sizeof(CRL_INFO), "Wrong size %ld\n", size);
3097         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
3098          info->cCRLEntry);
3099         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
3100         entry = info->rgCRLEntry;
3101         ok(entry->SerialNumber.cbData == 1,
3102          "Expected serial number size 1, got %ld\n",
3103          entry->SerialNumber.cbData);
3104         ok(*entry->SerialNumber.pbData == *serialNum,
3105          "Expected serial number %d, got %d\n", *serialNum,
3106          *entry->SerialNumber.pbData);
3107         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3108          "Wrong issuer size %ld\n", info->Issuer.cbData);
3109         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3110          "Unexpected issuer\n");
3111         ok(info->cExtension == 1, "Expected 1 extensions, got %ld\n",
3112          info->cExtension);
3113     }
3114     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3115      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
3116      NULL, (BYTE *)&buf, &size);
3117     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3118     if (buf)
3119     {
3120         CRL_INFO *info = (CRL_INFO *)buf;
3121
3122         ok(info->cExtension == 1, "Expected 1 extensions, got %ld\n",
3123          info->cExtension);
3124         LocalFree(buf);
3125     }
3126     /* And again, with an issuing dist point */
3127     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3128      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
3129      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3130     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3131     if (buf)
3132     {
3133         CRL_INFO *info = (CRL_INFO *)buf;
3134
3135         ok(info->cExtension == 1, "Expected 1 extensions, got %ld\n",
3136          info->cExtension);
3137         LocalFree(buf);
3138     }
3139 }
3140
3141 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
3142  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
3143 static const BYTE encodedUsage[] = {
3144  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
3145  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
3146  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
3147
3148 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
3149 {
3150     BOOL ret;
3151     BYTE *buf = NULL;
3152     DWORD size = 0;
3153     CERT_ENHKEY_USAGE usage;
3154
3155     /* Test with empty usage */
3156     usage.cUsageIdentifier = 0;
3157     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
3158      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3159     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
3160     if (buf)
3161     {
3162         ok(size == sizeof(emptySequence), "Wrong size %ld\n", size);
3163         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
3164         LocalFree(buf);
3165     }
3166     /* Test with a few usages */
3167     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
3168     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
3169     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
3170      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3171     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
3172     if (buf)
3173     {
3174         ok(size == sizeof(encodedUsage), "Wrong size %ld\n", size);
3175         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
3176         LocalFree(buf);
3177     }
3178 }
3179
3180 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
3181 {
3182     BOOL ret;
3183     LPBYTE buf = NULL;
3184     DWORD size = 0;
3185
3186     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
3187      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
3188      (BYTE *)&buf, &size);
3189     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3190     if (buf)
3191     {
3192         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
3193
3194         ok(size >= sizeof(CERT_ENHKEY_USAGE),
3195          "Wrong size %ld\n", size);
3196         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %ld\n",
3197          usage->cUsageIdentifier);
3198         LocalFree(buf);
3199     }
3200     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
3201      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
3202      (BYTE *)&buf, &size);
3203     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3204     if (buf)
3205     {
3206         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
3207         DWORD i;
3208
3209         ok(size >= sizeof(CERT_ENHKEY_USAGE),
3210          "Wrong size %ld\n", size);
3211         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
3212          "Wrong CRL entries count %ld\n", usage->cUsageIdentifier);
3213         for (i = 0; i < usage->cUsageIdentifier; i++)
3214             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
3215              "Expected OID %s, got %s\n", keyUsages[i],
3216              usage->rgpszUsageIdentifier[i]);
3217         LocalFree(buf);
3218     }
3219 }
3220
3221 /* Free *pInfo with HeapFree */
3222 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
3223 {
3224     BOOL ret;
3225     DWORD size = 0;
3226     HCRYPTKEY key;
3227
3228     /* This crashes
3229     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
3230      */
3231     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
3232     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3233      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3234     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
3235      &size);
3236     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3237      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3238     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
3239      NULL, &size);
3240     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3241      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3242     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
3243      0, NULL, NULL, &size);
3244     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3245      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3246     /* Test with no key */
3247     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
3248      0, NULL, NULL, &size);
3249     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08lx\n",
3250      GetLastError());
3251     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
3252     ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
3253     if (ret)
3254     {
3255         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
3256          NULL, 0, NULL, NULL, &size);
3257         ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n", GetLastError());
3258         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
3259         if (*pInfo)
3260         {
3261             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
3262              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
3263             ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n",
3264              GetLastError());
3265             if (ret)
3266             {
3267                 /* By default (we passed NULL as the OID) the OID is
3268                  * szOID_RSA_RSA.
3269                  */
3270                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
3271                  "Expected %s, got %s\n", szOID_RSA_RSA,
3272                  (*pInfo)->Algorithm.pszObjId);
3273             }
3274         }
3275     }
3276 }
3277
3278 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
3279  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
3280  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
3281  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
3282  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
3283  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
3284  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
3285  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
3286  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
3287  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
3288  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
3289  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3290  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
3291  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
3292  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
3293  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
3294  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
3295  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
3296  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
3297  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
3298  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
3299  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
3300  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
3301  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
3302  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
3303
3304 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
3305 {
3306     BOOL ret;
3307     HCRYPTKEY key;
3308     PCCERT_CONTEXT context;
3309
3310     /* These crash
3311     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
3312     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
3313     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
3314     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
3315      NULL);
3316      */
3317     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
3318     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3319      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
3320     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
3321     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3322      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
3323     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
3324      &key);
3325     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3326      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3327     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
3328      &key);
3329     ok(ret, "CryptImportPublicKeyInfoEx failed: %08lx\n", GetLastError());
3330     CryptDestroyKey(key);
3331
3332     /* Test importing a public key from a certificate context */
3333     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
3334      sizeof(expiredCert));
3335     ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
3336      GetLastError());
3337     if (context)
3338     {
3339         ok(!strcmp(szOID_RSA_RSA,
3340          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
3341          "Expected %s, got %s\n", szOID_RSA_RSA,
3342          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
3343         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
3344          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
3345         ok(ret, "CryptImportPublicKeyInfoEx failed: %08lx\n", GetLastError());
3346         CryptDestroyKey(key);
3347         CertFreeCertificateContext(context);
3348     }
3349 }
3350
3351 static const char cspName[] = "WineCryptTemp";
3352
3353 static void testPortPublicKeyInfo(void)
3354 {
3355     HCRYPTPROV csp;
3356     BOOL ret;
3357     PCERT_PUBLIC_KEY_INFO info = NULL;
3358
3359     /* Just in case a previous run failed, delete this thing */
3360     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3361      CRYPT_DELETEKEYSET);
3362     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3363      CRYPT_NEWKEYSET);
3364
3365     testExportPublicKey(csp, &info);
3366     testImportPublicKey(csp, info);
3367
3368     HeapFree(GetProcessHeap(), 0, info);
3369     CryptReleaseContext(csp, 0);
3370     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3371      CRYPT_DELETEKEYSET);
3372 }
3373
3374 START_TEST(encode)
3375 {
3376     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
3377      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
3378     DWORD i;
3379
3380     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
3381     {
3382         test_encodeInt(encodings[i]);
3383         test_decodeInt(encodings[i]);
3384         test_encodeEnumerated(encodings[i]);
3385         test_decodeEnumerated(encodings[i]);
3386         test_encodeFiletime(encodings[i]);
3387         test_decodeFiletime(encodings[i]);
3388         test_encodeName(encodings[i]);
3389         test_decodeName(encodings[i]);
3390         test_encodeNameValue(encodings[i]);
3391         test_decodeNameValue(encodings[i]);
3392         test_encodeAltName(encodings[i]);
3393         test_decodeAltName(encodings[i]);
3394         test_encodeOctets(encodings[i]);
3395         test_decodeOctets(encodings[i]);
3396         test_encodeBits(encodings[i]);
3397         test_decodeBits(encodings[i]);
3398         test_encodeBasicConstraints(encodings[i]);
3399         test_decodeBasicConstraints(encodings[i]);
3400         test_encodeRsaPublicKey(encodings[i]);
3401         test_decodeRsaPublicKey(encodings[i]);
3402         test_encodeSequenceOfAny(encodings[i]);
3403         test_decodeSequenceOfAny(encodings[i]);
3404         test_encodeExtensions(encodings[i]);
3405         test_decodeExtensions(encodings[i]);
3406         test_encodePublicKeyInfo(encodings[i]);
3407         test_decodePublicKeyInfo(encodings[i]);
3408         test_encodeCertToBeSigned(encodings[i]);
3409         test_decodeCertToBeSigned(encodings[i]);
3410         test_encodeCert(encodings[i]);
3411         test_decodeCert(encodings[i]);
3412         test_encodeCRLDistPoints(encodings[i]);
3413         test_decodeCRLDistPoints(encodings[i]);
3414         test_encodeCRLIssuingDistPoint(encodings[i]);
3415         test_decodeCRLIssuingDistPoint(encodings[i]);
3416         test_encodeCRLToBeSigned(encodings[i]);
3417         test_decodeCRLToBeSigned(encodings[i]);
3418         test_encodeEnhancedKeyUsage(encodings[i]);
3419         test_decodeEnhancedKeyUsage(encodings[i]);
3420     }
3421     testPortPublicKeyInfo();
3422 }