query: Add a stub implementation for LocateCatalogs.
[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 static const BYTE encodedTwoRDNs[] = {
609 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
610 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
611 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
612 0x6e,0x67,0x00,
613 };
614
615 static const BYTE us[] = { 0x55, 0x53 };
616 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
617  0x74, 0x61 };
618 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
619  0x6f, 0x6c, 0x69, 0x73 };
620 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
621  0x76, 0x65, 0x72, 0x73 };
622 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
623  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
624 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
625  0x73, 0x74 };
626 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
627  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
628
629 #define _blob_of(arr) { sizeof(arr), (LPBYTE)arr }
630 const CERT_RDN_ATTR rdnAttrs[] = {
631  { "2.5.4.6", CERT_RDN_PRINTABLE_STRING,        _blob_of(us) },
632  { "2.5.4.8", CERT_RDN_PRINTABLE_STRING,        _blob_of(minnesota) },
633  { "2.5.4.7", CERT_RDN_PRINTABLE_STRING,        _blob_of(minneapolis) },
634  { "2.5.4.10", CERT_RDN_PRINTABLE_STRING,       _blob_of(codeweavers) },
635  { "2.5.4.11", CERT_RDN_PRINTABLE_STRING,       _blob_of(wine) },
636  { "2.5.4.3", CERT_RDN_PRINTABLE_STRING,        _blob_of(localhostAttr) },
637  { "1.2.840.113549.1.9.1", CERT_RDN_IA5_STRING, _blob_of(aric) },
638 };
639 const CERT_RDN_ATTR decodedRdnAttrs[] = {
640  { "2.5.4.6", CERT_RDN_PRINTABLE_STRING,        _blob_of(us) },
641  { "2.5.4.3", CERT_RDN_PRINTABLE_STRING,        _blob_of(localhostAttr) },
642  { "2.5.4.8", CERT_RDN_PRINTABLE_STRING,        _blob_of(minnesota) },
643  { "2.5.4.7", CERT_RDN_PRINTABLE_STRING,        _blob_of(minneapolis) },
644  { "2.5.4.10", CERT_RDN_PRINTABLE_STRING,       _blob_of(codeweavers) },
645  { "2.5.4.11", CERT_RDN_PRINTABLE_STRING,       _blob_of(wine) },
646  { "1.2.840.113549.1.9.1", CERT_RDN_IA5_STRING, _blob_of(aric) },
647 };
648 #undef _blob_of
649
650 static const BYTE encodedRDNAttrs[] = {
651 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
652 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
653 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
654 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
655 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
656 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
657 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
658 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
659 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
660 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
661 };
662
663 static void test_encodeName(DWORD dwEncoding)
664 {
665     CERT_RDN_ATTR attrs[2];
666     CERT_RDN rdn;
667     CERT_NAME_INFO info;
668     static CHAR oid_common_name[] = szOID_COMMON_NAME,
669                 oid_sur_name[]    = szOID_SUR_NAME;
670     BYTE *buf = NULL;
671     DWORD size = 0;
672     BOOL ret;
673
674     /* Test with NULL pvStructInfo */
675     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
676      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
677     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
678      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
679     /* Test with empty CERT_NAME_INFO */
680     info.cRDN = 0;
681     info.rgRDN = NULL;
682     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
683      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
684     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
685     if (buf)
686     {
687         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
688          "Got unexpected encoding for empty name\n");
689         LocalFree(buf);
690     }
691     /* Test with bogus CERT_RDN */
692     info.cRDN = 1;
693     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
694      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
695     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
696      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
697     /* Test with empty CERT_RDN */
698     rdn.cRDNAttr = 0;
699     rdn.rgRDNAttr = NULL;
700     info.cRDN = 1;
701     info.rgRDN = &rdn;
702     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
703      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
704     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
705     if (buf)
706     {
707         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
708          "Got unexpected encoding for empty RDN array\n");
709         LocalFree(buf);
710     }
711     /* Test with bogus attr array */
712     rdn.cRDNAttr = 1;
713     rdn.rgRDNAttr = NULL;
714     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
715      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
716     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
717      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
718     /* oddly, a bogus OID is accepted by Windows XP; not testing.
719     attrs[0].pszObjId = "bogus";
720     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
721     attrs[0].Value.cbData = sizeof(commonName);
722     attrs[0].Value.pbData = (BYTE *)commonName;
723     rdn.cRDNAttr = 1;
724     rdn.rgRDNAttr = attrs;
725     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
726      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
727     ok(!ret, "Expected failure, got success\n");
728      */
729     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
730      * the encoded attributes to be swapped.
731      */
732     attrs[0].pszObjId = oid_common_name;
733     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
734     attrs[0].Value.cbData = sizeof(commonName);
735     attrs[0].Value.pbData = (BYTE *)commonName;
736     attrs[1].pszObjId = oid_sur_name;
737     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
738     attrs[1].Value.cbData = sizeof(surName);
739     attrs[1].Value.pbData = (BYTE *)surName;
740     rdn.cRDNAttr = 2;
741     rdn.rgRDNAttr = attrs;
742     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
743      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
744     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
745     if (buf)
746     {
747         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
748          "Got unexpected encoding for two RDN array\n");
749         LocalFree(buf);
750     }
751     /* A name can be "encoded" with previously encoded RDN attrs. */
752     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
753     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
754     attrs[0].Value.cbData = sizeof(twoRDNs);
755     rdn.cRDNAttr = 1;
756     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
757      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
758     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
759     if (buf)
760     {
761         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %ld\n", size);
762         ok(!memcmp(buf, encodedTwoRDNs, size),
763          "Unexpected value for re-endoded two RDN array\n");
764         LocalFree(buf);
765     }
766     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
767     rdn.cRDNAttr = 1;
768     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
769     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
770      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
771     ok(!ret && GetLastError() == E_INVALIDARG,
772      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
773     /* Test a more complex name */
774     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
775     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
776     info.cRDN = 1;
777     info.rgRDN = &rdn;
778     buf = NULL;
779     size = 0;
780     ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
781      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
782     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
783     if (ret)
784     {
785         ok(size == sizeof(encodedRDNAttrs), "Wrong size %ld\n", size);
786         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
787         LocalFree(buf);
788     }
789 }
790
791 static void compareNameValues(const CERT_NAME_VALUE *expected,
792  const CERT_NAME_VALUE *got)
793 {
794     ok(got->dwValueType == expected->dwValueType,
795      "Expected string type %ld, got %ld\n", expected->dwValueType,
796      got->dwValueType);
797     ok(got->Value.cbData == expected->Value.cbData,
798      "String type %ld: unexpected data size, got %ld, expected %ld\n",
799      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
800     if (got->Value.cbData && got->Value.pbData)
801         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
802          min(got->Value.cbData, expected->Value.cbData)),
803          "String type %ld: unexpected value\n", expected->dwValueType);
804 }
805
806 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
807  const CERT_RDN_ATTR *got)
808 {
809     if (expected->pszObjId && strlen(expected->pszObjId))
810     {
811         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
812          expected->pszObjId);
813         if (got->pszObjId)
814         {
815             ok(!strcmp(got->pszObjId, expected->pszObjId),
816              "Got unexpected OID %s, expected %s\n", got->pszObjId,
817              expected->pszObjId);
818         }
819     }
820     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
821      (const CERT_NAME_VALUE *)&got->dwValueType);
822 }
823
824 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
825 {
826     ok(got->cRDNAttr == expected->cRDNAttr,
827      "Expected %ld RDN attrs, got %ld\n", expected->cRDNAttr, got->cRDNAttr);
828     if (got->cRDNAttr)
829     {
830         DWORD i;
831
832         for (i = 0; i < got->cRDNAttr; i++)
833             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
834     }
835 }
836
837 static void compareNames(const CERT_NAME_INFO *expected,
838  const CERT_NAME_INFO *got)
839 {
840     ok(got->cRDN == expected->cRDN, "Expected %ld RDNs, got %ld\n",
841      expected->cRDN, got->cRDN);
842     if (got->cRDN)
843     {
844         DWORD i;
845
846         for (i = 0; i < got->cRDN; i++)
847             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
848     }
849 }
850
851 static void test_decodeName(DWORD dwEncoding)
852 {
853     BYTE *buf = NULL;
854     DWORD bufSize = 0;
855     BOOL ret;
856     CERT_RDN rdn;
857     CERT_NAME_INFO info = { 1, &rdn };
858
859     /* test empty name */
860     bufSize = 0;
861     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
862      emptySequence[1] + 2,
863      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
864      (BYTE *)&buf, &bufSize);
865     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
866     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
867      * decoder works the same way, so only test the count.
868      */
869     if (buf)
870     {
871         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %ld\n", bufSize);
872         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
873          "Expected 0 RDNs in empty info, got %ld\n",
874          ((CERT_NAME_INFO *)buf)->cRDN);
875         LocalFree(buf);
876     }
877     /* test empty RDN */
878     bufSize = 0;
879     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
880      emptyRDNs[1] + 2,
881      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
882      (BYTE *)&buf, &bufSize);
883     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
884     if (buf)
885     {
886         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
887
888         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
889          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
890          "Got unexpected value for empty RDN\n");
891         LocalFree(buf);
892     }
893     /* test two RDN attrs */
894     bufSize = 0;
895     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
896      twoRDNs[1] + 2,
897      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
898      (BYTE *)&buf, &bufSize);
899     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
900     if (buf)
901     {
902         CERT_RDN_ATTR attrs[] = {
903          { szOID_SUR_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
904           (BYTE *)surName } },
905          { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
906           (BYTE *)commonName } },
907         };
908
909         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
910         rdn.rgRDNAttr = attrs;
911         compareNames(&info, (CERT_NAME_INFO *)buf);
912         LocalFree(buf);
913     }
914     /* And, a slightly more complicated name */
915     buf = NULL;
916     bufSize = 0;
917     ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
918      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
919     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
920     if (ret)
921     {
922         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
923         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
924         compareNames(&info, (CERT_NAME_INFO *)buf);
925         LocalFree(buf);
926     }
927 }
928
929 struct EncodedNameValue
930 {
931     CERT_NAME_VALUE value;
932     const BYTE *encoded;
933     DWORD encodedSize;
934 };
935
936 static const char bogusIA5[] = "\x80";
937 static const char bogusPrintable[] = "~";
938 static const char bogusNumeric[] = "A";
939 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
940 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
941 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
942 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
943 static BYTE octetCommonNameValue[] = {
944  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
945 static BYTE numericCommonNameValue[] = {
946  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
947 static BYTE printableCommonNameValue[] = {
948  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
949 static BYTE t61CommonNameValue[] = {
950  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
951 static BYTE videotexCommonNameValue[] = {
952  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
953 static BYTE ia5CommonNameValue[] = {
954  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
955 static BYTE graphicCommonNameValue[] = {
956  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
957 static BYTE visibleCommonNameValue[] = {
958  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
959 static BYTE generalCommonNameValue[] = {
960  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
961 static BYTE bmpCommonNameValue[] = {
962  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
963  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
964 static BYTE utf8CommonNameValue[] = {
965  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
966
967 static struct EncodedNameValue nameValues[] = {
968  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
969      octetCommonNameValue, sizeof(octetCommonNameValue) },
970  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
971      numericCommonNameValue, sizeof(numericCommonNameValue) },
972  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
973      printableCommonNameValue, sizeof(printableCommonNameValue) },
974  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
975      t61CommonNameValue, sizeof(t61CommonNameValue) },
976  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
977      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
978  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
979      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
980  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
981      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
982  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
983      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
984  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
985      generalCommonNameValue, sizeof(generalCommonNameValue) },
986  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
987      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
988  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
989      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
990  /* The following tests succeed under Windows, but really should fail,
991   * they contain characters that are illegal for the encoding.  I'm
992   * including them to justify my lazy encoding.
993   */
994  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
995      sizeof(bin42) },
996  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
997      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
998  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
999      bin44, sizeof(bin44) },
1000 };
1001
1002 static void test_encodeNameValue(DWORD dwEncoding)
1003 {
1004     BYTE *buf = NULL;
1005     DWORD size = 0, i;
1006     BOOL ret;
1007     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1008
1009     value.dwValueType = 14;
1010     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1011      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1012     ok(!ret && GetLastError() == CRYPT_E_ASN1_CHOICE,
1013      "Expected CRYPT_E_ASN1_CHOICE, got %08lx\n", GetLastError());
1014     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1015     value.Value.pbData = printableCommonNameValue;
1016     value.Value.cbData = sizeof(printableCommonNameValue);
1017     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1018      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1019     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1020     if (buf)
1021     {
1022         ok(size == sizeof(printableCommonNameValue), "Unexpected size %ld\n",
1023          size);
1024         ok(!memcmp(buf, printableCommonNameValue, size),
1025          "Unexpected encoding\n");
1026         LocalFree(buf);
1027     }
1028     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1029     {
1030         ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1031          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1032          &size);
1033         ok(ret, "Type %ld: CryptEncodeObjectEx failed: %08lx\n",
1034          nameValues[i].value.dwValueType, GetLastError());
1035         if (buf)
1036         {
1037             ok(size == nameValues[i].encodedSize,
1038              "Expected size %ld, got %ld\n", nameValues[i].encodedSize, size);
1039             ok(!memcmp(buf, nameValues[i].encoded, size),
1040              "Got unexpected encoding\n");
1041             LocalFree(buf);
1042         }
1043     }
1044 }
1045
1046 static void test_decodeNameValue(DWORD dwEncoding)
1047 {
1048     int i;
1049     BYTE *buf = NULL;
1050     DWORD bufSize = 0;
1051     BOOL ret;
1052
1053     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1054     {
1055         ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1056          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1057          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1058          (BYTE *)&buf, &bufSize);
1059         ok(ret, "Value type %ld: CryptDecodeObjectEx failed: %08lx\n",
1060          nameValues[i].value.dwValueType, GetLastError());
1061         if (buf)
1062         {
1063             compareNameValues(&nameValues[i].value,
1064              (const CERT_NAME_VALUE *)buf);
1065             LocalFree(buf);
1066         }
1067     }
1068 }
1069
1070 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1071 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1072  'h','q','.','o','r','g',0 };
1073 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1074  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1075  0x6f, 0x72, 0x67 };
1076 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1077  0x575b, 0 };
1078 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1079 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1080  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1081 static const BYTE localhost[] = { 127, 0, 0, 1 };
1082 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1083  0x01 };
1084
1085 static void test_encodeAltName(DWORD dwEncoding)
1086 {
1087     CERT_ALT_NAME_INFO info = { 0 };
1088     CERT_ALT_NAME_ENTRY entry = { 0 };
1089     BYTE *buf = NULL;
1090     DWORD size = 0;
1091     BOOL ret;
1092
1093     /* Test with empty info */
1094     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1095      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1096     if (buf)
1097     {
1098         ok(size == sizeof(emptySequence), "Wrong size %ld\n", size);
1099         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1100         LocalFree(buf);
1101     }
1102     /* Test with an empty entry */
1103     info.cAltEntry = 1;
1104     info.rgAltEntry = &entry;
1105     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1106      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1107     ok(!ret && GetLastError() == E_INVALIDARG,
1108      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1109     /* Test with an empty pointer */
1110     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1111     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1112      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1113     if (buf)
1114     {
1115         ok(size == sizeof(emptyURL), "Wrong size %ld\n", size);
1116         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1117         LocalFree(buf);
1118     }
1119     /* Test with a real URL */
1120     U(entry).pwszURL = (LPWSTR)url;
1121     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1122      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1123     if (buf)
1124     {
1125         ok(size == sizeof(encodedURL), "Wrong size %ld\n", size);
1126         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1127         LocalFree(buf);
1128     }
1129     /* Now with the URL containing an invalid IA5 char */
1130     U(entry).pwszURL = (LPWSTR)nihongoURL;
1131     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1132      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1133     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1134      "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
1135     /* The first invalid character is at index 7 */
1136     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1137      "Expected invalid char at index 7, got %ld\n",
1138      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1139     /* Now with the URL missing a scheme */
1140     U(entry).pwszURL = (LPWSTR)dnsName;
1141     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1142      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1143     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1144     if (buf)
1145     {
1146         /* This succeeds, but it shouldn't, so don't worry about conforming */
1147         LocalFree(buf);
1148     }
1149     /* Now with a DNS name */
1150     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1151     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1152      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1153     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1154     if (buf)
1155     {
1156         ok(size == sizeof(encodedDnsName), "Wrong size %ld\n", size);
1157         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1158         LocalFree(buf);
1159     }
1160     /* Test with an IP address */
1161     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1162     U(entry).IPAddress.cbData = sizeof(localhost);
1163     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1164     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1165      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1166     if (buf)
1167     {
1168         ok(size == sizeof(encodedIPAddr), "Wrong size %ld\n", size);
1169         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1170         LocalFree(buf);
1171     }
1172 }
1173
1174 static void test_decodeAltName(DWORD dwEncoding)
1175 {
1176     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1177      0x00, 0x00, 0x01 };
1178     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1179      0x01 };
1180     BOOL ret;
1181     BYTE *buf = NULL;
1182     DWORD bufSize = 0;
1183     CERT_ALT_NAME_INFO *info;
1184
1185     /* Test some bogus ones first */
1186     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1187      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1188      NULL, (BYTE *)&buf, &bufSize);
1189     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1190      "Expected CRYPT_E_ASN1_BADTAG, got %08lx\n", GetLastError());
1191     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1192      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1193      &bufSize);
1194     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1195      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1196     /* Now expected cases */
1197     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1198      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1199      &bufSize);
1200     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1201     if (buf)
1202     {
1203         info = (CERT_ALT_NAME_INFO *)buf;
1204
1205         ok(info->cAltEntry == 0, "Expected 0 entries, got %ld\n",
1206          info->cAltEntry);
1207         LocalFree(buf);
1208     }
1209     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1210      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1211      &bufSize);
1212     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1213     if (buf)
1214     {
1215         info = (CERT_ALT_NAME_INFO *)buf;
1216
1217         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1218          info->cAltEntry);
1219         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1220          "Expected CERT_ALT_NAME_URL, got %ld\n",
1221          info->rgAltEntry[0].dwAltNameChoice);
1222         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1223          "Expected empty URL\n");
1224         LocalFree(buf);
1225     }
1226     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1227      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1228      &bufSize);
1229     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1230     if (buf)
1231     {
1232         info = (CERT_ALT_NAME_INFO *)buf;
1233
1234         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1235          info->cAltEntry);
1236         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1237          "Expected CERT_ALT_NAME_URL, got %ld\n",
1238          info->rgAltEntry[0].dwAltNameChoice);
1239         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1240         LocalFree(buf);
1241     }
1242     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1243      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1244      &bufSize);
1245     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1246     if (buf)
1247     {
1248         info = (CERT_ALT_NAME_INFO *)buf;
1249
1250         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1251          info->cAltEntry);
1252         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1253          "Expected CERT_ALT_NAME_DNS_NAME, got %ld\n",
1254          info->rgAltEntry[0].dwAltNameChoice);
1255         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1256          "Unexpected DNS name\n");
1257         LocalFree(buf);
1258     }
1259     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1260      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1261      &bufSize);
1262     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1263     if (buf)
1264     {
1265         info = (CERT_ALT_NAME_INFO *)buf;
1266
1267         ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1268          info->cAltEntry);
1269         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1270          "Expected CERT_ALT_NAME_IP_ADDRESS, got %ld\n",
1271          info->rgAltEntry[0].dwAltNameChoice);
1272         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1273          "Unexpected IP address length %ld\n",
1274           U(info->rgAltEntry[0]).IPAddress.cbData);
1275         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1276          sizeof(localhost)), "Unexpected IP address value\n");
1277         LocalFree(buf);
1278     }
1279 }
1280
1281 struct UnicodeExpectedError
1282 {
1283     DWORD   valueType;
1284     LPCWSTR str;
1285     DWORD   errorIndex;
1286     DWORD   error;
1287 };
1288
1289 static const WCHAR oneW[] = { '1',0 };
1290 static const WCHAR aW[] = { 'a',0 };
1291 static const WCHAR quoteW[] = { '"', 0 };
1292
1293 static struct UnicodeExpectedError unicodeErrors[] = {
1294  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1295  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1296  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1297  { 14,                        oneW,       0, CRYPT_E_ASN1_CHOICE },
1298  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1299  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1300  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1301 };
1302
1303 struct UnicodeExpectedResult
1304 {
1305     DWORD           valueType;
1306     LPCWSTR         str;
1307     CRYPT_DATA_BLOB encoded;
1308 };
1309
1310 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1311 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1312 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1313 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1314 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1315 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1316 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1317 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1318 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1319 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1320 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1321 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1322  0x5b };
1323 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1324  0x6f,0x5b };
1325 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1326  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1327 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1328  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1329
1330 static struct UnicodeExpectedResult unicodeResults[] = {
1331  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1332  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1333  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1334  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1335  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1336  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1337  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1338  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1339  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1340  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1341  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1342  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1343  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1344 };
1345
1346 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1347  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1348  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1349 };
1350
1351 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1352 {
1353     BYTE *buf = NULL;
1354     DWORD size = 0, i;
1355     BOOL ret;
1356     CERT_NAME_VALUE value;
1357
1358     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1359      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1360     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1361      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
1362     /* Have to have a string of some sort */
1363     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1364     value.Value.pbData = NULL;
1365     value.Value.cbData = 0;
1366     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1367      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1368     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1369      "Expected CRYPT_E_NOT_CHAR_STRING, got %08lx\n", GetLastError());
1370     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1371     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1372      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1373     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1374      "Expected CRYPT_E_NOT_CHAR_STRING, got %08lx\n", GetLastError());
1375     value.dwValueType = CERT_RDN_ANY_TYPE;
1376     value.Value.pbData = (LPBYTE)oneW;
1377     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1378      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1379     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1380      "Expected CRYPT_E_NOT_CHAR_STRING, got %08lx\n", GetLastError());
1381     value.Value.cbData = sizeof(oneW);
1382     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1383      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1384     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1385      "Expected CRYPT_E_NOT_CHAR_STRING, got %08lx\n", GetLastError());
1386     /* An encoded string with specified length isn't good enough either */
1387     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1388     value.Value.pbData = oneUniversal;
1389     value.Value.cbData = sizeof(oneUniversal);
1390     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1391      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1392     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1393      "Expected CRYPT_E_NOT_CHAR_STRING, got %08lx\n", GetLastError());
1394     /* More failure checking */
1395     value.Value.cbData = 0;
1396     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1397     {
1398         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1399         value.dwValueType = unicodeErrors[i].valueType;
1400         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1401          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1402         ok(!ret && GetLastError() == unicodeErrors[i].error,
1403          "Value type %ld: expected %08lx, got %08lx\n", value.dwValueType,
1404          unicodeErrors[i].error, GetLastError());
1405         ok(size == unicodeErrors[i].errorIndex,
1406          "Expected error index %ld, got %ld\n", unicodeErrors[i].errorIndex,
1407          size);
1408     }
1409     /* cbData can be zero if the string is NULL-terminated */
1410     value.Value.cbData = 0;
1411     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1412     {
1413         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1414         value.dwValueType = unicodeResults[i].valueType;
1415         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1416          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1417         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1418         if (buf)
1419         {
1420             ok(size == unicodeResults[i].encoded.cbData,
1421              "Value type %ld: expected size %ld, got %ld\n",
1422              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1423             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1424              "Value type %ld: unexpected value\n", value.dwValueType);
1425             LocalFree(buf);
1426         }
1427     }
1428     /* These "encode," but they do so by truncating each unicode character
1429      * rather than properly encoding it.  Kept separate from the proper results,
1430      * because the encoded forms won't decode to their original strings.
1431      */
1432     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1433     {
1434         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1435         value.dwValueType = unicodeWeirdness[i].valueType;
1436         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1437          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1438         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1439         if (buf)
1440         {
1441             ok(size == unicodeWeirdness[i].encoded.cbData,
1442              "Value type %ld: expected size %ld, got %ld\n",
1443              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1444             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1445              "Value type %ld: unexpected value\n", value.dwValueType);
1446             LocalFree(buf);
1447         }
1448     }
1449 }
1450
1451 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1452 {
1453     DWORD i;
1454
1455     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1456     {
1457         BYTE *buf = NULL;
1458         BOOL ret;
1459         DWORD size = 0;
1460
1461         ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1462          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1463          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1464         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1465         if (ret && buf)
1466         {
1467             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1468
1469             ok(value->dwValueType == unicodeResults[i].valueType,
1470              "Expected value type %ld, got %ld\n", unicodeResults[i].valueType,
1471              value->dwValueType);
1472             ok(!lstrcmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str),
1473              "Unexpected decoded value for index %ld (value type %ld)\n", i,
1474              unicodeResults[i].valueType);
1475             LocalFree(buf);
1476         }
1477     }
1478 }
1479
1480 struct encodedOctets
1481 {
1482     const BYTE *val;
1483     const BYTE *encoded;
1484 };
1485
1486 static const unsigned char bin46[] = { 'h','i',0 };
1487 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1488 static const unsigned char bin48[] = {
1489      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1490 static const unsigned char bin49[] = {
1491      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1492 static const unsigned char bin50[] = { 0 };
1493 static const unsigned char bin51[] = { 0x04,0x00,0 };
1494
1495 static const struct encodedOctets octets[] = {
1496     { bin46, bin47 },
1497     { bin48, bin49 },
1498     { bin50, bin51 },
1499 };
1500
1501 static void test_encodeOctets(DWORD dwEncoding)
1502 {
1503     CRYPT_DATA_BLOB blob;
1504     DWORD i;
1505
1506     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1507     {
1508         BYTE *buf = NULL;
1509         BOOL ret;
1510         DWORD bufSize = 0;
1511
1512         blob.cbData = strlen((const char*)octets[i].val);
1513         blob.pbData = (BYTE*)octets[i].val;
1514         ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1515          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1516         ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
1517         if (buf)
1518         {
1519             ok(buf[0] == 4,
1520              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1521             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1522              buf[1], octets[i].encoded[1]);
1523             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1524              octets[i].encoded[1] + 1), "Got unexpected value\n");
1525             LocalFree(buf);
1526         }
1527     }
1528 }
1529
1530 static void test_decodeOctets(DWORD dwEncoding)
1531 {
1532     DWORD i;
1533
1534     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1535     {
1536         BYTE *buf = NULL;
1537         BOOL ret;
1538         DWORD bufSize = 0;
1539
1540         ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1541          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1542          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1543         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1544         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1545          "Expected size >= %d, got %ld\n",
1546            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1547         ok(buf != NULL, "Expected allocated buffer\n");
1548         if (buf)
1549         {
1550             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1551
1552             if (blob->cbData)
1553                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1554                  "Unexpected value\n");
1555             LocalFree(buf);
1556         }
1557     }
1558 }
1559
1560 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1561
1562 struct encodedBits
1563 {
1564     DWORD cUnusedBits;
1565     const BYTE *encoded;
1566     DWORD cbDecoded;
1567     const BYTE *decoded;
1568 };
1569
1570 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1571 static const unsigned char bin53[] = { 0xff,0xff };
1572 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1573 static const unsigned char bin55[] = { 0xff,0xfe };
1574 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1575 static const unsigned char bin57[] = { 0xfe };
1576 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1577
1578 static const struct encodedBits bits[] = {
1579     /* normal test cases */
1580     { 0, bin52, 2, bin53 },
1581     { 1, bin54, 2, bin55 },
1582     /* strange test case, showing cUnusedBits >= 8 is allowed */
1583     { 9, bin56, 1, bin57 },
1584     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1585     { 17, bin58, 0, NULL },
1586 };
1587
1588 static void test_encodeBits(DWORD dwEncoding)
1589 {
1590     DWORD i;
1591
1592     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1593     {
1594         CRYPT_BIT_BLOB blob;
1595         BOOL ret;
1596         BYTE *buf = NULL;
1597         DWORD bufSize = 0;
1598
1599         blob.cbData = sizeof(bytesToEncode);
1600         blob.pbData = (BYTE *)bytesToEncode;
1601         blob.cUnusedBits = bits[i].cUnusedBits;
1602         ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1603          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1604         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1605         if (buf)
1606         {
1607             ok(bufSize == bits[i].encoded[1] + 2,
1608              "Got unexpected size %ld, expected %d\n", bufSize,
1609              bits[i].encoded[1] + 2);
1610             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1611              "Unexpected value\n");
1612             LocalFree(buf);
1613         }
1614     }
1615 }
1616
1617 static void test_decodeBits(DWORD dwEncoding)
1618 {
1619     static const BYTE ber[] = "\x03\x02\x01\xff";
1620     static const BYTE berDecoded = 0xfe;
1621     DWORD i;
1622     BOOL ret;
1623     BYTE *buf = NULL;
1624     DWORD bufSize = 0;
1625
1626     /* normal cases */
1627     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1628     {
1629         ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1630          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1631          &bufSize);
1632         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1633         if (buf)
1634         {
1635             CRYPT_BIT_BLOB *blob;
1636
1637             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1638              "Got unexpected size %ld, expected >= %ld\n", bufSize,
1639              sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded);
1640             blob = (CRYPT_BIT_BLOB *)buf;
1641             ok(blob->cbData == bits[i].cbDecoded,
1642              "Got unexpected length %ld, expected %ld\n", blob->cbData,
1643              bits[i].cbDecoded);
1644             if (blob->cbData && bits[i].cbDecoded)
1645                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1646                  "Unexpected value\n");
1647             LocalFree(buf);
1648         }
1649     }
1650     /* special case: check that something that's valid in BER but not in DER
1651      * decodes successfully
1652      */
1653     ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1654      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1655     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1656     if (buf)
1657     {
1658         CRYPT_BIT_BLOB *blob;
1659
1660         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1661            "Got unexpected size %ld\n", bufSize);
1662         blob = (CRYPT_BIT_BLOB *)buf;
1663         ok(blob->cbData == sizeof(berDecoded),
1664            "Got unexpected length %ld\n", blob->cbData);
1665         if (blob->cbData)
1666             ok(*blob->pbData == berDecoded, "Unexpected value\n");
1667         LocalFree(buf);
1668     }
1669 }
1670
1671 struct Constraints2
1672 {
1673     CERT_BASIC_CONSTRAINTS2_INFO info;
1674     const BYTE *encoded;
1675 };
1676
1677 static const unsigned char bin59[] = { 0x30,0x00 };
1678 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1679 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1680 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1681 static const struct Constraints2 constraints2[] = {
1682  /* empty constraints */
1683  { { FALSE, FALSE, 0}, bin59 },
1684  /* can be a CA */
1685  { { TRUE,  FALSE, 0}, bin60 },
1686  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1687   * but that's not the case
1688   */
1689  { { FALSE, TRUE,  0}, bin61 },
1690  /* can be a CA and has path length constraints set */
1691  { { TRUE,  TRUE,  1}, bin62 },
1692 };
1693
1694 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1695 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1696  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1697  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1698  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1699 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1700  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1701  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1702  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1703  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1704
1705 static void test_encodeBasicConstraints(DWORD dwEncoding)
1706 {
1707     DWORD i, bufSize = 0;
1708     CERT_BASIC_CONSTRAINTS_INFO info;
1709     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1710      (LPBYTE)encodedDomainName };
1711     BOOL ret;
1712     BYTE *buf = NULL;
1713
1714     /* First test with the simpler info2 */
1715     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1716     {
1717         ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1718          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1719          &bufSize);
1720         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1721         if (buf)
1722         {
1723             ok(bufSize == constraints2[i].encoded[1] + 2,
1724              "Expected %d bytes, got %ld\n", constraints2[i].encoded[1] + 2,
1725              bufSize);
1726             ok(!memcmp(buf, constraints2[i].encoded,
1727              constraints2[i].encoded[1] + 2), "Unexpected value\n");
1728             LocalFree(buf);
1729         }
1730     }
1731     /* Now test with more complex basic constraints */
1732     info.SubjectType.cbData = 0;
1733     info.fPathLenConstraint = FALSE;
1734     info.cSubtreesConstraint = 0;
1735     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1736      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1737     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1738     if (buf)
1739     {
1740         ok(bufSize == sizeof(emptyConstraint), "Wrong size %ld\n", bufSize);
1741         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1742          "Unexpected value\n");
1743         LocalFree(buf);
1744     }
1745     /* None of the certs I examined had any subtree constraint, but I test one
1746      * anyway just in case.
1747      */
1748     info.cSubtreesConstraint = 1;
1749     info.rgSubtreesConstraint = &nameBlob;
1750     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1751      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1752     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1753     if (buf)
1754     {
1755         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %ld\n", bufSize);
1756         ok(!memcmp(buf, constraintWithDomainName,
1757          sizeof(constraintWithDomainName)), "Unexpected value\n");
1758         LocalFree(buf);
1759     }
1760     /* FIXME: test encoding with subject type. */
1761 }
1762
1763 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1764 static const unsigned char encodedCommonName[] = {
1765     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1766
1767 static void test_decodeBasicConstraints(DWORD dwEncoding)
1768 {
1769     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1770      0xff };
1771     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1772     DWORD i;
1773     BOOL ret;
1774     BYTE *buf = NULL;
1775     DWORD bufSize = 0;
1776
1777     /* First test with simpler info2 */
1778     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1779     {
1780         ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1781          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1782          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1783         ok(ret, "CryptDecodeObjectEx failed for item %ld: %08lx\n", i,
1784          GetLastError());
1785         if (buf)
1786         {
1787             CERT_BASIC_CONSTRAINTS2_INFO *info =
1788              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1789
1790             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1791              "Unexpected value for item %ld\n", i);
1792             LocalFree(buf);
1793         }
1794     }
1795     /* Check with the order of encoded elements inverted */
1796     buf = (PBYTE)1;
1797     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1798      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1799      &bufSize);
1800     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1801      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1802     ok(!buf, "Expected buf to be set to NULL\n");
1803     /* Check with a non-DER bool */
1804     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1805      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1806      (BYTE *)&buf, &bufSize);
1807     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1808     if (buf)
1809     {
1810         CERT_BASIC_CONSTRAINTS2_INFO *info =
1811          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1812
1813         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
1814         LocalFree(buf);
1815     }
1816     /* Check with a non-basic constraints value */
1817     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1818      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
1819      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1820     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1821      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1822     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
1823     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
1824      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
1825      (BYTE *)&buf, &bufSize);
1826     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1827     if (buf)
1828     {
1829         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
1830
1831         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
1832         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
1833         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
1834         LocalFree(buf);
1835     }
1836     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
1837      constraintWithDomainName, sizeof(constraintWithDomainName),
1838      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1839     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1840     if (buf)
1841     {
1842         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
1843
1844         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
1845         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
1846         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
1847         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
1848         {
1849             ok(info->rgSubtreesConstraint[0].cbData ==
1850              sizeof(encodedDomainName), "Wrong size %ld\n",
1851              info->rgSubtreesConstraint[0].cbData);
1852             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
1853              sizeof(encodedDomainName)), "Unexpected value\n");
1854         }
1855         LocalFree(buf);
1856     }
1857 }
1858
1859 /* These are terrible public keys of course, I'm just testing encoding */
1860 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
1861 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
1862 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
1863 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
1864 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
1865 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1866 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
1867 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1868
1869 struct EncodedRSAPubKey
1870 {
1871     const BYTE *modulus;
1872     size_t modulusLen;
1873     const BYTE *encoded;
1874     size_t decodedModulusLen;
1875 };
1876
1877 struct EncodedRSAPubKey rsaPubKeys[] = {
1878     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
1879     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
1880     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
1881     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
1882 };
1883
1884 static void test_encodeRsaPublicKey(DWORD dwEncoding)
1885 {
1886     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
1887     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
1888     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
1889     BOOL ret;
1890     BYTE *buf = NULL;
1891     DWORD bufSize = 0, i;
1892
1893     /* Try with a bogus blob type */
1894     hdr->bType = 2;
1895     hdr->bVersion = CUR_BLOB_VERSION;
1896     hdr->reserved = 0;
1897     hdr->aiKeyAlg = CALG_RSA_KEYX;
1898     rsaPubKey->magic = 0x31415352;
1899     rsaPubKey->bitlen = sizeof(modulus1) * 8;
1900     rsaPubKey->pubexp = 65537;
1901     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
1902      sizeof(modulus1));
1903
1904     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1905      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1906      &bufSize);
1907     ok(!ret && GetLastError() == E_INVALIDARG,
1908      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1909     /* Now with a bogus reserved field */
1910     hdr->bType = PUBLICKEYBLOB;
1911     hdr->reserved = 1;
1912     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1913      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1914      &bufSize);
1915     if (buf)
1916     {
1917         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1918          "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1919         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1920         LocalFree(buf);
1921     }
1922     /* Now with a bogus blob version */
1923     hdr->reserved = 0;
1924     hdr->bVersion = 0;
1925     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1926      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1927      &bufSize);
1928     if (buf)
1929     {
1930         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1931          "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1932         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1933         LocalFree(buf);
1934     }
1935     /* And with a bogus alg ID */
1936     hdr->bVersion = CUR_BLOB_VERSION;
1937     hdr->aiKeyAlg = CALG_DES;
1938     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1939      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1940      &bufSize);
1941     if (buf)
1942     {
1943         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1944          "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1945         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1946         LocalFree(buf);
1947     }
1948     /* Check a couple of RSA-related OIDs */
1949     hdr->aiKeyAlg = CALG_RSA_KEYX;
1950     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
1951      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1952     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1953      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1954     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1955      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1956     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1957      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1958     /* Finally, all valid */
1959     hdr->aiKeyAlg = CALG_RSA_KEYX;
1960     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1961     {
1962         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1963          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
1964         ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1965          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1966         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1967         if (buf)
1968         {
1969             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
1970              "Expected size %d, got %ld\n", rsaPubKeys[i].encoded[1] + 2,
1971              bufSize);
1972             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
1973              "Unexpected value\n");
1974             LocalFree(buf);
1975         }
1976     }
1977 }
1978
1979 static void test_decodeRsaPublicKey(DWORD dwEncoding)
1980 {
1981     DWORD i;
1982     LPBYTE buf = NULL;
1983     DWORD bufSize = 0;
1984     BOOL ret;
1985
1986     /* Try with a bad length */
1987     ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1988      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
1989      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1990     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1991      "Expected CRYPT_E_ASN1_EOD, got %08lx\n", CRYPT_E_ASN1_EOD);
1992     /* Try with a couple of RSA-related OIDs */
1993     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
1994      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
1995      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1996     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1997      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1998     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1999      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2000      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2001     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2002      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
2003     /* Now try success cases */
2004     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2005     {
2006         bufSize = 0;
2007         ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2008          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2009          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2010         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2011         if (buf)
2012         {
2013             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2014             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2015
2016             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2017              rsaPubKeys[i].decodedModulusLen,
2018              "Wrong size %ld\n", bufSize);
2019             ok(hdr->bType == PUBLICKEYBLOB,
2020              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2021              hdr->bType);
2022             ok(hdr->bVersion == CUR_BLOB_VERSION,
2023              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2024              CUR_BLOB_VERSION, hdr->bVersion);
2025             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2026              hdr->reserved);
2027             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2028              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2029             ok(rsaPubKey->magic == 0x31415352,
2030              "Expected magic RSA1, got %08lx\n", rsaPubKey->magic);
2031             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2032              "Wrong bit len %ld\n", rsaPubKey->bitlen);
2033             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %ld\n",
2034              rsaPubKey->pubexp);
2035             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2036              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2037              "Unexpected modulus\n");
2038             LocalFree(buf);
2039         }
2040     }
2041 }
2042
2043 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2044  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2045  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2046
2047 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2048  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2049  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2050  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2051
2052 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2053 {
2054     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2055     CRYPT_SEQUENCE_OF_ANY seq;
2056     DWORD i;
2057     BOOL ret;
2058     BYTE *buf = NULL;
2059     DWORD bufSize = 0;
2060
2061     /* Encode a homogenous sequence */
2062     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2063     {
2064         blobs[i].cbData = ints[i].encoded[1] + 2;
2065         blobs[i].pbData = (BYTE *)ints[i].encoded;
2066     }
2067     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2068     seq.rgValue = blobs;
2069
2070     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2071      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2072     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2073     if (buf)
2074     {
2075         ok(bufSize == sizeof(intSequence), "Wrong size %ld\n", bufSize);
2076         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2077         LocalFree(buf);
2078     }
2079     /* Change the type of the first element in the sequence, and give it
2080      * another go
2081      */
2082     blobs[0].cbData = times[0].encodedTime[1] + 2;
2083     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2084     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2085      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2086     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2087     if (buf)
2088     {
2089         ok(bufSize == sizeof(mixedSequence), "Wrong size %ld\n", bufSize);
2090         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2091          "Unexpected value\n");
2092         LocalFree(buf);
2093     }
2094 }
2095
2096 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2097 {
2098     BOOL ret;
2099     BYTE *buf = NULL;
2100     DWORD bufSize = 0;
2101
2102     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2103      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2104     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2105     if (buf)
2106     {
2107         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2108         DWORD i;
2109
2110         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2111          "Wrong elements %ld\n", seq->cValue);
2112         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2113         {
2114             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2115              "Expected %d bytes, got %ld\n", ints[i].encoded[1] + 2,
2116              seq->rgValue[i].cbData);
2117             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2118              ints[i].encoded[1] + 2), "Unexpected value\n");
2119         }
2120         LocalFree(buf);
2121     }
2122     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2123      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2124      &bufSize);
2125     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2126     if (buf)
2127     {
2128         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2129
2130         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2131          "Wrong elements %ld\n", seq->cValue);
2132         /* Just check the first element since it's all that changed */
2133         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2134          "Expected %d bytes, got %ld\n", times[0].encodedTime[1] + 2,
2135          seq->rgValue[0].cbData);
2136         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2137          times[0].encodedTime[1] + 2), "Unexpected value\n");
2138         LocalFree(buf);
2139     }
2140 }
2141
2142 struct encodedExtensions
2143 {
2144     CERT_EXTENSIONS exts;
2145     const BYTE *encoded;
2146 };
2147
2148 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2149 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2150
2151 static CERT_EXTENSION criticalExt =
2152  { szOID_BASIC_CONSTRAINTS2, TRUE, { 8, crit_ext_data } };
2153 static CERT_EXTENSION nonCriticalExt =
2154  { szOID_BASIC_CONSTRAINTS2, FALSE, { 8, noncrit_ext_data } };
2155
2156 static const BYTE ext0[] = { 0x30,0x00 };
2157 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2158                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2159 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2160                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2161
2162 static const struct encodedExtensions exts[] = {
2163  { { 0, NULL }, ext0 },
2164  { { 1, &criticalExt }, ext1 },
2165  { { 1, &nonCriticalExt }, ext2 },
2166 };
2167
2168 static void test_encodeExtensions(DWORD dwEncoding)
2169 {
2170     DWORD i;
2171
2172     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2173     {
2174         BOOL ret;
2175         BYTE *buf = NULL;
2176         DWORD bufSize = 0;
2177
2178         ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2179          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2180         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2181         if (buf)
2182         {
2183             ok(bufSize == exts[i].encoded[1] + 2,
2184              "Expected %d bytes, got %ld\n", exts[i].encoded[1] + 2, bufSize);
2185             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2186              "Unexpected value\n");
2187             LocalFree(buf);
2188         }
2189     }
2190 }
2191
2192 static void test_decodeExtensions(DWORD dwEncoding)
2193 {
2194     DWORD i;
2195
2196     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2197     {
2198         BOOL ret;
2199         BYTE *buf = NULL;
2200         DWORD bufSize = 0;
2201
2202         ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2203          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2204          NULL, (BYTE *)&buf, &bufSize);
2205         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2206         if (buf)
2207         {
2208             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2209             DWORD j;
2210
2211             ok(ext->cExtension == exts[i].exts.cExtension,
2212              "Expected %ld extensions, see %ld\n", exts[i].exts.cExtension,
2213              ext->cExtension);
2214             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2215             {
2216                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2217                  exts[i].exts.rgExtension[j].pszObjId),
2218                  "Expected OID %s, got %s\n",
2219                  exts[i].exts.rgExtension[j].pszObjId,
2220                  ext->rgExtension[j].pszObjId);
2221                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2222                  exts[i].exts.rgExtension[j].Value.pbData,
2223                  exts[i].exts.rgExtension[j].Value.cbData),
2224                  "Unexpected value\n");
2225             }
2226             LocalFree(buf);
2227         }
2228     }
2229 }
2230
2231 /* MS encodes public key info with a NULL if the algorithm identifier's
2232  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2233  * it encodes them by omitting the algorithm parameters.  This latter approach
2234  * seems more correct, so accept either form.
2235  */
2236 struct encodedPublicKey
2237 {
2238     CERT_PUBLIC_KEY_INFO info;
2239     const BYTE *encoded;
2240     const BYTE *encodedNoNull;
2241     CERT_PUBLIC_KEY_INFO decoded;
2242 };
2243
2244 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2245  0xe, 0xf };
2246 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2247
2248 static const unsigned char bin64[] = {
2249     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2250 static const unsigned char bin65[] = {
2251     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2252 static const unsigned char bin66[] = {
2253     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2254 static const unsigned char bin67[] = {
2255     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2256 static const unsigned char bin68[] = {
2257     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2258     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2259 static const unsigned char bin69[] = {
2260     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2261     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2262 static const unsigned char bin70[] = {
2263     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2264     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2265     0x0f};
2266 static const unsigned char bin71[] = {
2267     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2268     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2269     0x0f};
2270 static unsigned char bin72[] = { 0x05,0x00};
2271
2272 static const struct encodedPublicKey pubKeys[] = {
2273  /* with a bogus OID */
2274  { { { "1.2.3", { 0, NULL } }, { 0, NULL, 0 } },
2275   bin64, bin65,
2276   { { "1.2.3", { 2, bin72 } }, { 0, NULL, 0 } } },
2277  /* some normal keys */
2278  { { { szOID_RSA, { 0, NULL } }, { 0, NULL, 0} },
2279   bin66, bin67,
2280   { { szOID_RSA, { 2, bin72 } }, { 0, NULL, 0 } } },
2281  { { { szOID_RSA, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2282   bin68, bin69,
2283   { { szOID_RSA, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2284  /* with add'l parameters--note they must be DER-encoded */
2285  { { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2286   (BYTE *)aKey, 0 } },
2287   bin70, bin71,
2288   { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2289   (BYTE *)aKey, 0 } } },
2290 };
2291
2292 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2293 {
2294     DWORD i;
2295
2296     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2297     {
2298         BOOL ret;
2299         BYTE *buf = NULL;
2300         DWORD bufSize = 0;
2301
2302         ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2303          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2304          &bufSize);
2305         ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2306         if (buf)
2307         {
2308             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2309              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2310              "Expected %d or %d bytes, got %ld\n", pubKeys[i].encoded[1] + 2,
2311              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2312             if (bufSize == pubKeys[i].encoded[1] + 2)
2313                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2314                  "Unexpected value\n");
2315             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2316                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2317                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2318             LocalFree(buf);
2319         }
2320     }
2321 }
2322
2323 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2324  const CERT_PUBLIC_KEY_INFO *got)
2325 {
2326     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2327      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2328      got->Algorithm.pszObjId);
2329     ok(expected->Algorithm.Parameters.cbData ==
2330      got->Algorithm.Parameters.cbData,
2331      "Expected parameters of %ld bytes, got %ld\n",
2332      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2333     if (expected->Algorithm.Parameters.cbData)
2334         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2335          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2336          "Unexpected algorithm parameters\n");
2337     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2338      "Expected public key of %ld bytes, got %ld\n",
2339      expected->PublicKey.cbData, got->PublicKey.cbData);
2340     if (expected->PublicKey.cbData)
2341         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2342          got->PublicKey.cbData), "Unexpected public key value\n");
2343 }
2344
2345 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2346 {
2347     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2348      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2349      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2350      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2351     DWORD i;
2352     BOOL ret;
2353     BYTE *buf = NULL;
2354     DWORD bufSize = 0;
2355
2356     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2357     {
2358         /* The NULL form decodes to the decoded member */
2359         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2360          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2361          NULL, (BYTE *)&buf, &bufSize);
2362         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2363         if (buf)
2364         {
2365             comparePublicKeyInfo(&pubKeys[i].decoded,
2366              (CERT_PUBLIC_KEY_INFO *)buf);
2367             LocalFree(buf);
2368         }
2369         /* The non-NULL form decodes to the original */
2370         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2371          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2372          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2373         ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2374         if (buf)
2375         {
2376             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2377             LocalFree(buf);
2378         }
2379     }
2380     /* Test with bogus (not valid DER) parameters */
2381     ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2382      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2383      NULL, (BYTE *)&buf, &bufSize);
2384     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2385      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2386 }
2387
2388 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2389  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2390  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2391  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2392  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2393 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2394  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2395  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2396  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2397  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2398 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2399  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2400  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2401  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2402  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2403 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2404  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2405  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2406  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2407  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2408  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2409  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2410 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2411  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2412  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2413  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2414  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2415  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2416  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2417 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2418  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2419  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2420  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2421  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2422  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2423  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2424  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2425  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2426  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2427
2428 static const BYTE serialNum[] = { 0x01 };
2429
2430 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2431 {
2432     BOOL ret;
2433     BYTE *buf = NULL;
2434     DWORD size = 0;
2435     CERT_INFO info = { 0 };
2436
2437     /* Test with NULL pvStructInfo */
2438     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2439      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2440     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2441      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2442     /* Test with a V1 cert */
2443     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2444      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2445     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2446     if (buf)
2447     {
2448         ok(size == v1Cert[1] + 2, "Expected size %d, got %ld\n",
2449          v1Cert[1] + 2, size);
2450         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2451         LocalFree(buf);
2452     }
2453     /* Test v2 cert */
2454     info.dwVersion = CERT_V2;
2455     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2456      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2457     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2458     if (buf)
2459     {
2460         ok(size == sizeof(v2Cert), "Wrong size %ld\n", size);
2461         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2462         LocalFree(buf);
2463     }
2464     /* Test v3 cert */
2465     info.dwVersion = CERT_V3;
2466     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2467      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2468     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2469     if (buf)
2470     {
2471         ok(size == sizeof(v3Cert), "Wrong size %ld\n", size);
2472         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2473         LocalFree(buf);
2474     }
2475     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2476      * API doesn't prevent it)
2477      */
2478     info.dwVersion = CERT_V1;
2479     info.cExtension = 1;
2480     info.rgExtension = &criticalExt;
2481     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2482      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2483     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2484     if (buf)
2485     {
2486         ok(size == sizeof(v1CertWithConstraints), "Wrong size %ld\n", size);
2487         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2488         LocalFree(buf);
2489     }
2490     /* test v1 cert with a serial number */
2491     info.SerialNumber.cbData = sizeof(serialNum);
2492     info.SerialNumber.pbData = (BYTE *)serialNum;
2493     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2494      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2495     if (buf)
2496     {
2497         ok(size == sizeof(v1CertWithSerial), "Wrong size %ld\n", size);
2498         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2499         LocalFree(buf);
2500     }
2501     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2502     info.Issuer.cbData = sizeof(encodedCommonName);
2503     info.Issuer.pbData = (BYTE *)encodedCommonName;
2504     info.Subject.cbData = sizeof(encodedCommonName);
2505     info.Subject.pbData = (BYTE *)encodedCommonName;
2506     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2507      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2508     if (buf)
2509     {
2510         ok(size == sizeof(bigCert), "Wrong size %ld\n", size);
2511         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2512         LocalFree(buf);
2513     }
2514     /* for now, I let more interesting tests be done for each subcomponent,
2515      * rather than retesting them all here.
2516      */
2517 }
2518
2519 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2520 {
2521     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2522      v1CertWithConstraints, v1CertWithSerial };
2523     BOOL ret;
2524     BYTE *buf = NULL;
2525     DWORD size = 0, i;
2526
2527     /* Test with NULL pbEncoded */
2528     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2529      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2530     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2531      "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
2532     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2533      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2534     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2535      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2536     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2537      * minimum a cert must have a non-zero serial number, an issuer, and a
2538      * subject.
2539      */
2540     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2541     {
2542         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2543          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2544          (BYTE *)&buf, &size);
2545         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2546          "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2547     }
2548     /* Now check with serial number, subject and issuer specified */
2549     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2550      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2551     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2552     if (buf)
2553     {
2554         CERT_INFO *info = (CERT_INFO *)buf;
2555
2556         ok(size >= sizeof(CERT_INFO), "Wrong size %ld\n", size);
2557         ok(info->SerialNumber.cbData == 1,
2558          "Expected serial number size 1, got %ld\n", info->SerialNumber.cbData);
2559         ok(*info->SerialNumber.pbData == *serialNum,
2560          "Expected serial number %d, got %d\n", *serialNum,
2561          *info->SerialNumber.pbData);
2562         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2563          "Wrong size %ld\n", info->Issuer.cbData);
2564         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2565          "Unexpected issuer\n");
2566         ok(info->Subject.cbData == sizeof(encodedCommonName),
2567          "Wrong size %ld\n", info->Subject.cbData);
2568         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2569          info->Subject.cbData), "Unexpected subject\n");
2570         LocalFree(buf);
2571     }
2572 }
2573
2574 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2575  0xe, 0xf };
2576
2577 static const BYTE signedBigCert[] = {
2578  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2579  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2580  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2581  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2582  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2583  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2584  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2585  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2586  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2587  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2588  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2589  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2590
2591 static void test_encodeCert(DWORD dwEncoding)
2592 {
2593     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
2594      * also that bigCert is a NULL-terminated string, so don't count its
2595      * last byte (otherwise the signed cert won't decode.)
2596      */
2597     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2598      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2599     BOOL ret;
2600     BYTE *buf = NULL;
2601     DWORD bufSize = 0;
2602
2603     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2604      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2605     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2606     if (buf)
2607     {
2608         ok(bufSize == sizeof(signedBigCert), "Wrong size %ld\n", bufSize);
2609         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2610         LocalFree(buf);
2611     }
2612 }
2613
2614 static void test_decodeCert(DWORD dwEncoding)
2615 {
2616     BOOL ret;
2617     BYTE *buf = NULL;
2618     DWORD size = 0;
2619
2620     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2621      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2622     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2623     if (buf)
2624     {
2625         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2626
2627         ok(info->ToBeSigned.cbData == sizeof(bigCert),
2628          "Wrong cert size %ld\n", info->ToBeSigned.cbData);
2629         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2630          "Unexpected cert\n");
2631         ok(info->Signature.cbData == sizeof(hash),
2632          "Wrong signature size %ld\n", info->Signature.cbData);
2633         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2634          "Unexpected signature\n");
2635         LocalFree(buf);
2636     }
2637     /* A signed cert decodes as a CERT_INFO too */
2638     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
2639      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2640     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2641     if (buf)
2642     {
2643         CERT_INFO *info = (CERT_INFO *)buf;
2644
2645         ok(size >= sizeof(CERT_INFO), "Wrong size %ld\n", size);
2646         ok(info->SerialNumber.cbData == 1,
2647          "Expected serial number size 1, got %ld\n", info->SerialNumber.cbData);
2648         ok(*info->SerialNumber.pbData == *serialNum,
2649          "Expected serial number %d, got %d\n", *serialNum,
2650          *info->SerialNumber.pbData);
2651         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2652          "Wrong size %ld\n", info->Issuer.cbData);
2653         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2654          "Unexpected issuer\n");
2655         ok(info->Subject.cbData == sizeof(encodedCommonName),
2656          "Wrong size %ld\n", info->Subject.cbData);
2657         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2658          info->Subject.cbData), "Unexpected subject\n");
2659         LocalFree(buf);
2660     }
2661 }
2662
2663 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2664 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2665  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2666  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2667 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2668  0x00, 0x03 };
2669 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2670  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2671  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2672 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2673  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2674  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2675  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2676  0x2e, 0x6f, 0x72, 0x67 };
2677 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2678  CRL_REASON_AFFILIATION_CHANGED;
2679
2680 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2681 {
2682     CRL_DIST_POINTS_INFO info = { 0 };
2683     CRL_DIST_POINT point = { { 0 } };
2684     CERT_ALT_NAME_ENTRY entry = { 0 };
2685     BOOL ret;
2686     BYTE *buf = NULL;
2687     DWORD size = 0;
2688
2689     /* Test with an empty info */
2690     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2691      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2692     ok(!ret && GetLastError() == E_INVALIDARG,
2693      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
2694     /* Test with one empty dist point */
2695     info.cDistPoint = 1;
2696     info.rgDistPoint = &point;
2697     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2698      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2699     if (buf)
2700     {
2701         ok(size == sizeof(emptyDistPoint), "Wrong size %ld\n", size);
2702         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2703         LocalFree(buf);
2704     }
2705     /* A dist point with an invalid name */
2706     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2707     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2708     U(entry).pwszURL = (LPWSTR)nihongoURL;
2709     U(point.DistPointName).FullName.cAltEntry = 1;
2710     U(point.DistPointName).FullName.rgAltEntry = &entry;
2711     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2712      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2713     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2714      "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
2715     /* The first invalid character is at index 7 */
2716     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2717      "Expected invalid char at index 7, got %ld\n",
2718      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2719     /* A dist point with (just) a valid name */
2720     U(entry).pwszURL = (LPWSTR)url;
2721     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2722      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2723     if (buf)
2724     {
2725         ok(size == sizeof(distPointWithUrl), "Wrong size %ld\n", size);
2726         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2727         LocalFree(buf);
2728     }
2729     /* A dist point with (just) reason flags */
2730     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2731     point.ReasonFlags.cbData = sizeof(crlReason);
2732     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2733     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2734      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2735     if (buf)
2736     {
2737         ok(size == sizeof(distPointWithReason), "Wrong size %ld\n", size);
2738         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2739         LocalFree(buf);
2740     }
2741     /* A dist point with just an issuer */
2742     point.ReasonFlags.cbData = 0;
2743     point.CRLIssuer.cAltEntry = 1;
2744     point.CRLIssuer.rgAltEntry = &entry;
2745     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2746      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2747     if (buf)
2748     {
2749         ok(size == sizeof(distPointWithIssuer), "Wrong size %ld\n", size);
2750         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2751         LocalFree(buf);
2752     }
2753     /* A dist point with both a name and an issuer */
2754     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2755     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2756      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2757     if (buf)
2758     {
2759         ok(size == sizeof(distPointWithUrlAndIssuer),
2760          "Wrong size %ld\n", size);
2761         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2762         LocalFree(buf);
2763     }
2764 }
2765
2766 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2767 {
2768     BOOL ret;
2769     BYTE *buf = NULL;
2770     DWORD size = 0;
2771     PCRL_DIST_POINTS_INFO info;
2772     PCRL_DIST_POINT point;
2773     PCERT_ALT_NAME_ENTRY entry;
2774
2775     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2776      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2777      (BYTE *)&buf, &size);
2778     if (ret)
2779     {
2780         info = (PCRL_DIST_POINTS_INFO)buf;
2781         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2782          "Wrong size %ld\n", size);
2783         ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2784          info->cDistPoint);
2785         point = info->rgDistPoint;
2786         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
2787          "Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
2788          point->DistPointName.dwDistPointNameChoice);
2789         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2790         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2791         LocalFree(buf);
2792     }
2793     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2794      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2795      (BYTE *)&buf, &size);
2796     if (ret)
2797     {
2798         info = (PCRL_DIST_POINTS_INFO)buf;
2799         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2800          "Wrong size %ld\n", size);
2801         ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2802          info->cDistPoint);
2803         point = info->rgDistPoint;
2804         ok(point->DistPointName.dwDistPointNameChoice ==
2805          CRL_DIST_POINT_FULL_NAME,
2806          "Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
2807          point->DistPointName.dwDistPointNameChoice);
2808         ok(U(point->DistPointName).FullName.cAltEntry == 1,
2809          "Expected 1 name entry, got %ld\n",
2810          U(point->DistPointName).FullName.cAltEntry);
2811         entry = U(point->DistPointName).FullName.rgAltEntry;
2812         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2813          "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2814         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2815         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2816         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2817         LocalFree(buf);
2818     }
2819     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2820      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2821      NULL, (BYTE *)&buf, &size);
2822     if (ret)
2823     {
2824         info = (PCRL_DIST_POINTS_INFO)buf;
2825         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2826          "Wrong size %ld\n", size);
2827         ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2828          info->cDistPoint);
2829         point = info->rgDistPoint;
2830         ok(point->DistPointName.dwDistPointNameChoice ==
2831          CRL_DIST_POINT_NO_NAME,
2832          "Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
2833          point->DistPointName.dwDistPointNameChoice);
2834         ok(point->ReasonFlags.cbData == sizeof(crlReason),
2835          "Expected reason length\n");
2836         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
2837          "Unexpected reason\n");
2838         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2839         LocalFree(buf);
2840     }
2841     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2842      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
2843      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2844     if (ret)
2845     {
2846         info = (PCRL_DIST_POINTS_INFO)buf;
2847         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2848          "Wrong size %ld\n", size);
2849         ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2850          info->cDistPoint);
2851         point = info->rgDistPoint;
2852         ok(point->DistPointName.dwDistPointNameChoice ==
2853          CRL_DIST_POINT_FULL_NAME,
2854          "Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
2855          point->DistPointName.dwDistPointNameChoice);
2856         ok(U(point->DistPointName).FullName.cAltEntry == 1,
2857          "Expected 1 name entry, got %ld\n",
2858          U(point->DistPointName).FullName.cAltEntry);
2859         entry = U(point->DistPointName).FullName.rgAltEntry;
2860         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2861          "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2862         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2863         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2864         ok(point->CRLIssuer.cAltEntry == 1,
2865          "Expected 1 issuer entry, got %ld\n", point->CRLIssuer.cAltEntry);
2866         entry = point->CRLIssuer.rgAltEntry;
2867         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2868          "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2869         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2870         LocalFree(buf);
2871     }
2872 }
2873
2874 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
2875 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
2876 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
2877  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
2878  0x67 };
2879
2880 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
2881 {
2882     BOOL ret;
2883     BYTE *buf = NULL;
2884     DWORD size = 0;
2885     CRL_ISSUING_DIST_POINT point = { { 0 } };
2886     CERT_ALT_NAME_ENTRY entry;
2887
2888     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
2889      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2890     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2891      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2892     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
2893      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2894     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2895     if (buf)
2896     {
2897         ok(size == sizeof(emptySequence), "Unexpected size %ld\n", size);
2898         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
2899         LocalFree(buf);
2900     }
2901     /* nonsensical flags */
2902     point.fOnlyContainsUserCerts = TRUE;
2903     point.fOnlyContainsCACerts = TRUE;
2904     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
2905      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2906     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2907     if (buf)
2908     {
2909         ok(size == sizeof(badFlagsIDP), "Unexpected size %ld\n", size);
2910         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
2911         LocalFree(buf);
2912     }
2913     /* unimplemented name type */
2914     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
2915     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
2916     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
2917      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2918     ok(!ret && GetLastError() == E_INVALIDARG,
2919      "Expected E_INVALIDARG, got %08lx\n", GetLastError());
2920     /* empty name */
2921     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2922     U(point.DistPointName).FullName.cAltEntry = 0;
2923     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
2924      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2925     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2926     if (buf)
2927     {
2928         ok(size == sizeof(emptyNameIDP), "Unexpected size %ld\n", size);
2929         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
2930         LocalFree(buf);
2931     }
2932     /* name with URL entry */
2933     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2934     U(entry).pwszURL = (LPWSTR)url;
2935     U(point.DistPointName).FullName.cAltEntry = 1;
2936     U(point.DistPointName).FullName.rgAltEntry = &entry;
2937     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
2938      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2939     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2940     if (buf)
2941     {
2942         ok(size == sizeof(urlIDP), "Unexpected size %ld\n", size);
2943         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
2944         LocalFree(buf);
2945     }
2946 }
2947
2948 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
2949  const CERT_ALT_NAME_ENTRY *got)
2950 {
2951     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
2952      "Expected name choice %ld, got %ld\n", expected->dwAltNameChoice,
2953      got->dwAltNameChoice);
2954     if (expected->dwAltNameChoice == got->dwAltNameChoice)
2955     {
2956         switch (got->dwAltNameChoice)
2957         {
2958         case CERT_ALT_NAME_RFC822_NAME:
2959         case CERT_ALT_NAME_DNS_NAME:
2960         case CERT_ALT_NAME_EDI_PARTY_NAME:
2961         case CERT_ALT_NAME_URL:
2962         case CERT_ALT_NAME_REGISTERED_ID:
2963             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
2964                !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), "Unexpected name\n");
2965             break;
2966         case CERT_ALT_NAME_X400_ADDRESS:
2967         case CERT_ALT_NAME_DIRECTORY_NAME:
2968         case CERT_ALT_NAME_IP_ADDRESS:
2969             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
2970                "Unexpected IP address length %ld\n", U(*got).IPAddress.cbData);
2971             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
2972                        U(*got).IPAddress.cbData), "Unexpected value\n");
2973             break;
2974         }
2975     }
2976 }
2977
2978 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
2979  const CERT_ALT_NAME_INFO *got)
2980 {
2981     DWORD i;
2982
2983     ok(expected->cAltEntry == got->cAltEntry, "Expected %ld entries, got %ld\n",
2984      expected->cAltEntry, got->cAltEntry);
2985     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
2986         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
2987 }
2988
2989 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
2990  const CRL_DIST_POINT_NAME *got)
2991 {
2992     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
2993      "Unexpected name choice %ld\n", got->dwDistPointNameChoice);
2994     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
2995         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
2996 }
2997
2998 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
2999  const CRL_ISSUING_DIST_POINT *got)
3000 {
3001     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3002     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3003      "Unexpected fOnlyContainsUserCerts\n");
3004     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3005      "Unexpected fOnlyContainsCACerts\n");
3006     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3007      "Unexpected reason flags\n");
3008     ok(got->fIndirectCRL == expected->fIndirectCRL,
3009      "Unexpected fIndirectCRL\n");
3010 }
3011
3012 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3013 {
3014     BOOL ret;
3015     BYTE *buf = NULL;
3016     DWORD size = 0;
3017     CRL_ISSUING_DIST_POINT point = { { 0 } };
3018
3019     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3020      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3021      (BYTE *)&buf, &size);
3022     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3023     if (ret)
3024     {
3025         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3026         LocalFree(buf);
3027     }
3028     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3029      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3030      (BYTE *)&buf, &size);
3031     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3032     if (ret)
3033     {
3034         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3035         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3036         LocalFree(buf);
3037     }
3038     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3039      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3040      (BYTE *)&buf, &size);
3041     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3042     if (ret)
3043     {
3044         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3045         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3046         U(point.DistPointName).FullName.cAltEntry = 0;
3047         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3048         LocalFree(buf);
3049     }
3050     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3051      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3052     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3053     if (ret)
3054     {
3055         CERT_ALT_NAME_ENTRY entry;
3056
3057         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3058         U(entry).pwszURL = (LPWSTR)url;
3059         U(point.DistPointName).FullName.cAltEntry = 1;
3060         U(point.DistPointName).FullName.rgAltEntry = &entry;
3061         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3062         LocalFree(buf);
3063     }
3064 }
3065
3066 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3067  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3068  0x30, 0x5a };
3069 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3070  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3071  0x30, 0x30, 0x30, 0x30, 0x5a };
3072 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3073  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3074  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3075  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3076  0x5a };
3077 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3078  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3079  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3080  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3081  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3082  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3083 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3084  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3085  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3086  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3087  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3088  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3089 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3090  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3091  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3092  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3093  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3094  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3095  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3096 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3097  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3098  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3099  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3100  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3101  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3102  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3103 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3104  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3105  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3106  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3107  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3108  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3109  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3110 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3111  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3112  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3113  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3114  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3115  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3116  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3117
3118 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3119 {
3120     BOOL ret;
3121     BYTE *buf = NULL;
3122     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3123     DWORD size = 0;
3124     CRL_INFO info = { 0 };
3125     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3126     CERT_EXTENSION ext;
3127
3128     /* Test with a V1 CRL */
3129     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3130      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3131     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
3132     if (buf)
3133     {
3134         ok(size == sizeof(v1CRL), "Wrong size %ld\n", size);
3135         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3136         LocalFree(buf);
3137     }
3138     /* Test v2 CRL */
3139     info.dwVersion = CRL_V2;
3140     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3141      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3142     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
3143     if (buf)
3144     {
3145         ok(size == v2CRL[1] + 2, "Expected size %d, got %ld\n",
3146          v2CRL[1] + 2, size);
3147         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3148         LocalFree(buf);
3149     }
3150     /* v1 CRL with a name */
3151     info.dwVersion = CRL_V1;
3152     info.Issuer.cbData = sizeof(encodedCommonName);
3153     info.Issuer.pbData = (BYTE *)encodedCommonName;
3154     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3155      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3156     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
3157     if (buf)
3158     {
3159         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %ld\n", size);
3160         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3161         LocalFree(buf);
3162     }
3163     /* v1 CRL with a name and a NULL entry pointer */
3164     info.cCRLEntry = 1;
3165     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3166      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3167     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3168      "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
3169     /* now set an empty entry */
3170     info.rgCRLEntry = &entry;
3171     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3172      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3173     if (buf)
3174     {
3175         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3176          "Wrong size %ld\n", size);
3177         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3178          "Got unexpected value\n");
3179         LocalFree(buf);
3180     }
3181     /* an entry with a serial number */
3182     entry.SerialNumber.cbData = sizeof(serialNum);
3183     entry.SerialNumber.pbData = (BYTE *)serialNum;
3184     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3185      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3186     if (buf)
3187     {
3188         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3189          "Wrong size %ld\n", size);
3190         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3191          "Got unexpected value\n");
3192         LocalFree(buf);
3193     }
3194     /* an entry with an extension */
3195     entry.cExtension = 1;
3196     entry.rgExtension = &criticalExt;
3197     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3198      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3199     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
3200     if (buf)
3201     {
3202         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %ld\n", size);
3203         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3204         LocalFree(buf);
3205     }
3206     /* a CRL with an extension */
3207     entry.cExtension = 0;
3208     info.cExtension = 1;
3209     info.rgExtension = &criticalExt;
3210     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3211      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3212     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
3213     if (buf)
3214     {
3215         ok(size == sizeof(v1CRLWithExt), "Wrong size %ld\n", size);
3216         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3217         LocalFree(buf);
3218     }
3219     /* a v2 CRL with an extension, this time non-critical */
3220     info.dwVersion = CRL_V2;
3221     info.rgExtension = &nonCriticalExt;
3222     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3223      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3224     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
3225     if (buf)
3226     {
3227         ok(size == sizeof(v2CRLWithExt), "Wrong size %ld\n", size);
3228         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3229         LocalFree(buf);
3230     }
3231     /* a v2 CRL with an issuing dist point extension */
3232     ext.pszObjId = oid_issuing_dist_point;
3233     ext.fCritical = TRUE;
3234     ext.Value.cbData = sizeof(urlIDP);
3235     ext.Value.pbData = (LPBYTE)urlIDP;
3236     entry.rgExtension = &ext;
3237     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3238      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3239     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
3240     if (buf)
3241     {
3242         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %ld\n", size);
3243         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3244         LocalFree(buf);
3245     }
3246 }
3247
3248 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3249  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3250  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3251  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3252  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3253  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3254  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3255  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3256  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3257  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3258  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3259  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3260  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3261  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3262  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3263  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3264  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3265  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3266  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3267  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3268  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3269  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3270  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3271  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3272  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3273  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3274  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3275  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3276  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3277  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3278  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3279  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3280  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3281  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3282  0xcd };
3283
3284 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
3285 {
3286     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
3287     BOOL ret;
3288     BYTE *buf = NULL;
3289     DWORD size = 0, i;
3290
3291     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
3292     {
3293         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3294          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3295          (BYTE *)&buf, &size);
3296         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
3297          "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
3298     }
3299     /* at a minimum, a CRL must contain an issuer: */
3300     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3301      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3302      (BYTE *)&buf, &size);
3303     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3304     if (buf)
3305     {
3306         CRL_INFO *info = (CRL_INFO *)buf;
3307
3308         ok(size >= sizeof(CRL_INFO), "Wrong size %ld\n", size);
3309         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %ld\n",
3310          info->cCRLEntry);
3311         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3312          "Wrong issuer size %ld\n", info->Issuer.cbData);
3313         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3314          "Unexpected issuer\n");
3315         LocalFree(buf);
3316     }
3317     /* check decoding with an empty CRL entry */
3318     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3319      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
3320      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3321     todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
3322      "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
3323     /* with a real CRL entry */
3324     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3325      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
3326      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3327     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3328     if (buf)
3329     {
3330         CRL_INFO *info = (CRL_INFO *)buf;
3331         CRL_ENTRY *entry;
3332
3333         ok(size >= sizeof(CRL_INFO), "Wrong size %ld\n", size);
3334         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
3335          info->cCRLEntry);
3336         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
3337         entry = info->rgCRLEntry;
3338         ok(entry->SerialNumber.cbData == 1,
3339          "Expected serial number size 1, got %ld\n",
3340          entry->SerialNumber.cbData);
3341         ok(*entry->SerialNumber.pbData == *serialNum,
3342          "Expected serial number %d, got %d\n", *serialNum,
3343          *entry->SerialNumber.pbData);
3344         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3345          "Wrong issuer size %ld\n", info->Issuer.cbData);
3346         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3347          "Unexpected issuer\n");
3348     }
3349     /* a real CRL from verisign that has extensions */
3350     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3351      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
3352      NULL, (BYTE *)&buf, &size);
3353     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3354     if (buf)
3355     {
3356         CRL_INFO *info = (CRL_INFO *)buf;
3357         CRL_ENTRY *entry;
3358
3359         ok(size >= sizeof(CRL_INFO), "Wrong size %ld\n", size);
3360         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %ld\n",
3361          info->cCRLEntry);
3362         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
3363         entry = info->rgCRLEntry;
3364         ok(info->cExtension == 2, "Expected 2 extensions, got %ld\n",
3365          info->cExtension);
3366     }
3367     /* and finally, with an extension */
3368     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3369      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
3370      NULL, (BYTE *)&buf, &size);
3371     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3372     if (buf)
3373     {
3374         CRL_INFO *info = (CRL_INFO *)buf;
3375         CRL_ENTRY *entry;
3376
3377         ok(size >= sizeof(CRL_INFO), "Wrong size %ld\n", size);
3378         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
3379          info->cCRLEntry);
3380         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
3381         entry = info->rgCRLEntry;
3382         ok(entry->SerialNumber.cbData == 1,
3383          "Expected serial number size 1, got %ld\n",
3384          entry->SerialNumber.cbData);
3385         ok(*entry->SerialNumber.pbData == *serialNum,
3386          "Expected serial number %d, got %d\n", *serialNum,
3387          *entry->SerialNumber.pbData);
3388         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3389          "Wrong issuer size %ld\n", info->Issuer.cbData);
3390         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3391          "Unexpected issuer\n");
3392         ok(info->cExtension == 1, "Expected 1 extensions, got %ld\n",
3393          info->cExtension);
3394     }
3395     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3396      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
3397      NULL, (BYTE *)&buf, &size);
3398     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3399     if (buf)
3400     {
3401         CRL_INFO *info = (CRL_INFO *)buf;
3402
3403         ok(info->cExtension == 1, "Expected 1 extensions, got %ld\n",
3404          info->cExtension);
3405         LocalFree(buf);
3406     }
3407     /* And again, with an issuing dist point */
3408     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
3409      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
3410      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3411     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3412     if (buf)
3413     {
3414         CRL_INFO *info = (CRL_INFO *)buf;
3415
3416         ok(info->cExtension == 1, "Expected 1 extensions, got %ld\n",
3417          info->cExtension);
3418         LocalFree(buf);
3419     }
3420 }
3421
3422 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
3423  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
3424 static const BYTE encodedUsage[] = {
3425  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
3426  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
3427  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
3428
3429 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
3430 {
3431     BOOL ret;
3432     BYTE *buf = NULL;
3433     DWORD size = 0;
3434     CERT_ENHKEY_USAGE usage;
3435
3436     /* Test with empty usage */
3437     usage.cUsageIdentifier = 0;
3438     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
3439      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3440     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
3441     if (buf)
3442     {
3443         ok(size == sizeof(emptySequence), "Wrong size %ld\n", size);
3444         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
3445         LocalFree(buf);
3446     }
3447     /* Test with a few usages */
3448     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
3449     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
3450     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
3451      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3452     ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
3453     if (buf)
3454     {
3455         ok(size == sizeof(encodedUsage), "Wrong size %ld\n", size);
3456         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
3457         LocalFree(buf);
3458     }
3459 }
3460
3461 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
3462 {
3463     BOOL ret;
3464     LPBYTE buf = NULL;
3465     DWORD size = 0;
3466
3467     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
3468      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
3469      (BYTE *)&buf, &size);
3470     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3471     if (buf)
3472     {
3473         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
3474
3475         ok(size >= sizeof(CERT_ENHKEY_USAGE),
3476          "Wrong size %ld\n", size);
3477         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %ld\n",
3478          usage->cUsageIdentifier);
3479         LocalFree(buf);
3480     }
3481     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
3482      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
3483      (BYTE *)&buf, &size);
3484     ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
3485     if (buf)
3486     {
3487         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
3488         DWORD i;
3489
3490         ok(size >= sizeof(CERT_ENHKEY_USAGE),
3491          "Wrong size %ld\n", size);
3492         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
3493          "Wrong CRL entries count %ld\n", usage->cUsageIdentifier);
3494         for (i = 0; i < usage->cUsageIdentifier; i++)
3495             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
3496              "Expected OID %s, got %s\n", keyUsages[i],
3497              usage->rgpszUsageIdentifier[i]);
3498         LocalFree(buf);
3499     }
3500 }
3501
3502 /* Free *pInfo with HeapFree */
3503 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
3504 {
3505     BOOL ret;
3506     DWORD size = 0;
3507     HCRYPTKEY key;
3508
3509     /* This crashes
3510     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
3511      */
3512     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
3513     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3514      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3515     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
3516      &size);
3517     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3518      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3519     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
3520      NULL, &size);
3521     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3522      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3523     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
3524      0, NULL, NULL, &size);
3525     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3526      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3527     /* Test with no key */
3528     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
3529      0, NULL, NULL, &size);
3530     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08lx\n",
3531      GetLastError());
3532     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
3533     ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
3534     if (ret)
3535     {
3536         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
3537          NULL, 0, NULL, NULL, &size);
3538         ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n", GetLastError());
3539         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
3540         if (*pInfo)
3541         {
3542             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
3543              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
3544             ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n",
3545              GetLastError());
3546             if (ret)
3547             {
3548                 /* By default (we passed NULL as the OID) the OID is
3549                  * szOID_RSA_RSA.
3550                  */
3551                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
3552                  "Expected %s, got %s\n", szOID_RSA_RSA,
3553                  (*pInfo)->Algorithm.pszObjId);
3554             }
3555         }
3556     }
3557 }
3558
3559 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
3560  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
3561  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
3562  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
3563  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
3564  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
3565  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
3566  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
3567  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
3568  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
3569  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
3570  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3571  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
3572  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
3573  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
3574  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
3575  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
3576  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
3577  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
3578  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
3579  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
3580  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
3581  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
3582  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
3583  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
3584
3585 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
3586 {
3587     BOOL ret;
3588     HCRYPTKEY key;
3589     PCCERT_CONTEXT context;
3590
3591     /* These crash
3592     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
3593     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
3594     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
3595     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
3596      NULL);
3597      */
3598     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
3599     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3600      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
3601     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
3602     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3603      "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
3604     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
3605      &key);
3606     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3607      "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3608     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
3609      &key);
3610     ok(ret, "CryptImportPublicKeyInfoEx failed: %08lx\n", GetLastError());
3611     CryptDestroyKey(key);
3612
3613     /* Test importing a public key from a certificate context */
3614     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
3615      sizeof(expiredCert));
3616     ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
3617      GetLastError());
3618     if (context)
3619     {
3620         ok(!strcmp(szOID_RSA_RSA,
3621          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
3622          "Expected %s, got %s\n", szOID_RSA_RSA,
3623          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
3624         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
3625          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
3626         ok(ret, "CryptImportPublicKeyInfoEx failed: %08lx\n", GetLastError());
3627         CryptDestroyKey(key);
3628         CertFreeCertificateContext(context);
3629     }
3630 }
3631
3632 static const char cspName[] = "WineCryptTemp";
3633
3634 static void testPortPublicKeyInfo(void)
3635 {
3636     HCRYPTPROV csp;
3637     BOOL ret;
3638     PCERT_PUBLIC_KEY_INFO info = NULL;
3639
3640     /* Just in case a previous run failed, delete this thing */
3641     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3642      CRYPT_DELETEKEYSET);
3643     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3644      CRYPT_NEWKEYSET);
3645
3646     testExportPublicKey(csp, &info);
3647     testImportPublicKey(csp, info);
3648
3649     HeapFree(GetProcessHeap(), 0, info);
3650     CryptReleaseContext(csp, 0);
3651     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3652      CRYPT_DELETEKEYSET);
3653 }
3654
3655 START_TEST(encode)
3656 {
3657     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
3658      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
3659     DWORD i;
3660
3661     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
3662     {
3663         test_encodeInt(encodings[i]);
3664         test_decodeInt(encodings[i]);
3665         test_encodeEnumerated(encodings[i]);
3666         test_decodeEnumerated(encodings[i]);
3667         test_encodeFiletime(encodings[i]);
3668         test_decodeFiletime(encodings[i]);
3669         test_encodeName(encodings[i]);
3670         test_decodeName(encodings[i]);
3671         test_encodeNameValue(encodings[i]);
3672         test_decodeNameValue(encodings[i]);
3673         test_encodeUnicodeNameValue(encodings[i]);
3674         test_decodeUnicodeNameValue(encodings[i]);
3675         test_encodeAltName(encodings[i]);
3676         test_decodeAltName(encodings[i]);
3677         test_encodeOctets(encodings[i]);
3678         test_decodeOctets(encodings[i]);
3679         test_encodeBits(encodings[i]);
3680         test_decodeBits(encodings[i]);
3681         test_encodeBasicConstraints(encodings[i]);
3682         test_decodeBasicConstraints(encodings[i]);
3683         test_encodeRsaPublicKey(encodings[i]);
3684         test_decodeRsaPublicKey(encodings[i]);
3685         test_encodeSequenceOfAny(encodings[i]);
3686         test_decodeSequenceOfAny(encodings[i]);
3687         test_encodeExtensions(encodings[i]);
3688         test_decodeExtensions(encodings[i]);
3689         test_encodePublicKeyInfo(encodings[i]);
3690         test_decodePublicKeyInfo(encodings[i]);
3691         test_encodeCertToBeSigned(encodings[i]);
3692         test_decodeCertToBeSigned(encodings[i]);
3693         test_encodeCert(encodings[i]);
3694         test_decodeCert(encodings[i]);
3695         test_encodeCRLDistPoints(encodings[i]);
3696         test_decodeCRLDistPoints(encodings[i]);
3697         test_encodeCRLIssuingDistPoint(encodings[i]);
3698         test_decodeCRLIssuingDistPoint(encodings[i]);
3699         test_encodeCRLToBeSigned(encodings[i]);
3700         test_decodeCRLToBeSigned(encodings[i]);
3701         test_encodeEnhancedKeyUsage(encodings[i]);
3702         test_decodeEnhancedKeyUsage(encodings[i]);
3703     }
3704     testPortPublicKeyInfo();
3705 }