wined3d: Shaders will never have a NULL function.
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
32
33 struct encodedInt
34 {
35     int val;
36     const BYTE *encoded;
37 };
38
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
46
47 static const struct encodedInt ints[] = {
48  { 1,          bin1 },
49  { 127,        bin2 },
50  { 128,        bin3 },
51  { 256,        bin4 },
52  { -128,       bin5 },
53  { -129,       bin6 },
54  { 0xbaddf00d, bin7 },
55 };
56
57 struct encodedBigInt
58 {
59     const BYTE *val;
60     const BYTE *encoded;
61     const BYTE *decoded;
62 };
63
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
67
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
71
72 static const struct encodedBigInt bigInts[] = {
73  { bin8, bin9, bin10 },
74  { bin11, bin12, bin13 },
75 };
76
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
81
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84  { bin14, bin15, NULL },
85  { bin16, bin17, NULL },
86 };
87
88 static void test_encodeInt(DWORD dwEncoding)
89 {
90     DWORD bufSize = 0;
91     int i;
92     BOOL ret;
93     CRYPT_INTEGER_BLOB blob;
94     BYTE *buf = NULL;
95
96     /* CryptEncodeObjectEx with NULL bufSize crashes..
97     ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98      NULL);
99      */
100     /* check bogus encoding */
101     ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102      &bufSize);
103     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105     if (0)
106     {
107         /* check with NULL integer buffer.  Windows XP incorrectly returns an
108          * NTSTATUS (crashes on win9x).
109          */
110         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111          &bufSize);
112         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
114     }
115     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
116     {
117         /* encode as normal integer */
118         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119          NULL, NULL, &bufSize);
120         ok(ret, "Expected success, got %d\n", GetLastError());
121         ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124         if (buf)
125         {
126             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127              buf[0]);
128             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129              buf[1], ints[i].encoded[1]);
130             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132             LocalFree(buf);
133         }
134         /* encode as multibyte integer */
135         blob.cbData = sizeof(ints[i].val);
136         blob.pbData = (BYTE *)&ints[i].val;
137         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138          0, NULL, NULL, &bufSize);
139         ok(ret, "Expected success, got %d\n", GetLastError());
140         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143         if (buf)
144         {
145             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146              buf[0]);
147             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148              buf[1], ints[i].encoded[1]);
149             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151             LocalFree(buf);
152         }
153     }
154     /* encode a couple bigger ints, just to show it's little-endian and leading
155      * sign bytes are dropped
156      */
157     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158     {
159         blob.cbData = strlen((const char*)bigInts[i].val);
160         blob.pbData = (BYTE *)bigInts[i].val;
161         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162          0, NULL, NULL, &bufSize);
163         ok(ret, "Expected success, got %d\n", GetLastError());
164         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167         if (buf)
168         {
169             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170              buf[0]);
171             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172              buf[1], bigInts[i].encoded[1]);
173             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174              bigInts[i].encoded[1] + 1),
175              "Encoded value didn't match expected\n");
176             LocalFree(buf);
177         }
178     }
179     /* and, encode some uints */
180     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181     {
182         blob.cbData = strlen((const char*)bigUInts[i].val);
183         blob.pbData = (BYTE*)bigUInts[i].val;
184         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185          0, NULL, NULL, &bufSize);
186         ok(ret, "Expected success, got %d\n", GetLastError());
187         ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190         if (buf)
191         {
192             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193              buf[0]);
194             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195              buf[1], bigUInts[i].encoded[1]);
196             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197              bigUInts[i].encoded[1] + 1),
198              "Encoded value didn't match expected\n");
199             LocalFree(buf);
200         }
201     }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211     BYTE *buf = NULL;
212     DWORD bufSize = 0;
213     int i;
214     BOOL ret;
215
216     /* CryptDecodeObjectEx with NULL bufSize crashes..
217     ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219      */
220     /* check bogus encoding */
221     ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225     /* check with NULL integer buffer */
226     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227      &bufSize);
228     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229      GetLastError() == OSS_BAD_ARG /* Win9x */),
230      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231     /* check with a valid, but too large, integer */
232     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
234     ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
235      broken(ret) /* Win9x */,
236      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
237     /* check with a DER-encoded string */
238     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
239      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
240     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
241      GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
242      "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
243      GetLastError());
244     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
245     {
246         /* When the output buffer is NULL, this always succeeds */
247         SetLastError(0xdeadbeef);
248         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250          &bufSize);
251         ok(ret && GetLastError() == NOERROR,
252          "Expected success and NOERROR, got %d\n", GetLastError());
253         ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254          ints[i].encoded, ints[i].encoded[1] + 2,
255          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
256         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
257         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
258         ok(buf != NULL, "Expected allocated buffer\n");
259         if (buf)
260         {
261             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262              ints[i].val, *(int *)buf);
263             LocalFree(buf);
264         }
265     }
266     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
267     {
268         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270          &bufSize);
271         ok(ret && GetLastError() == NOERROR,
272          "Expected success and NOERROR, got %d\n", GetLastError());
273         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
276         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278         ok(buf != NULL, "Expected allocated buffer\n");
279         if (buf)
280         {
281             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
282
283             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285              blob->cbData);
286             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287              "Unexpected value\n");
288             LocalFree(buf);
289         }
290     }
291     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
292     {
293         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295          &bufSize);
296         ok(ret && GetLastError() == NOERROR,
297          "Expected success and NOERROR, got %d\n", GetLastError());
298         ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
301         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303         ok(buf != NULL, "Expected allocated buffer\n");
304         if (buf)
305         {
306             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
307
308             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310              blob->cbData);
311             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312              "Unexpected value\n");
313             LocalFree(buf);
314         }
315     }
316     /* Decode the value 1 with long-form length */
317     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
319     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320     if (buf)
321     {
322         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323         LocalFree(buf);
324     }
325     /* check with extra bytes at the end */
326     ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
328     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329     if (buf)
330     {
331         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332         LocalFree(buf);
333     }
334     /* Try to decode some bogus large items */
335     /* The buffer size is smaller than the encoded length, so this should fail
336      * with CRYPT_E_ASN1_EOD if it's being decoded.
337      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339      * So this test unfortunately isn't useful.
340     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
342     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
344      */
345     /* This will try to decode the buffer and overflow it, check that it's
346      * caught.
347      */
348     if (0)
349     {
350     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351     ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
353     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
355     }
356 }
357
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
360
361 /* These are always encoded unsigned, and aren't constrained to be any
362  * particular value
363  */
364 static const struct encodedInt enums[] = {
365  { 1,    bin18 },
366  { -128, bin19 },
367 };
368
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370  * X509_ENUMERATED.
371  */
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373  szOID_CRL_REASON_CODE };
374
375 static void test_encodeEnumerated(DWORD dwEncoding)
376 {
377     DWORD i, j;
378
379     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
380     {
381         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
382         {
383             BOOL ret;
384             BYTE *buf = NULL;
385             DWORD bufSize = 0;
386
387             ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
389              &bufSize);
390             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391             if (buf)
392             {
393                 ok(buf[0] == 0xa,
394                  "Got unexpected type %d for enumerated (expected 0xa)\n",
395                  buf[0]);
396                 ok(buf[1] == enums[j].encoded[1],
397                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399                  enums[j].encoded[1] + 1),
400                  "Encoded value of 0x%08x didn't match expected\n",
401                  enums[j].val);
402                 LocalFree(buf);
403             }
404         }
405     }
406 }
407
408 static void test_decodeEnumerated(DWORD dwEncoding)
409 {
410     DWORD i, j;
411
412     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
413     {
414         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
415         {
416             BOOL ret;
417             DWORD bufSize = sizeof(int);
418             int val;
419
420             ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422              (BYTE *)&val, &bufSize);
423             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424             ok(bufSize == sizeof(int),
425              "Got unexpected size %d for enumerated\n", bufSize);
426             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427              val, enums[j].val);
428         }
429     }
430 }
431
432 struct encodedFiletime
433 {
434     SYSTEMTIME sysTime;
435     const BYTE *encodedTime;
436 };
437
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439  const struct encodedFiletime *time)
440 {
441     FILETIME ft = { 0 };
442     BYTE *buf = NULL;
443     DWORD bufSize = 0;
444     BOOL ret;
445
446     ret = SystemTimeToFileTime(&time->sysTime, &ft);
447     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448     ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
450     /* years other than 1950-2050 are not allowed for encodings other than
451      * X509_CHOICE_OF_TIME.
452      */
453     if (structType == X509_CHOICE_OF_TIME ||
454      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
455     {
456         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457          GetLastError());
458         ok(buf != NULL, "Expected an allocated buffer\n");
459         if (buf)
460         {
461             ok(buf[0] == time->encodedTime[0],
462              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463              buf[0]);
464             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465              time->encodedTime[1], bufSize);
466             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467              "Got unexpected value for time encoding\n");
468             LocalFree(buf);
469         }
470     }
471     else
472         ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473          broken(GetLastError() == ERROR_SUCCESS),
474          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
475 }
476
477 static const char *printSystemTime(const SYSTEMTIME *st)
478 {
479     static char buf[25];
480
481     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482      st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483     return buf;
484 }
485
486 static const char *printFileTime(const FILETIME *ft)
487 {
488     static char buf[25];
489     SYSTEMTIME st;
490
491     FileTimeToSystemTime(ft, &st);
492     sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493      st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494     return buf;
495 }
496
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
498 {
499     SYSTEMTIME st;
500
501     FileTimeToSystemTime(got, &st);
502     ok((expected->wYear == st.wYear &&
503      expected->wMonth == st.wMonth &&
504      expected->wDay == st.wDay &&
505      expected->wHour == st.wHour &&
506      expected->wMinute == st.wMinute &&
507      expected->wSecond == st.wSecond &&
508      abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509      /* Some Windows systems only seem to be accurate in their time decoding to
510       * within about an hour.
511       */
512      broken(expected->wYear == st.wYear &&
513      expected->wMonth == st.wMonth &&
514      expected->wDay == st.wDay &&
515      abs(expected->wHour - st.wHour) <= 1),
516      "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517      printSystemTime(expected), printFileTime(got));
518 }
519
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521  const struct encodedFiletime *time)
522 {
523     FILETIME ft = { 0 };
524     DWORD size = sizeof(ft);
525     BOOL ret;
526
527     ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528      time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529     /* years other than 1950-2050 are not allowed for encodings other than
530      * X509_CHOICE_OF_TIME.
531      */
532     if (structType == X509_CHOICE_OF_TIME ||
533      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
534     {
535         ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536          "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537          GetLastError());
538         if (ret)
539             compareTime(&time->sysTime, &ft);
540     }
541     else
542         ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543          GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544          "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545          GetLastError());
546 }
547
548 static const BYTE bin20[] = {
549     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
554
555 static const struct encodedFiletime times[] = {
556  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
559 };
560
561 static void test_encodeFiletime(DWORD dwEncoding)
562 {
563     DWORD i;
564
565     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
566     {
567         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
570     }
571 }
572
573 static const BYTE bin23[] = {
574     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598     0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602     0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604     0x18,0x08, '2','1','4','5','0','6','0','6'};
605
606 static void test_decodeFiletime(DWORD dwEncoding)
607 {
608     static const struct encodedFiletime otherTimes[] = {
609      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
610      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
612      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
613      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
614      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
615      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
616      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
617      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
618      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
619      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
620      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
621     };
622     /* An oddball case that succeeds in Windows, but doesn't seem correct
623      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
624      */
625     static const unsigned char *bogusTimes[] = {
626      /* oddly, this succeeds on Windows, with year 2765
627      "\x18" "\x0f" "21r50606161000Z",
628       */
629      bin35,
630      bin36,
631      bin37,
632      bin38,
633     };
634     DWORD i, size;
635     FILETIME ft1 = { 0 }, ft2 = { 0 };
636     BOOL ret;
637
638     /* Check bogus length with non-NULL buffer */
639     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641     size = 1;
642     ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644     ok(!ret && GetLastError() == ERROR_MORE_DATA,
645      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646     /* Normal tests */
647     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
648     {
649         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
652     }
653     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
654     {
655         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
658     }
659     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
660     {
661         size = sizeof(ft1);
662         ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664         ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665                      GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666            broken(ret), /* Win9x and NT4 for bin38 */
667          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668          GetLastError());
669     }
670 }
671
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
674
675 static const BYTE emptySequence[] = { 0x30, 0 };
676 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
677 static const BYTE twoRDNs[] = {
678     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
679     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
680     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
681 static const BYTE encodedTwoRDNs[] = {
682 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
683 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
684 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
685 0x6e,0x67,0x00,
686 };
687
688 static const BYTE us[] = { 0x55, 0x53 };
689 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
690  0x74, 0x61 };
691 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
692  0x6f, 0x6c, 0x69, 0x73 };
693 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
694  0x76, 0x65, 0x72, 0x73 };
695 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
696  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
697 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
698  0x73, 0x74 };
699 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
700  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
701
702 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
703 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
704
705 static CHAR oid_us[]            = "2.5.4.6",
706             oid_minnesota[]     = "2.5.4.8",
707             oid_minneapolis[]   = "2.5.4.7",
708             oid_codeweavers[]   = "2.5.4.10",
709             oid_wine[]          = "2.5.4.11",
710             oid_localhostAttr[] = "2.5.4.3",
711             oid_aric[]          = "1.2.840.113549.1.9.1";
712 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
713                                     { RDNA(minnesota) },
714                                     { RDNA(minneapolis) },
715                                     { RDNA(codeweavers) },
716                                     { RDNA(wine) },
717                                     { RDNA(localhostAttr) },
718                                     { RDNIA5(aric) } };
719 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
720                                            { RDNA(localhostAttr) },
721                                            { RDNA(minnesota) },
722                                            { RDNA(minneapolis) },
723                                            { RDNA(codeweavers) },
724                                            { RDNA(wine) },
725                                            { RDNIA5(aric) } };
726
727 #undef RDNIA5
728 #undef RDNA
729
730 static const BYTE encodedRDNAttrs[] = {
731 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
732 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
733 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
734 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
735 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
736 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
737 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
738 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
739 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
740 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
741 };
742
743 static void test_encodeName(DWORD dwEncoding)
744 {
745     CERT_RDN_ATTR attrs[2];
746     CERT_RDN rdn;
747     CERT_NAME_INFO info;
748     static CHAR oid_common_name[] = szOID_COMMON_NAME,
749                 oid_sur_name[]    = szOID_SUR_NAME;
750     BYTE *buf = NULL;
751     DWORD size = 0;
752     BOOL ret;
753
754     if (0)
755     {
756         /* Test with NULL pvStructInfo (crashes on win9x) */
757         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
758          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
759         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
760          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
761     }
762     /* Test with empty CERT_NAME_INFO */
763     info.cRDN = 0;
764     info.rgRDN = NULL;
765     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
767     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
768     if (buf)
769     {
770         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771          "Got unexpected encoding for empty name\n");
772         LocalFree(buf);
773     }
774     if (0)
775     {
776         /* Test with bogus CERT_RDN (crashes on win9x) */
777         info.cRDN = 1;
778         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
780         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
781          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
782     }
783     /* Test with empty CERT_RDN */
784     rdn.cRDNAttr = 0;
785     rdn.rgRDNAttr = NULL;
786     info.cRDN = 1;
787     info.rgRDN = &rdn;
788     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
789      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
790     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
791     if (buf)
792     {
793         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794          "Got unexpected encoding for empty RDN array\n");
795         LocalFree(buf);
796     }
797     if (0)
798     {
799         /* Test with bogus attr array (crashes on win9x) */
800         rdn.cRDNAttr = 1;
801         rdn.rgRDNAttr = NULL;
802         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
803          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
804         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
805          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
806     }
807     /* oddly, a bogus OID is accepted by Windows XP; not testing.
808     attrs[0].pszObjId = "bogus";
809     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
810     attrs[0].Value.cbData = sizeof(commonName);
811     attrs[0].Value.pbData = (BYTE *)commonName;
812     rdn.cRDNAttr = 1;
813     rdn.rgRDNAttr = attrs;
814     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
815      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
816     ok(!ret, "Expected failure, got success\n");
817      */
818     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
819      * the encoded attributes to be swapped.
820      */
821     attrs[0].pszObjId = oid_common_name;
822     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
823     attrs[0].Value.cbData = sizeof(commonName);
824     attrs[0].Value.pbData = (BYTE *)commonName;
825     attrs[1].pszObjId = oid_sur_name;
826     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
827     attrs[1].Value.cbData = sizeof(surName);
828     attrs[1].Value.pbData = (BYTE *)surName;
829     rdn.cRDNAttr = 2;
830     rdn.rgRDNAttr = attrs;
831     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
832      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
833     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
834     if (buf)
835     {
836         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837          "Got unexpected encoding for two RDN array\n");
838         LocalFree(buf);
839     }
840     /* A name can be "encoded" with previously encoded RDN attrs. */
841     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
842     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
843     attrs[0].Value.cbData = sizeof(twoRDNs);
844     rdn.cRDNAttr = 1;
845     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
846      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
847     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
848     if (buf)
849     {
850         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851         ok(!memcmp(buf, encodedTwoRDNs, size),
852          "Unexpected value for re-endoded two RDN array\n");
853         LocalFree(buf);
854     }
855     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
856     rdn.cRDNAttr = 1;
857     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
858     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
859      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
860     ok(!ret && GetLastError() == E_INVALIDARG,
861      "Expected E_INVALIDARG, got %08x\n", GetLastError());
862     /* Test a more complex name */
863     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
864     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
865     info.cRDN = 1;
866     info.rgRDN = &rdn;
867     buf = NULL;
868     size = 0;
869     ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
870      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
871     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
872     if (ret)
873     {
874         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
875         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
876         LocalFree(buf);
877     }
878 }
879
880 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
881 static WCHAR surNameW[] = { 'L','a','n','g',0 };
882
883 static const BYTE twoRDNsNoNull[] = {
884  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
885  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
886  0x20,0x4c,0x61,0x6e,0x67 };
887 static const BYTE anyType[] = {
888  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
889  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
890  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
891  0x61,0x4c,0x67,0x6e };
892
893 static void test_encodeUnicodeName(DWORD dwEncoding)
894 {
895     CERT_RDN_ATTR attrs[2];
896     CERT_RDN rdn;
897     CERT_NAME_INFO info;
898     static CHAR oid_common_name[] = szOID_COMMON_NAME,
899                 oid_sur_name[]    = szOID_SUR_NAME;
900     BYTE *buf = NULL;
901     DWORD size = 0;
902     BOOL ret;
903
904     if (0)
905     {
906         /* Test with NULL pvStructInfo (crashes on win9x) */
907         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
908          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
909         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
910          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
911     }
912     /* Test with empty CERT_NAME_INFO */
913     info.cRDN = 0;
914     info.rgRDN = NULL;
915     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
916      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
917     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
918     if (buf)
919     {
920         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921          "Got unexpected encoding for empty name\n");
922         LocalFree(buf);
923     }
924     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925      * encoding (the NULL).
926      */
927     attrs[0].pszObjId = oid_common_name;
928     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
929     attrs[0].Value.cbData = sizeof(commonNameW);
930     attrs[0].Value.pbData = (BYTE *)commonNameW;
931     rdn.cRDNAttr = 1;
932     rdn.rgRDNAttr = attrs;
933     info.cRDN = 1;
934     info.rgRDN = &rdn;
935     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
937     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
938      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
939     ok(size == 9, "Unexpected error index %08x\n", size);
940     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
941      * forces the order of the encoded attributes to be swapped.
942      */
943     attrs[0].pszObjId = oid_common_name;
944     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
945     attrs[0].Value.cbData = 0;
946     attrs[0].Value.pbData = (BYTE *)commonNameW;
947     attrs[1].pszObjId = oid_sur_name;
948     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
949     attrs[1].Value.cbData = 0;
950     attrs[1].Value.pbData = (BYTE *)surNameW;
951     rdn.cRDNAttr = 2;
952     rdn.rgRDNAttr = attrs;
953     info.cRDN = 1;
954     info.rgRDN = &rdn;
955     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
956      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
957     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
958     if (buf)
959     {
960         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961          "Got unexpected encoding for two RDN array\n");
962         LocalFree(buf);
963     }
964     /* A name can be "encoded" with previously encoded RDN attrs. */
965     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
966     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
967     attrs[0].Value.cbData = sizeof(twoRDNs);
968     rdn.cRDNAttr = 1;
969     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
970      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
971     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
972     if (buf)
973     {
974         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975         ok(!memcmp(buf, encodedTwoRDNs, size),
976          "Unexpected value for re-endoded two RDN array\n");
977         LocalFree(buf);
978     }
979     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980     rdn.cRDNAttr = 1;
981     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
984     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985     if (buf)
986     {
987         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989         LocalFree(buf);
990     }
991 }
992
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994  const CERT_NAME_VALUE *got)
995 {
996     ok(got->dwValueType == expected->dwValueType,
997      "Expected string type %d, got %d\n", expected->dwValueType,
998      got->dwValueType);
999     ok(got->Value.cbData == expected->Value.cbData,
1000      "String type %d: unexpected data size, got %d, expected %d\n",
1001      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1002     if (got->Value.cbData && got->Value.pbData)
1003         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1004          min(got->Value.cbData, expected->Value.cbData)),
1005          "String type %d: unexpected value\n", expected->dwValueType);
1006 }
1007
1008 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1009  const CERT_RDN_ATTR *got)
1010 {
1011     if (expected->pszObjId && strlen(expected->pszObjId))
1012     {
1013         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1014          expected->pszObjId);
1015         if (got->pszObjId)
1016         {
1017             ok(!strcmp(got->pszObjId, expected->pszObjId),
1018              "Got unexpected OID %s, expected %s\n", got->pszObjId,
1019              expected->pszObjId);
1020         }
1021     }
1022     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1023      (const CERT_NAME_VALUE *)&got->dwValueType);
1024 }
1025
1026 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1027 {
1028     ok(got->cRDNAttr == expected->cRDNAttr,
1029      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1030     if (got->cRDNAttr)
1031     {
1032         DWORD i;
1033
1034         for (i = 0; i < got->cRDNAttr; i++)
1035             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1036     }
1037 }
1038
1039 static void compareNames(const CERT_NAME_INFO *expected,
1040  const CERT_NAME_INFO *got)
1041 {
1042     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1043      expected->cRDN, got->cRDN);
1044     if (got->cRDN)
1045     {
1046         DWORD i;
1047
1048         for (i = 0; i < got->cRDN; i++)
1049             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1050     }
1051 }
1052
1053 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1054 static const BYTE twoRDNsExtraBytes[] = {
1055     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1056     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1057     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1058
1059 static void test_decodeName(DWORD dwEncoding)
1060 {
1061     BYTE *buf = NULL;
1062     DWORD bufSize = 0;
1063     BOOL ret;
1064     CERT_RDN rdn;
1065     CERT_NAME_INFO info = { 1, &rdn };
1066
1067     /* test empty name */
1068     bufSize = 0;
1069     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1070      emptySequence[1] + 2,
1071      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1072      (BYTE *)&buf, &bufSize);
1073     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1074     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1075      * decoder works the same way, so only test the count.
1076      */
1077     if (buf)
1078     {
1079         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1080         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1081          "Expected 0 RDNs in empty info, got %d\n",
1082          ((CERT_NAME_INFO *)buf)->cRDN);
1083         LocalFree(buf);
1084     }
1085     /* test empty name with indefinite-length encoding */
1086     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1087      sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1088      (BYTE *)&buf, &bufSize);
1089     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1090     if (ret)
1091     {
1092         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1093         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1094          "Expected 0 RDNs in empty info, got %d\n",
1095          ((CERT_NAME_INFO *)buf)->cRDN);
1096         LocalFree(buf);
1097     }
1098     /* test empty RDN */
1099     bufSize = 0;
1100     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1101      emptyRDNs[1] + 2,
1102      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1103      (BYTE *)&buf, &bufSize);
1104     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1105     if (buf)
1106     {
1107         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1108
1109         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1110          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1111          "Got unexpected value for empty RDN\n");
1112         LocalFree(buf);
1113     }
1114     /* test two RDN attrs */
1115     bufSize = 0;
1116     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1117      twoRDNs[1] + 2,
1118      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1119      (BYTE *)&buf, &bufSize);
1120     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1121     if (buf)
1122     {
1123         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1124                     oid_common_name[] = szOID_COMMON_NAME;
1125
1126         CERT_RDN_ATTR attrs[] = {
1127          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1128           (BYTE *)surName } },
1129          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1130           (BYTE *)commonName } },
1131         };
1132
1133         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1134         rdn.rgRDNAttr = attrs;
1135         compareNames(&info, (CERT_NAME_INFO *)buf);
1136         LocalFree(buf);
1137     }
1138     /* test that two RDN attrs with extra bytes succeeds */
1139     bufSize = 0;
1140     ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1141      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1142     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1143     /* And, a slightly more complicated name */
1144     buf = NULL;
1145     bufSize = 0;
1146     ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1147      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1148     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1149     if (ret)
1150     {
1151         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1152         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1153         compareNames(&info, (CERT_NAME_INFO *)buf);
1154         LocalFree(buf);
1155     }
1156 }
1157
1158 static void test_decodeUnicodeName(DWORD dwEncoding)
1159 {
1160     BYTE *buf = NULL;
1161     DWORD bufSize = 0;
1162     BOOL ret;
1163     CERT_RDN rdn;
1164     CERT_NAME_INFO info = { 1, &rdn };
1165
1166     /* test empty name */
1167     bufSize = 0;
1168     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1169      emptySequence[1] + 2,
1170      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1171      (BYTE *)&buf, &bufSize);
1172     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1173     if (buf)
1174     {
1175         ok(bufSize == sizeof(CERT_NAME_INFO),
1176          "Got wrong bufSize %d\n", bufSize);
1177         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1178          "Expected 0 RDNs in empty info, got %d\n",
1179          ((CERT_NAME_INFO *)buf)->cRDN);
1180         LocalFree(buf);
1181     }
1182     /* test empty RDN */
1183     bufSize = 0;
1184     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1185      emptyRDNs[1] + 2,
1186      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1187      (BYTE *)&buf, &bufSize);
1188     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1189     if (buf)
1190     {
1191         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1192
1193         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1194          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1195          "Got unexpected value for empty RDN\n");
1196         LocalFree(buf);
1197     }
1198     /* test two RDN attrs */
1199     bufSize = 0;
1200     ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1201      sizeof(twoRDNsNoNull),
1202      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1203      (BYTE *)&buf, &bufSize);
1204     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1205     if (buf)
1206     {
1207         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1208                     oid_common_name[] = szOID_COMMON_NAME;
1209
1210         CERT_RDN_ATTR attrs[] = {
1211          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1212          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1213          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1214          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1215         };
1216
1217         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1218         rdn.rgRDNAttr = attrs;
1219         compareNames(&info, (CERT_NAME_INFO *)buf);
1220         LocalFree(buf);
1221     }
1222 }
1223
1224 struct EncodedNameValue
1225 {
1226     CERT_NAME_VALUE value;
1227     const BYTE *encoded;
1228     DWORD encodedSize;
1229 };
1230
1231 static const char bogusIA5[] = "\x80";
1232 static const char bogusPrintable[] = "~";
1233 static const char bogusNumeric[] = "A";
1234 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1235 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1236 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1237 static BYTE octetCommonNameValue[] = {
1238  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1239 static BYTE numericCommonNameValue[] = {
1240  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1241 static BYTE printableCommonNameValue[] = {
1242  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1243 static BYTE t61CommonNameValue[] = {
1244  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1245 static BYTE videotexCommonNameValue[] = {
1246  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1247 static BYTE ia5CommonNameValue[] = {
1248  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1249 static BYTE graphicCommonNameValue[] = {
1250  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1251 static BYTE visibleCommonNameValue[] = {
1252  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1253 static BYTE generalCommonNameValue[] = {
1254  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1255 static BYTE bmpCommonNameValue[] = {
1256  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1257  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1258 static BYTE utf8CommonNameValue[] = {
1259  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1260
1261 static struct EncodedNameValue nameValues[] = {
1262  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1263      octetCommonNameValue, sizeof(octetCommonNameValue) },
1264  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1265      numericCommonNameValue, sizeof(numericCommonNameValue) },
1266  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1267      printableCommonNameValue, sizeof(printableCommonNameValue) },
1268  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1269      t61CommonNameValue, sizeof(t61CommonNameValue) },
1270  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1271      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1272  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1273      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1274  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1275      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1276  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1277      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1278  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1279      generalCommonNameValue, sizeof(generalCommonNameValue) },
1280  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1281      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1282  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1283      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1284  /* The following tests succeed under Windows, but really should fail,
1285   * they contain characters that are illegal for the encoding.  I'm
1286   * including them to justify my lazy encoding.
1287   */
1288  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1289      sizeof(bin42) },
1290  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1291      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1292  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1293      bin44, sizeof(bin44) },
1294 };
1295
1296 static void test_encodeNameValue(DWORD dwEncoding)
1297 {
1298     BYTE *buf = NULL;
1299     DWORD size = 0, i;
1300     BOOL ret;
1301     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1302
1303     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1304     value.Value.pbData = printableCommonNameValue;
1305     value.Value.cbData = sizeof(printableCommonNameValue);
1306     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1307      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1308     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1309     if (buf)
1310     {
1311         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1312          size);
1313         ok(!memcmp(buf, printableCommonNameValue, size),
1314          "Unexpected encoding\n");
1315         LocalFree(buf);
1316     }
1317     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1318     {
1319         ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1320          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1321          &size);
1322         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1323          "Type %d: CryptEncodeObjectEx failed: %08x\n",
1324          nameValues[i].value.dwValueType, GetLastError());
1325         if (ret)
1326         {
1327             ok(size == nameValues[i].encodedSize,
1328              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1329             ok(!memcmp(buf, nameValues[i].encoded, size),
1330              "Got unexpected encoding\n");
1331             LocalFree(buf);
1332         }
1333     }
1334 }
1335
1336 static void test_decodeNameValue(DWORD dwEncoding)
1337 {
1338     int i;
1339     BYTE *buf = NULL;
1340     DWORD bufSize = 0;
1341     BOOL ret;
1342
1343     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1344     {
1345         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1346          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1347          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1348          (BYTE *)&buf, &bufSize);
1349         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1350          nameValues[i].value.dwValueType, GetLastError());
1351         if (ret)
1352         {
1353             compareNameValues(&nameValues[i].value,
1354              (const CERT_NAME_VALUE *)buf);
1355             LocalFree(buf);
1356         }
1357     }
1358 }
1359
1360 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1361 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1362 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1363  'h','q','.','o','r','g',0 };
1364 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1365  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1366  0x6f, 0x72, 0x67 };
1367 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1368  0x575b, 0 };
1369 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1370 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1371  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1372 static const BYTE localhost[] = { 127, 0, 0, 1 };
1373 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1374  0x01 };
1375 static const unsigned char encodedCommonName[] = {
1376     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1377 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1378 static const BYTE encodedDirectoryName[] = {
1379 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1380 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1381
1382 static void test_encodeAltName(DWORD dwEncoding)
1383 {
1384     CERT_ALT_NAME_INFO info = { 0 };
1385     CERT_ALT_NAME_ENTRY entry = { 0 };
1386     BYTE *buf = NULL;
1387     DWORD size = 0;
1388     BOOL ret;
1389     char oid[] = "1.2.3";
1390
1391     /* Test with empty info */
1392     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1393      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1394     if (buf)
1395     {
1396         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1397         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1398         LocalFree(buf);
1399     }
1400     /* Test with an empty entry */
1401     info.cAltEntry = 1;
1402     info.rgAltEntry = &entry;
1403     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1404      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1405     ok(!ret && GetLastError() == E_INVALIDARG,
1406      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1407     /* Test with an empty pointer */
1408     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1409     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1410      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1411     if (buf)
1412     {
1413         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1414         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1415         LocalFree(buf);
1416     }
1417     /* Test with a real URL */
1418     U(entry).pwszURL = (LPWSTR)url;
1419     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1420      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1421     if (buf)
1422     {
1423         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1424         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1425         LocalFree(buf);
1426     }
1427     /* Now with the URL containing an invalid IA5 char */
1428     U(entry).pwszURL = (LPWSTR)nihongoURL;
1429     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1430      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1431     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1432      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1433     /* The first invalid character is at index 7 */
1434     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1435      "Expected invalid char at index 7, got %d\n",
1436      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1437     /* Now with the URL missing a scheme */
1438     U(entry).pwszURL = (LPWSTR)dnsName;
1439     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1440      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1441     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1442     if (buf)
1443     {
1444         /* This succeeds, but it shouldn't, so don't worry about conforming */
1445         LocalFree(buf);
1446     }
1447     /* Now with a DNS name */
1448     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1449     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1450      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1451     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1452     if (buf)
1453     {
1454         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1455         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1456         LocalFree(buf);
1457     }
1458     /* Test with an IP address */
1459     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1460     U(entry).IPAddress.cbData = sizeof(localhost);
1461     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1462     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1463      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1464     if (buf)
1465     {
1466         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1467         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1468         LocalFree(buf);
1469     }
1470     /* Test with OID */
1471     entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1472     U(entry).pszRegisteredID = oid;
1473     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1474      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1475     if (buf)
1476     {
1477         ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1478         ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1479         LocalFree(buf);
1480     }
1481     /* Test with directory name */
1482     entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1483     U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1484     U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1485     ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1486      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1487     if (buf)
1488     {
1489         ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1490         ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1491         LocalFree(buf);
1492     }
1493 }
1494
1495 static void test_decodeAltName(DWORD dwEncoding)
1496 {
1497     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1498      0x00, 0x00, 0x01 };
1499     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1500      0x01 };
1501     BOOL ret;
1502     BYTE *buf = NULL;
1503     DWORD bufSize = 0;
1504     CERT_ALT_NAME_INFO *info;
1505
1506     /* Test some bogus ones first */
1507     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1508      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1509      NULL, (BYTE *)&buf, &bufSize);
1510     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1511      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1512      "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1513      GetLastError());
1514     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1515      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1516      &bufSize);
1517     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1518      GetLastError() == OSS_DATA_ERROR /* Win9x */),
1519      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1520      GetLastError());
1521     /* Now expected cases */
1522     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1523      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1524      &bufSize);
1525     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1526     if (buf)
1527     {
1528         info = (CERT_ALT_NAME_INFO *)buf;
1529
1530         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1531          info->cAltEntry);
1532         LocalFree(buf);
1533     }
1534     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1535      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1536      &bufSize);
1537     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1538     if (buf)
1539     {
1540         info = (CERT_ALT_NAME_INFO *)buf;
1541
1542         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1543          info->cAltEntry);
1544         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1545          "Expected CERT_ALT_NAME_URL, got %d\n",
1546          info->rgAltEntry[0].dwAltNameChoice);
1547         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1548          "Expected empty URL\n");
1549         LocalFree(buf);
1550     }
1551     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1552      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1553     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1554     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1555      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1556      &bufSize);
1557     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1558     if (buf)
1559     {
1560         info = (CERT_ALT_NAME_INFO *)buf;
1561
1562         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1563          info->cAltEntry);
1564         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1565          "Expected CERT_ALT_NAME_URL, got %d\n",
1566          info->rgAltEntry[0].dwAltNameChoice);
1567         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1568         LocalFree(buf);
1569     }
1570     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1571      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1572      &bufSize);
1573     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1574     if (buf)
1575     {
1576         info = (CERT_ALT_NAME_INFO *)buf;
1577
1578         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1579          info->cAltEntry);
1580         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1581          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1582          info->rgAltEntry[0].dwAltNameChoice);
1583         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1584          "Unexpected DNS name\n");
1585         LocalFree(buf);
1586     }
1587     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1588      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1589      &bufSize);
1590     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1591     if (buf)
1592     {
1593         info = (CERT_ALT_NAME_INFO *)buf;
1594
1595         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1596          info->cAltEntry);
1597         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1598          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1599          info->rgAltEntry[0].dwAltNameChoice);
1600         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1601          "Unexpected IP address length %d\n",
1602           U(info->rgAltEntry[0]).IPAddress.cbData);
1603         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1604          sizeof(localhost)), "Unexpected IP address value\n");
1605         LocalFree(buf);
1606     }
1607     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1608      sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1609      &bufSize);
1610     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1611     if (buf)
1612     {
1613         info = (CERT_ALT_NAME_INFO *)buf;
1614
1615         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1616          info->cAltEntry);
1617         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1618          "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1619          info->rgAltEntry[0].dwAltNameChoice);
1620         ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1621            "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1622         LocalFree(buf);
1623     }
1624     ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1625      encodedDirectoryName, sizeof(encodedDirectoryName),
1626      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1627     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1628     if (buf)
1629     {
1630         info = (CERT_ALT_NAME_INFO *)buf;
1631
1632         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1633          info->cAltEntry);
1634         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1635          "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1636          info->rgAltEntry[0].dwAltNameChoice);
1637         ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1638          sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1639           U(info->rgAltEntry[0]).DirectoryName.cbData);
1640         ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1641          encodedCommonName, sizeof(encodedCommonName)),
1642          "Unexpected directory name value\n");
1643         LocalFree(buf);
1644     }
1645 }
1646
1647 struct UnicodeExpectedError
1648 {
1649     DWORD   valueType;
1650     LPCWSTR str;
1651     DWORD   errorIndex;
1652     DWORD   error;
1653 };
1654
1655 static const WCHAR oneW[] = { '1',0 };
1656 static const WCHAR aW[] = { 'a',0 };
1657 static const WCHAR quoteW[] = { '"', 0 };
1658
1659 static struct UnicodeExpectedError unicodeErrors[] = {
1660  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1661  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1662  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1663  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1664  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1665  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1666 };
1667
1668 struct UnicodeExpectedResult
1669 {
1670     DWORD           valueType;
1671     LPCWSTR         str;
1672     CRYPT_DATA_BLOB encoded;
1673 };
1674
1675 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1676 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1677 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1678 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1679 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1680 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1681 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1682 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1683 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1684 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1685 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1686 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1687  0x5b };
1688 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1689  0x6f,0x5b };
1690 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1691  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1692 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1693  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1694
1695 static struct UnicodeExpectedResult unicodeResults[] = {
1696  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1697  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1698  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1699  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1700  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1701  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1702  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1703  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1704  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1705  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1706  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1707  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1708  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1709 };
1710
1711 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1712  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1713  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1714 };
1715
1716 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1717 {
1718     BYTE *buf = NULL;
1719     DWORD size = 0, i;
1720     BOOL ret;
1721     CERT_NAME_VALUE value;
1722
1723     if (0)
1724     {
1725         /* Crashes on win9x */
1726         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1727          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1728         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1729          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1730     }
1731     /* Have to have a string of some sort */
1732     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1733     value.Value.pbData = NULL;
1734     value.Value.cbData = 0;
1735     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1736      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1737     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1738      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1739     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1740     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1741      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1742     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1743      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1744     value.dwValueType = CERT_RDN_ANY_TYPE;
1745     value.Value.pbData = (LPBYTE)oneW;
1746     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1747      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1748     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1749      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1750     value.Value.cbData = sizeof(oneW);
1751     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1752      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1753     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1754      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1755     /* An encoded string with specified length isn't good enough either */
1756     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1757     value.Value.pbData = oneUniversal;
1758     value.Value.cbData = sizeof(oneUniversal);
1759     ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1760      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1761     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1762      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1763     /* More failure checking */
1764     value.Value.cbData = 0;
1765     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1766     {
1767         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1768         value.dwValueType = unicodeErrors[i].valueType;
1769         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1770          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1771         ok(!ret && GetLastError() == unicodeErrors[i].error,
1772          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1773          unicodeErrors[i].error, GetLastError());
1774         ok(size == unicodeErrors[i].errorIndex,
1775          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1776          size);
1777     }
1778     /* cbData can be zero if the string is NULL-terminated */
1779     value.Value.cbData = 0;
1780     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1781     {
1782         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1783         value.dwValueType = unicodeResults[i].valueType;
1784         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1785          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1786         ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1787          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1788         if (buf)
1789         {
1790             ok(size == unicodeResults[i].encoded.cbData,
1791              "Value type %d: expected size %d, got %d\n",
1792              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1793             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1794              "Value type %d: unexpected value\n", value.dwValueType);
1795             LocalFree(buf);
1796         }
1797     }
1798     /* These "encode," but they do so by truncating each unicode character
1799      * rather than properly encoding it.  Kept separate from the proper results,
1800      * because the encoded forms won't decode to their original strings.
1801      */
1802     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1803     {
1804         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1805         value.dwValueType = unicodeWeirdness[i].valueType;
1806         ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1807          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1808         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1809         if (buf)
1810         {
1811             ok(size == unicodeWeirdness[i].encoded.cbData,
1812              "Value type %d: expected size %d, got %d\n",
1813              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1814             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1815              "Value type %d: unexpected value\n", value.dwValueType);
1816             LocalFree(buf);
1817         }
1818     }
1819 }
1820
1821 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1822 {
1823     if (n <= 0) return 0;
1824     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1825     return *str1 - *str2;
1826 }
1827
1828 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1829 {
1830     DWORD i;
1831
1832     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1833     {
1834         BYTE *buf = NULL;
1835         BOOL ret;
1836         DWORD size = 0;
1837
1838         ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1839          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1840          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1841         ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1842          "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1843         if (ret && buf)
1844         {
1845             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1846
1847             ok(value->dwValueType == unicodeResults[i].valueType,
1848              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1849              value->dwValueType);
1850             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1851              value->Value.cbData / sizeof(WCHAR)),
1852              "Unexpected decoded value for index %d (value type %d)\n", i,
1853              unicodeResults[i].valueType);
1854             LocalFree(buf);
1855         }
1856     }
1857 }
1858
1859 struct encodedOctets
1860 {
1861     const BYTE *val;
1862     const BYTE *encoded;
1863 };
1864
1865 static const unsigned char bin46[] = { 'h','i',0 };
1866 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1867 static const unsigned char bin48[] = {
1868      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1869 static const unsigned char bin49[] = {
1870      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1871 static const unsigned char bin50[] = { 0 };
1872 static const unsigned char bin51[] = { 0x04,0x00,0 };
1873
1874 static const struct encodedOctets octets[] = {
1875     { bin46, bin47 },
1876     { bin48, bin49 },
1877     { bin50, bin51 },
1878 };
1879
1880 static void test_encodeOctets(DWORD dwEncoding)
1881 {
1882     CRYPT_DATA_BLOB blob;
1883     DWORD i;
1884
1885     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1886     {
1887         BYTE *buf = NULL;
1888         BOOL ret;
1889         DWORD bufSize = 0;
1890
1891         blob.cbData = strlen((const char*)octets[i].val);
1892         blob.pbData = (BYTE*)octets[i].val;
1893         ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1894          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1895         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1896         if (buf)
1897         {
1898             ok(buf[0] == 4,
1899              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1900             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1901              buf[1], octets[i].encoded[1]);
1902             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1903              octets[i].encoded[1] + 1), "Got unexpected value\n");
1904             LocalFree(buf);
1905         }
1906     }
1907 }
1908
1909 static void test_decodeOctets(DWORD dwEncoding)
1910 {
1911     DWORD i;
1912
1913     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1914     {
1915         BYTE *buf = NULL;
1916         BOOL ret;
1917         DWORD bufSize = 0;
1918
1919         ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1920          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1921          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1922         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1923         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1924          "Expected size >= %d, got %d\n",
1925            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1926         ok(buf != NULL, "Expected allocated buffer\n");
1927         if (buf)
1928         {
1929             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1930
1931             if (blob->cbData)
1932                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1933                  "Unexpected value\n");
1934             LocalFree(buf);
1935         }
1936     }
1937 }
1938
1939 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1940
1941 struct encodedBits
1942 {
1943     DWORD cUnusedBits;
1944     const BYTE *encoded;
1945     DWORD cbDecoded;
1946     const BYTE *decoded;
1947 };
1948
1949 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1950 static const unsigned char bin53[] = { 0xff,0xff };
1951 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1952 static const unsigned char bin55[] = { 0xff,0xfe };
1953 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1954 static const unsigned char bin57[] = { 0xfe };
1955 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1956
1957 static const struct encodedBits bits[] = {
1958     /* normal test cases */
1959     { 0, bin52, 2, bin53 },
1960     { 1, bin54, 2, bin55 },
1961     /* strange test case, showing cUnusedBits >= 8 is allowed */
1962     { 9, bin56, 1, bin57 },
1963     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1964     { 17, bin58, 0, NULL },
1965 };
1966
1967 static void test_encodeBits(DWORD dwEncoding)
1968 {
1969     DWORD i;
1970
1971     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1972     {
1973         CRYPT_BIT_BLOB blob;
1974         BOOL ret;
1975         BYTE *buf = NULL;
1976         DWORD bufSize = 0;
1977
1978         blob.cbData = sizeof(bytesToEncode);
1979         blob.pbData = (BYTE *)bytesToEncode;
1980         blob.cUnusedBits = bits[i].cUnusedBits;
1981         ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1982          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1983         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1984         if (buf)
1985         {
1986             ok(bufSize == bits[i].encoded[1] + 2,
1987              "Got unexpected size %d, expected %d\n", bufSize,
1988              bits[i].encoded[1] + 2);
1989             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1990              "Unexpected value\n");
1991             LocalFree(buf);
1992         }
1993     }
1994 }
1995
1996 static void test_decodeBits(DWORD dwEncoding)
1997 {
1998     static const BYTE ber[] = "\x03\x02\x01\xff";
1999     static const BYTE berDecoded = 0xfe;
2000     DWORD i;
2001     BOOL ret;
2002     BYTE *buf = NULL;
2003     DWORD bufSize = 0;
2004
2005     /* normal cases */
2006     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2007     {
2008         ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2009          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2010          &bufSize);
2011         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2012         if (buf)
2013         {
2014             CRYPT_BIT_BLOB *blob;
2015
2016             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2017                "Got unexpected size %d\n", bufSize);
2018             blob = (CRYPT_BIT_BLOB *)buf;
2019             ok(blob->cbData == bits[i].cbDecoded,
2020              "Got unexpected length %d, expected %d\n", blob->cbData,
2021              bits[i].cbDecoded);
2022             if (blob->cbData && bits[i].cbDecoded)
2023                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2024                  "Unexpected value\n");
2025             LocalFree(buf);
2026         }
2027     }
2028     /* special case: check that something that's valid in BER but not in DER
2029      * decodes successfully
2030      */
2031     ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2032      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2033     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2034     if (buf)
2035     {
2036         CRYPT_BIT_BLOB *blob;
2037
2038         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2039            "Got unexpected size %d\n", bufSize);
2040         blob = (CRYPT_BIT_BLOB *)buf;
2041         ok(blob->cbData == sizeof(berDecoded),
2042            "Got unexpected length %d\n", blob->cbData);
2043         if (blob->cbData)
2044             ok(*blob->pbData == berDecoded, "Unexpected value\n");
2045         LocalFree(buf);
2046     }
2047 }
2048
2049 struct Constraints2
2050 {
2051     CERT_BASIC_CONSTRAINTS2_INFO info;
2052     const BYTE *encoded;
2053 };
2054
2055 static const unsigned char bin59[] = { 0x30,0x00 };
2056 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2057 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2058 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2059 static const struct Constraints2 constraints2[] = {
2060  /* empty constraints */
2061  { { FALSE, FALSE, 0}, bin59 },
2062  /* can be a CA */
2063  { { TRUE,  FALSE, 0}, bin60 },
2064  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2065   * but that's not the case
2066   */
2067  { { FALSE, TRUE,  0}, bin61 },
2068  /* can be a CA and has path length constraints set */
2069  { { TRUE,  TRUE,  1}, bin62 },
2070 };
2071
2072 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2073 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2074  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2075  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2076  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2077 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2078  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2079  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2080  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2081  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2082
2083 static void test_encodeBasicConstraints(DWORD dwEncoding)
2084 {
2085     DWORD i, bufSize = 0;
2086     CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2087     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2088      (LPBYTE)encodedDomainName };
2089     BOOL ret;
2090     BYTE *buf = NULL;
2091
2092     /* First test with the simpler info2 */
2093     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2094     {
2095         ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2096          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2097          &bufSize);
2098         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2099         if (buf)
2100         {
2101             ok(bufSize == constraints2[i].encoded[1] + 2,
2102              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2103              bufSize);
2104             ok(!memcmp(buf, constraints2[i].encoded,
2105              constraints2[i].encoded[1] + 2), "Unexpected value\n");
2106             LocalFree(buf);
2107         }
2108     }
2109     /* Now test with more complex basic constraints */
2110     info.SubjectType.cbData = 0;
2111     info.fPathLenConstraint = FALSE;
2112     info.cSubtreesConstraint = 0;
2113     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2114      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2115     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2116      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2117     if (buf)
2118     {
2119         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2120         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2121          "Unexpected value\n");
2122         LocalFree(buf);
2123     }
2124     /* None of the certs I examined had any subtree constraint, but I test one
2125      * anyway just in case.
2126      */
2127     info.cSubtreesConstraint = 1;
2128     info.rgSubtreesConstraint = &nameBlob;
2129     ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2130      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2131     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2132      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2133     if (buf)
2134     {
2135         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2136         ok(!memcmp(buf, constraintWithDomainName,
2137          sizeof(constraintWithDomainName)), "Unexpected value\n");
2138         LocalFree(buf);
2139     }
2140     /* FIXME: test encoding with subject type. */
2141 }
2142
2143 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2144
2145 static void test_decodeBasicConstraints(DWORD dwEncoding)
2146 {
2147     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2148      0xff };
2149     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2150     DWORD i;
2151     BOOL ret;
2152     BYTE *buf = NULL;
2153     DWORD bufSize = 0;
2154
2155     /* First test with simpler info2 */
2156     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2157     {
2158         ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2159          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2160          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2161         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2162          GetLastError());
2163         if (buf)
2164         {
2165             CERT_BASIC_CONSTRAINTS2_INFO *info =
2166              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2167
2168             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2169              "Unexpected value for item %d\n", i);
2170             LocalFree(buf);
2171         }
2172     }
2173     /* Check with the order of encoded elements inverted */
2174     buf = (PBYTE)1;
2175     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2176      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2177      &bufSize);
2178     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2179      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2180      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2181      GetLastError());
2182     ok(!buf, "Expected buf to be set to NULL\n");
2183     /* Check with a non-DER bool */
2184     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2185      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2186      (BYTE *)&buf, &bufSize);
2187     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2188     if (buf)
2189     {
2190         CERT_BASIC_CONSTRAINTS2_INFO *info =
2191          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2192
2193         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2194         LocalFree(buf);
2195     }
2196     /* Check with a non-basic constraints value */
2197     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2198      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2199      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2200     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2201      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2202      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2203      GetLastError());
2204     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2205     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2206      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2207      (BYTE *)&buf, &bufSize);
2208     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2209     if (buf)
2210     {
2211         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2212
2213         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2214         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2215         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2216         LocalFree(buf);
2217     }
2218     ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2219      constraintWithDomainName, sizeof(constraintWithDomainName),
2220      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2221     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2222     if (buf)
2223     {
2224         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2225
2226         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2227         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2228         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2229         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2230         {
2231             ok(info->rgSubtreesConstraint[0].cbData ==
2232              sizeof(encodedDomainName), "Wrong size %d\n",
2233              info->rgSubtreesConstraint[0].cbData);
2234             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2235              sizeof(encodedDomainName)), "Unexpected value\n");
2236         }
2237         LocalFree(buf);
2238     }
2239 }
2240
2241 /* These are terrible public keys of course, I'm just testing encoding */
2242 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2243 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2244 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2245 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2246 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2247 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2248 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2249 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2250
2251 struct EncodedRSAPubKey
2252 {
2253     const BYTE *modulus;
2254     size_t modulusLen;
2255     const BYTE *encoded;
2256     size_t decodedModulusLen;
2257 };
2258
2259 struct EncodedRSAPubKey rsaPubKeys[] = {
2260     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2261     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2262     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2263     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2264 };
2265
2266 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2267 {
2268     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2269     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2270     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2271     BOOL ret;
2272     BYTE *buf = NULL;
2273     DWORD bufSize = 0, i;
2274
2275     /* Try with a bogus blob type */
2276     hdr->bType = 2;
2277     hdr->bVersion = CUR_BLOB_VERSION;
2278     hdr->reserved = 0;
2279     hdr->aiKeyAlg = CALG_RSA_KEYX;
2280     rsaPubKey->magic = 0x31415352;
2281     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2282     rsaPubKey->pubexp = 65537;
2283     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2284      sizeof(modulus1));
2285
2286     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2287      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2288      &bufSize);
2289     ok(!ret && GetLastError() == E_INVALIDARG,
2290      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2291     /* Now with a bogus reserved field */
2292     hdr->bType = PUBLICKEYBLOB;
2293     hdr->reserved = 1;
2294     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2295      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2296      &bufSize);
2297     if (buf)
2298     {
2299         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2300          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2301         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2302         LocalFree(buf);
2303     }
2304     /* Now with a bogus blob version */
2305     hdr->reserved = 0;
2306     hdr->bVersion = 0;
2307     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2308      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2309      &bufSize);
2310     if (buf)
2311     {
2312         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2313          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2314         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2315         LocalFree(buf);
2316     }
2317     /* And with a bogus alg ID */
2318     hdr->bVersion = CUR_BLOB_VERSION;
2319     hdr->aiKeyAlg = CALG_DES;
2320     ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2321      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2322      &bufSize);
2323     if (buf)
2324     {
2325         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2326          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2327         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2328         LocalFree(buf);
2329     }
2330     /* Check a couple of RSA-related OIDs */
2331     hdr->aiKeyAlg = CALG_RSA_KEYX;
2332     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2333      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2334     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2335      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2336     ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2337      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2338     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2339      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2340     /* Finally, all valid */
2341     hdr->aiKeyAlg = CALG_RSA_KEYX;
2342     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2343     {
2344         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2345          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2346         ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2347          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2348         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2349         if (buf)
2350         {
2351             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2352              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2353              bufSize);
2354             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2355              "Unexpected value\n");
2356             LocalFree(buf);
2357         }
2358     }
2359 }
2360
2361 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2362 {
2363     DWORD i;
2364     LPBYTE buf = NULL;
2365     DWORD bufSize = 0;
2366     BOOL ret;
2367
2368     /* Try with a bad length */
2369     ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2370      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2371      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2372     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2373      GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2374      "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2375      GetLastError());
2376     /* Try with a couple of RSA-related OIDs */
2377     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2378      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2379      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2380     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2381      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2382     ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2383      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2384      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2385     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2386      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2387     /* Now try success cases */
2388     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2389     {
2390         bufSize = 0;
2391         ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2392          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2393          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2394         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2395         if (buf)
2396         {
2397             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2398             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2399
2400             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2401              rsaPubKeys[i].decodedModulusLen,
2402              "Wrong size %d\n", bufSize);
2403             ok(hdr->bType == PUBLICKEYBLOB,
2404              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2405              hdr->bType);
2406             ok(hdr->bVersion == CUR_BLOB_VERSION,
2407              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2408              CUR_BLOB_VERSION, hdr->bVersion);
2409             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2410              hdr->reserved);
2411             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2412              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2413             ok(rsaPubKey->magic == 0x31415352,
2414              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2415             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2416              "Wrong bit len %d\n", rsaPubKey->bitlen);
2417             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2418              rsaPubKey->pubexp);
2419             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2420              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2421              "Unexpected modulus\n");
2422             LocalFree(buf);
2423         }
2424     }
2425 }
2426
2427 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2428  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2429  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2430
2431 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2432  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2433  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2434  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2435
2436 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2437 {
2438     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2439     CRYPT_SEQUENCE_OF_ANY seq;
2440     DWORD i;
2441     BOOL ret;
2442     BYTE *buf = NULL;
2443     DWORD bufSize = 0;
2444
2445     /* Encode a homogeneous sequence */
2446     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2447     {
2448         blobs[i].cbData = ints[i].encoded[1] + 2;
2449         blobs[i].pbData = (BYTE *)ints[i].encoded;
2450     }
2451     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2452     seq.rgValue = blobs;
2453
2454     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2455      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2456     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2457     if (buf)
2458     {
2459         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2460         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2461         LocalFree(buf);
2462     }
2463     /* Change the type of the first element in the sequence, and give it
2464      * another go
2465      */
2466     blobs[0].cbData = times[0].encodedTime[1] + 2;
2467     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2468     ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2469      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2470     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2471     if (buf)
2472     {
2473         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2474         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2475          "Unexpected value\n");
2476         LocalFree(buf);
2477     }
2478 }
2479
2480 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2481 {
2482     BOOL ret;
2483     BYTE *buf = NULL;
2484     DWORD bufSize = 0;
2485
2486     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2487      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2488     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2489     if (buf)
2490     {
2491         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2492         DWORD i;
2493
2494         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2495          "Wrong elements %d\n", seq->cValue);
2496         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2497         {
2498             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2499              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2500              seq->rgValue[i].cbData);
2501             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2502              ints[i].encoded[1] + 2), "Unexpected value\n");
2503         }
2504         LocalFree(buf);
2505     }
2506     ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2507      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2508      &bufSize);
2509     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2510     if (buf)
2511     {
2512         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2513
2514         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2515          "Wrong elements %d\n", seq->cValue);
2516         /* Just check the first element since it's all that changed */
2517         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2518          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2519          seq->rgValue[0].cbData);
2520         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2521          times[0].encodedTime[1] + 2), "Unexpected value\n");
2522         LocalFree(buf);
2523     }
2524 }
2525
2526 struct encodedExtensions
2527 {
2528     CERT_EXTENSIONS exts;
2529     const BYTE *encoded;
2530 };
2531
2532 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2533 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2534 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2535 static CERT_EXTENSION criticalExt =
2536  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2537 static CERT_EXTENSION nonCriticalExt =
2538  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2539
2540 static const BYTE ext0[] = { 0x30,0x00 };
2541 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2542                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2543 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2544                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2545
2546 static const struct encodedExtensions exts[] = {
2547  { { 0, NULL }, ext0 },
2548  { { 1, &criticalExt }, ext1 },
2549  { { 1, &nonCriticalExt }, ext2 },
2550 };
2551
2552 static void test_encodeExtensions(DWORD dwEncoding)
2553 {
2554     DWORD i;
2555
2556     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2557     {
2558         BOOL ret;
2559         BYTE *buf = NULL;
2560         DWORD bufSize = 0;
2561
2562         ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2563          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2564         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2565         if (buf)
2566         {
2567             ok(bufSize == exts[i].encoded[1] + 2,
2568              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2569             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2570              "Unexpected value\n");
2571             LocalFree(buf);
2572         }
2573     }
2574 }
2575
2576 static void test_decodeExtensions(DWORD dwEncoding)
2577 {
2578     DWORD i;
2579
2580     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2581     {
2582         BOOL ret;
2583         BYTE *buf = NULL;
2584         DWORD bufSize = 0;
2585
2586         ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2587          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2588          NULL, (BYTE *)&buf, &bufSize);
2589         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2590         if (buf)
2591         {
2592             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2593             DWORD j;
2594
2595             ok(ext->cExtension == exts[i].exts.cExtension,
2596              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2597              ext->cExtension);
2598             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2599             {
2600                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2601                  exts[i].exts.rgExtension[j].pszObjId),
2602                  "Expected OID %s, got %s\n",
2603                  exts[i].exts.rgExtension[j].pszObjId,
2604                  ext->rgExtension[j].pszObjId);
2605                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2606                  exts[i].exts.rgExtension[j].Value.pbData,
2607                  exts[i].exts.rgExtension[j].Value.cbData),
2608                  "Unexpected value\n");
2609             }
2610             LocalFree(buf);
2611         }
2612     }
2613 }
2614
2615 /* MS encodes public key info with a NULL if the algorithm identifier's
2616  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2617  * it encodes them by omitting the algorithm parameters.  This latter approach
2618  * seems more correct, so accept either form.
2619  */
2620 struct encodedPublicKey
2621 {
2622     CERT_PUBLIC_KEY_INFO info;
2623     const BYTE *encoded;
2624     const BYTE *encodedNoNull;
2625     CERT_PUBLIC_KEY_INFO decoded;
2626 };
2627
2628 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2629  0xe, 0xf };
2630 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2631
2632 static const unsigned char bin64[] = {
2633     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2634 static const unsigned char bin65[] = {
2635     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2636 static const unsigned char bin66[] = {
2637     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2638 static const unsigned char bin67[] = {
2639     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2640 static const unsigned char bin68[] = {
2641     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2642     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2643 static const unsigned char bin69[] = {
2644     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2645     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2646 static const unsigned char bin70[] = {
2647     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2648     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2649     0x0f};
2650 static const unsigned char bin71[] = {
2651     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2652     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2653     0x0f};
2654 static unsigned char bin72[] = { 0x05,0x00};
2655
2656 static CHAR oid_bogus[] = "1.2.3",
2657             oid_rsa[]   = szOID_RSA;
2658
2659 static const struct encodedPublicKey pubKeys[] = {
2660  /* with a bogus OID */
2661  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2662   bin64, bin65,
2663   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2664  /* some normal keys */
2665  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2666   bin66, bin67,
2667   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2668  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2669   bin68, bin69,
2670   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2671  /* with add'l parameters--note they must be DER-encoded */
2672  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2673   (BYTE *)aKey, 0 } },
2674   bin70, bin71,
2675   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2676   (BYTE *)aKey, 0 } } },
2677 };
2678
2679 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2680 {
2681     DWORD i;
2682
2683     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2684     {
2685         BOOL ret;
2686         BYTE *buf = NULL;
2687         DWORD bufSize = 0;
2688
2689         ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2690          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2691          &bufSize);
2692         ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2693          "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2694         if (buf)
2695         {
2696             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2697              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2698              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2699              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2700             if (bufSize == pubKeys[i].encoded[1] + 2)
2701                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2702                  "Unexpected value\n");
2703             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2704                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2705                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2706             LocalFree(buf);
2707         }
2708     }
2709 }
2710
2711 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2712  const CERT_PUBLIC_KEY_INFO *got)
2713 {
2714     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2715      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2716      got->Algorithm.pszObjId);
2717     ok(expected->Algorithm.Parameters.cbData ==
2718      got->Algorithm.Parameters.cbData,
2719      "Expected parameters of %d bytes, got %d\n",
2720      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2721     if (expected->Algorithm.Parameters.cbData)
2722         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2723          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2724          "Unexpected algorithm parameters\n");
2725     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2726      "Expected public key of %d bytes, got %d\n",
2727      expected->PublicKey.cbData, got->PublicKey.cbData);
2728     if (expected->PublicKey.cbData)
2729         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2730          got->PublicKey.cbData), "Unexpected public key value\n");
2731 }
2732
2733 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2734 {
2735     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2736      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2737      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2738      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2739     DWORD i;
2740     BOOL ret;
2741     BYTE *buf = NULL;
2742     DWORD bufSize = 0;
2743
2744     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2745     {
2746         /* The NULL form decodes to the decoded member */
2747         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2748          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2749          NULL, (BYTE *)&buf, &bufSize);
2750         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2751         if (buf)
2752         {
2753             comparePublicKeyInfo(&pubKeys[i].decoded,
2754              (CERT_PUBLIC_KEY_INFO *)buf);
2755             LocalFree(buf);
2756         }
2757         /* The non-NULL form decodes to the original */
2758         ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2759          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2760          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2761         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2762         if (buf)
2763         {
2764             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2765             LocalFree(buf);
2766         }
2767     }
2768     /* Test with bogus (not valid DER) parameters */
2769     ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2770      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2771      NULL, (BYTE *)&buf, &bufSize);
2772     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2773      GetLastError() == OSS_DATA_ERROR /* Win9x */),
2774      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2775      GetLastError());
2776 }
2777
2778 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2779  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2780  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2781  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2782  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2783 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2784  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2785  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2786  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2787  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2788 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2789  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2790  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2791  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2792  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2793 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2794  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2795  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2796  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2797  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2798  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2799  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2800 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2801  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2802  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2803  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2804  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2805  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2806  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2807 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2808  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2809  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2810  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2811  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2812  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2813  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2814  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2815  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2816  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2817 static const BYTE v1CertWithPubKey[] = {
2818 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2819 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2820 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2821 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2822 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2823 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2824 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2825 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2826 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2827 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2828 0x01,0x01 };
2829 static const BYTE v1CertWithPubKeyNoNull[] = {
2830 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2831 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2832 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2833 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2834 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2835 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2836 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2837 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2838 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2839 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2840 static const BYTE v1CertWithSubjectKeyId[] = {
2841 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2842 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2843 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2844 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2845 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2846 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2847 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2848 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2849 0x4c,0x61,0x6e,0x67,0x00 };
2850
2851 static const BYTE serialNum[] = { 0x01 };
2852
2853 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2854 {
2855     BOOL ret;
2856     BYTE *buf = NULL;
2857     DWORD size = 0;
2858     CERT_INFO info = { 0 };
2859     static char oid_rsa_rsa[] = szOID_RSA_RSA;
2860     static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2861     CERT_EXTENSION ext;
2862
2863     if (0)
2864     {
2865         /* Test with NULL pvStructInfo (crashes on win9x) */
2866         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2867          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2868         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2869          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2870     }
2871     /* Test with a V1 cert */
2872     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2873      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2874     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2875      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2876     if (buf)
2877     {
2878         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2879          v1Cert[1] + 2, size);
2880         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2881         LocalFree(buf);
2882     }
2883     /* Test v2 cert */
2884     info.dwVersion = CERT_V2;
2885     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2886      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2887     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2888      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2889     if (buf)
2890     {
2891         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2892         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2893         LocalFree(buf);
2894     }
2895     /* Test v3 cert */
2896     info.dwVersion = CERT_V3;
2897     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2898      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2899     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2900      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2901     if (buf)
2902     {
2903         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2904         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2905         LocalFree(buf);
2906     }
2907     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2908      * API doesn't prevent it)
2909      */
2910     info.dwVersion = CERT_V1;
2911     info.cExtension = 1;
2912     info.rgExtension = &criticalExt;
2913     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2914      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2915     ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2916      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2917     if (buf)
2918     {
2919         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2920         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2921         LocalFree(buf);
2922     }
2923     /* test v1 cert with a serial number */
2924     info.SerialNumber.cbData = sizeof(serialNum);
2925     info.SerialNumber.pbData = (BYTE *)serialNum;
2926     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2927      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2928     if (buf)
2929     {
2930         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2931         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2932         LocalFree(buf);
2933     }
2934     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2935     info.Issuer.cbData = sizeof(encodedCommonName);
2936     info.Issuer.pbData = (BYTE *)encodedCommonName;
2937     info.Subject.cbData = sizeof(encodedCommonName);
2938     info.Subject.pbData = (BYTE *)encodedCommonName;
2939     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2940      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2941     if (buf)
2942     {
2943         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2944         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2945         LocalFree(buf);
2946     }
2947     /* Add a public key */
2948     info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2949     info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2950     info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2951     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2952      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2953     if (buf)
2954     {
2955         ok(size == sizeof(v1CertWithPubKey) ||
2956          size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2957         if (size == sizeof(v1CertWithPubKey))
2958             ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2959         else if (size == sizeof(v1CertWithPubKeyNoNull))
2960             ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2961              "Got unexpected value\n");
2962         LocalFree(buf);
2963     }
2964     /* Remove the public key, and add a subject key identifier extension */
2965     info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2966     info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2967     info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2968     ext.pszObjId = oid_subject_key_identifier;
2969     ext.fCritical = FALSE;
2970     ext.Value.cbData = sizeof(octetCommonNameValue);
2971     ext.Value.pbData = (BYTE *)octetCommonNameValue;
2972     info.cExtension = 1;
2973     info.rgExtension = &ext;
2974     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2975      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2976     if (buf)
2977     {
2978         ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2979         ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2980         LocalFree(buf);
2981     }
2982 }
2983
2984 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2985 {
2986     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2987      v1CertWithConstraints, v1CertWithSerial };
2988     BOOL ret;
2989     BYTE *buf = NULL;
2990     DWORD size = 0, i;
2991
2992     /* Test with NULL pbEncoded */
2993     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2994      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2995     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2996      GetLastError() == OSS_BAD_ARG /* Win9x */),
2997      "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
2998     if (0)
2999     {
3000         /* Crashes on win9x */
3001         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3002          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3003         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3004          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3005     }
3006     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
3007      * minimum a cert must have a non-zero serial number, an issuer, and a
3008      * subject.
3009      */
3010     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3011     {
3012         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3013          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3014          (BYTE *)&buf, &size);
3015         ok(!ret, "Expected failure\n");
3016     }
3017     /* Now check with serial number, subject and issuer specified */
3018     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3019      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3020     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3021     if (buf)
3022     {
3023         CERT_INFO *info = (CERT_INFO *)buf;
3024
3025         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3026         ok(info->SerialNumber.cbData == 1,
3027          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3028         ok(*info->SerialNumber.pbData == *serialNum,
3029          "Expected serial number %d, got %d\n", *serialNum,
3030          *info->SerialNumber.pbData);
3031         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3032          "Wrong size %d\n", info->Issuer.cbData);
3033         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3034          "Unexpected issuer\n");
3035         ok(info->Subject.cbData == sizeof(encodedCommonName),
3036          "Wrong size %d\n", info->Subject.cbData);
3037         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3038          info->Subject.cbData), "Unexpected subject\n");
3039         LocalFree(buf);
3040     }
3041     /* Check again with pub key specified */
3042     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3043      v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3044      (BYTE *)&buf, &size);
3045     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3046     if (buf)
3047     {
3048         CERT_INFO *info = (CERT_INFO *)buf;
3049
3050         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3051         ok(info->SerialNumber.cbData == 1,
3052          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3053         ok(*info->SerialNumber.pbData == *serialNum,
3054          "Expected serial number %d, got %d\n", *serialNum,
3055          *info->SerialNumber.pbData);
3056         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3057          "Wrong size %d\n", info->Issuer.cbData);
3058         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3059          "Unexpected issuer\n");
3060         ok(info->Subject.cbData == sizeof(encodedCommonName),
3061          "Wrong size %d\n", info->Subject.cbData);
3062         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3063          info->Subject.cbData), "Unexpected subject\n");
3064         ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3065          szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3066          info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3067         ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3068          "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3069         ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3070          sizeof(aKey)), "Unexpected public key\n");
3071         LocalFree(buf);
3072     }
3073 }
3074
3075 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3076  0xe, 0xf };
3077
3078 static const BYTE signedBigCert[] = {
3079  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3080  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3081  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3082  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3083  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3084  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3085  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3086  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3087  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3088  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3089  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3090  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3091
3092 static void test_encodeCert(DWORD dwEncoding)
3093 {
3094     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
3095      * also that bigCert is a NULL-terminated string, so don't count its
3096      * last byte (otherwise the signed cert won't decode.)
3097      */
3098     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3099      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3100     BOOL ret;
3101     BYTE *buf = NULL;
3102     DWORD bufSize = 0;
3103
3104     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3105      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
3106     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3107     if (buf)
3108     {
3109         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3110         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3111         LocalFree(buf);
3112     }
3113 }
3114
3115 static void test_decodeCert(DWORD dwEncoding)
3116 {
3117     BOOL ret;
3118     BYTE *buf = NULL;
3119     DWORD size = 0;
3120
3121     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3122      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3123     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3124     if (buf)
3125     {
3126         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3127
3128         ok(info->ToBeSigned.cbData == sizeof(bigCert),
3129          "Wrong cert size %d\n", info->ToBeSigned.cbData);
3130         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3131          "Unexpected cert\n");
3132         ok(info->Signature.cbData == sizeof(hash),
3133          "Wrong signature size %d\n", info->Signature.cbData);
3134         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3135          "Unexpected signature\n");
3136         LocalFree(buf);
3137     }
3138     /* A signed cert decodes as a CERT_INFO too */
3139     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3140      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3141     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3142     if (buf)
3143     {
3144         CERT_INFO *info = (CERT_INFO *)buf;
3145
3146         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3147         ok(info->SerialNumber.cbData == 1,
3148          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3149         ok(*info->SerialNumber.pbData == *serialNum,
3150          "Expected serial number %d, got %d\n", *serialNum,
3151          *info->SerialNumber.pbData);
3152         ok(info->Issuer.cbData == sizeof(encodedCommonName),
3153          "Wrong size %d\n", info->Issuer.cbData);
3154         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3155          "Unexpected issuer\n");
3156         ok(info->Subject.cbData == sizeof(encodedCommonName),
3157          "Wrong size %d\n", info->Subject.cbData);
3158         ok(!memcmp(info->Subject.pbData, encodedCommonName,
3159          info->Subject.cbData), "Unexpected subject\n");
3160         LocalFree(buf);
3161     }
3162 }
3163
3164 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3165 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3166  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3167  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3168 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3169  0x00, 0x03 };
3170 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3171  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3172  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3173 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3174  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3175  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3176  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3177  0x2e, 0x6f, 0x72, 0x67 };
3178 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3179  CRL_REASON_AFFILIATION_CHANGED;
3180
3181 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3182 {
3183     CRL_DIST_POINTS_INFO info = { 0 };
3184     CRL_DIST_POINT point = { { 0 } };
3185     CERT_ALT_NAME_ENTRY entry = { 0 };
3186     BOOL ret;
3187     BYTE *buf = NULL;
3188     DWORD size = 0;
3189
3190     /* Test with an empty info */
3191     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3192      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3193     ok(!ret && GetLastError() == E_INVALIDARG,
3194      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3195     /* Test with one empty dist point */
3196     info.cDistPoint = 1;
3197     info.rgDistPoint = &point;
3198     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3199      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3200     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3201     if (buf)
3202     {
3203         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3204         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3205         LocalFree(buf);
3206     }
3207     /* A dist point with an invalid name */
3208     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3209     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3210     U(entry).pwszURL = (LPWSTR)nihongoURL;
3211     U(point.DistPointName).FullName.cAltEntry = 1;
3212     U(point.DistPointName).FullName.rgAltEntry = &entry;
3213     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3214      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3215     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3216      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3217     /* The first invalid character is at index 7 */
3218     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3219      "Expected invalid char at index 7, got %d\n",
3220      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3221     /* A dist point with (just) a valid name */
3222     U(entry).pwszURL = (LPWSTR)url;
3223     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3224      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3225     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3226     if (buf)
3227     {
3228         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3229         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3230         LocalFree(buf);
3231     }
3232     /* A dist point with (just) reason flags */
3233     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3234     point.ReasonFlags.cbData = sizeof(crlReason);
3235     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3236     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3237      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3238     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3239     if (buf)
3240     {
3241         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3242         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3243         LocalFree(buf);
3244     }
3245     /* A dist point with just an issuer */
3246     point.ReasonFlags.cbData = 0;
3247     point.CRLIssuer.cAltEntry = 1;
3248     point.CRLIssuer.rgAltEntry = &entry;
3249     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3250      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3251     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3252     if (buf)
3253     {
3254         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3255         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3256         LocalFree(buf);
3257     }
3258     /* A dist point with both a name and an issuer */
3259     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3260     ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3261      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3262     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3263     if (buf)
3264     {
3265         ok(size == sizeof(distPointWithUrlAndIssuer),
3266          "Wrong size %d\n", size);
3267         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3268         LocalFree(buf);
3269     }
3270 }
3271
3272 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3273 {
3274     BOOL ret;
3275     BYTE *buf = NULL;
3276     DWORD size = 0;
3277     PCRL_DIST_POINTS_INFO info;
3278     PCRL_DIST_POINT point;
3279     PCERT_ALT_NAME_ENTRY entry;
3280
3281     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3282      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3283      (BYTE *)&buf, &size);
3284     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3285     if (ret)
3286     {
3287         info = (PCRL_DIST_POINTS_INFO)buf;
3288         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3289          "Wrong size %d\n", size);
3290         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3291          info->cDistPoint);
3292         point = info->rgDistPoint;
3293         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3294          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3295          point->DistPointName.dwDistPointNameChoice);
3296         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3297         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3298         LocalFree(buf);
3299     }
3300     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3301      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3302      (BYTE *)&buf, &size);
3303     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3304     if (ret)
3305     {
3306         info = (PCRL_DIST_POINTS_INFO)buf;
3307         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3308          "Wrong size %d\n", size);
3309         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3310          info->cDistPoint);
3311         point = info->rgDistPoint;
3312         ok(point->DistPointName.dwDistPointNameChoice ==
3313          CRL_DIST_POINT_FULL_NAME,
3314          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3315          point->DistPointName.dwDistPointNameChoice);
3316         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3317          "Expected 1 name entry, got %d\n",
3318          U(point->DistPointName).FullName.cAltEntry);
3319         entry = U(point->DistPointName).FullName.rgAltEntry;
3320         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3321          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3322         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3323         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3324         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3325         LocalFree(buf);
3326     }
3327     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3328      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3329      NULL, (BYTE *)&buf, &size);
3330     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3331     if (ret)
3332     {
3333         info = (PCRL_DIST_POINTS_INFO)buf;
3334         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3335          "Wrong size %d\n", size);
3336         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3337          info->cDistPoint);
3338         point = info->rgDistPoint;
3339         ok(point->DistPointName.dwDistPointNameChoice ==
3340          CRL_DIST_POINT_NO_NAME,
3341          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3342          point->DistPointName.dwDistPointNameChoice);
3343         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3344          "Expected reason length\n");
3345         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3346          "Unexpected reason\n");
3347         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3348         LocalFree(buf);
3349     }
3350     ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3351      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3352      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3353     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3354     if (ret)
3355     {
3356         info = (PCRL_DIST_POINTS_INFO)buf;
3357         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3358          "Wrong size %d\n", size);
3359         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3360          info->cDistPoint);
3361         point = info->rgDistPoint;
3362         ok(point->DistPointName.dwDistPointNameChoice ==
3363          CRL_DIST_POINT_FULL_NAME,
3364          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3365          point->DistPointName.dwDistPointNameChoice);
3366         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3367          "Expected 1 name entry, got %d\n",
3368          U(point->DistPointName).FullName.cAltEntry);
3369         entry = U(point->DistPointName).FullName.rgAltEntry;
3370         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3371          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3372         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3373         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3374         ok(point->CRLIssuer.cAltEntry == 1,
3375          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3376         entry = point->CRLIssuer.rgAltEntry;
3377         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3378          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3379         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3380         LocalFree(buf);
3381     }
3382 }
3383
3384 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3385 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3386 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3387  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3388  0x67 };
3389
3390 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3391 {
3392     BOOL ret;
3393     BYTE *buf = NULL;
3394     DWORD size = 0;
3395     CRL_ISSUING_DIST_POINT point = { { 0 } };
3396     CERT_ALT_NAME_ENTRY entry;
3397
3398     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3399      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3400     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3401     {
3402         skip("no X509_ISSUING_DIST_POINT encode support\n");
3403         return;
3404     }
3405     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3406      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3407     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3408      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3409     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3410     if (buf)
3411     {
3412         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3413         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3414         LocalFree(buf);
3415     }
3416     /* nonsensical flags */
3417     point.fOnlyContainsUserCerts = TRUE;
3418     point.fOnlyContainsCACerts = TRUE;
3419     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3420      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3421     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3422     if (buf)
3423     {
3424         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3425         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3426         LocalFree(buf);
3427     }
3428     /* unimplemented name type */
3429     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3430     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3431     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3432      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3433     ok(!ret && GetLastError() == E_INVALIDARG,
3434      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3435     /* empty name */
3436     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3437     U(point.DistPointName).FullName.cAltEntry = 0;
3438     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3439      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3440     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3441     if (buf)
3442     {
3443         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3444         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3445         LocalFree(buf);
3446     }
3447     /* name with URL entry */
3448     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3449     U(entry).pwszURL = (LPWSTR)url;
3450     U(point.DistPointName).FullName.cAltEntry = 1;
3451     U(point.DistPointName).FullName.rgAltEntry = &entry;
3452     ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3453      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3454     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3455     if (buf)
3456     {
3457         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3458         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3459         LocalFree(buf);
3460     }
3461 }
3462
3463 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3464  const CERT_ALT_NAME_ENTRY *got)
3465 {
3466     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3467      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3468      got->dwAltNameChoice);
3469     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3470     {
3471         switch (got->dwAltNameChoice)
3472         {
3473         case CERT_ALT_NAME_RFC822_NAME:
3474         case CERT_ALT_NAME_DNS_NAME:
3475         case CERT_ALT_NAME_EDI_PARTY_NAME:
3476         case CERT_ALT_NAME_URL:
3477         case CERT_ALT_NAME_REGISTERED_ID:
3478             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3479              (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3480              (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3481              !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3482              "Unexpected name\n");
3483             break;
3484         case CERT_ALT_NAME_X400_ADDRESS:
3485         case CERT_ALT_NAME_DIRECTORY_NAME:
3486         case CERT_ALT_NAME_IP_ADDRESS:
3487             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3488                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3489             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3490                        U(*got).IPAddress.cbData), "Unexpected value\n");
3491             break;
3492         }
3493     }
3494 }
3495
3496 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3497  const CERT_ALT_NAME_INFO *got)
3498 {
3499     DWORD i;
3500
3501     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3502      expected->cAltEntry, got->cAltEntry);
3503     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3504         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3505 }
3506
3507 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3508  const CRL_DIST_POINT_NAME *got)
3509 {
3510     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3511      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3512     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3513         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3514 }
3515
3516 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3517  const CRL_ISSUING_DIST_POINT *got)
3518 {
3519     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3520     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3521      "Unexpected fOnlyContainsUserCerts\n");
3522     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3523      "Unexpected fOnlyContainsCACerts\n");
3524     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3525      "Unexpected reason flags\n");
3526     ok(got->fIndirectCRL == expected->fIndirectCRL,
3527      "Unexpected fIndirectCRL\n");
3528 }
3529
3530 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3531 {
3532     BOOL ret;
3533     BYTE *buf = NULL;
3534     DWORD size = 0;
3535     CRL_ISSUING_DIST_POINT point = { { 0 } };
3536
3537     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3538      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3539      (BYTE *)&buf, &size);
3540     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3541     {
3542         skip("no X509_ISSUING_DIST_POINT decode support\n");
3543         return;
3544     }
3545     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3546     if (ret)
3547     {
3548         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3549         LocalFree(buf);
3550     }
3551     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3552      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3553      (BYTE *)&buf, &size);
3554     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3555     if (ret)
3556     {
3557         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3558         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3559         LocalFree(buf);
3560     }
3561     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3562      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3563      (BYTE *)&buf, &size);
3564     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3565     if (ret)
3566     {
3567         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3568         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3569         U(point.DistPointName).FullName.cAltEntry = 0;
3570         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3571         LocalFree(buf);
3572     }
3573     ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3574      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3575     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3576     if (ret)
3577     {
3578         CERT_ALT_NAME_ENTRY entry;
3579
3580         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3581         U(entry).pwszURL = (LPWSTR)url;
3582         U(point.DistPointName).FullName.cAltEntry = 1;
3583         U(point.DistPointName).FullName.rgAltEntry = &entry;
3584         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3585         LocalFree(buf);
3586     }
3587 }
3588
3589 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3590  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3591  0x30, 0x5a };
3592 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3593  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3594  0x30, 0x30, 0x30, 0x30, 0x5a };
3595 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3596  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3597  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3598  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3599  0x5a };
3600 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3601  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3602  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3603  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3604  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3605  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3606 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3607  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3608  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3609  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3610  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3611  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3612 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3613  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3614  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3615  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3616  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3617  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3618  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3619 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3620  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3621  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3622  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3623  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3624  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3625  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3626 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3627  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3628  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3629  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3630  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3631  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3632  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3633 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3634  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3635  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3636  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3637  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3638  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3639  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3640
3641 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3642 {
3643     BOOL ret;
3644     BYTE *buf = NULL;
3645     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3646     DWORD size = 0;
3647     CRL_INFO info = { 0 };
3648     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3649     CERT_EXTENSION ext;
3650
3651     /* Test with a V1 CRL */
3652     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3653      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3654     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3655      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3656     if (buf)
3657     {
3658         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3659         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3660         LocalFree(buf);
3661     }
3662     /* Test v2 CRL */
3663     info.dwVersion = CRL_V2;
3664     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3665      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3666     ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3667      "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3668     if (buf)
3669     {
3670         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3671          v2CRL[1] + 2, size);
3672         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3673         LocalFree(buf);
3674     }
3675     /* v1 CRL with a name */
3676     info.dwVersion = CRL_V1;
3677     info.Issuer.cbData = sizeof(encodedCommonName);
3678     info.Issuer.pbData = (BYTE *)encodedCommonName;
3679     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3680      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3681     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3682     if (buf)
3683     {
3684         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3685         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3686         LocalFree(buf);
3687     }
3688     if (0)
3689     {
3690         /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3691         info.cCRLEntry = 1;
3692         ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3693          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3694         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3695          "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3696     }
3697     /* now set an empty entry */
3698     info.cCRLEntry = 1;
3699     info.rgCRLEntry = &entry;
3700     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3701      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3702     if (buf)
3703     {
3704         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3705          "Wrong size %d\n", size);
3706         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3707          "Got unexpected value\n");
3708         LocalFree(buf);
3709     }
3710     /* an entry with a serial number */
3711     entry.SerialNumber.cbData = sizeof(serialNum);
3712     entry.SerialNumber.pbData = (BYTE *)serialNum;
3713     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3714      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3715     if (buf)
3716     {
3717         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3718          "Wrong size %d\n", size);
3719         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3720          "Got unexpected value\n");
3721         LocalFree(buf);
3722     }
3723     /* an entry with an extension */
3724     entry.cExtension = 1;
3725     entry.rgExtension = &criticalExt;
3726     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3727      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3728     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3729     if (buf)
3730     {
3731         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3732         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3733         LocalFree(buf);
3734     }
3735     /* a CRL with an extension */
3736     entry.cExtension = 0;
3737     info.cExtension = 1;
3738     info.rgExtension = &criticalExt;
3739     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3740      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3741     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3742     if (buf)
3743     {
3744         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3745         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3746         LocalFree(buf);
3747     }
3748     /* a v2 CRL with an extension, this time non-critical */
3749     info.dwVersion = CRL_V2;
3750     info.rgExtension = &nonCriticalExt;
3751     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3752      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3753     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3754     if (buf)
3755     {
3756         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3757         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3758         LocalFree(buf);
3759     }
3760     /* a v2 CRL with an issuing dist point extension */
3761     ext.pszObjId = oid_issuing_dist_point;
3762     ext.fCritical = TRUE;
3763     ext.Value.cbData = sizeof(urlIDP);
3764     ext.Value.pbData = (LPBYTE)urlIDP;
3765     entry.rgExtension = &ext;
3766     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3767      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3768     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3769     if (buf)
3770     {
3771         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3772         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3773         LocalFree(buf);
3774     }
3775 }
3776
3777 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3778  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3779  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3780  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3781  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3782  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3783  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3784  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3785  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3786  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3787  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3788  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3789  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3790  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3791  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3792  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3793  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3794  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3795  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3796  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3797  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3798  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3799  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3800  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3801  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3802  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3803  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3804  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3805  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3806  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3807  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3808  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3809  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3810  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3811  0xcd };
3812 static const BYTE verisignCRLWithLotsOfEntries[] = {
3813 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3814 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3815 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3816 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3817 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3818 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3819 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3820 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3821 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3822 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3823 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3824 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3825 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3826 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3827 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3828 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3829 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3830 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3831 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3832 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3833 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3834 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3835 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3836 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3837 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3838 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3839 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3840 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3841 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3842 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3843 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3844 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3845 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3846 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3847 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3848 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3849 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3850 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3851 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3852 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3853 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3854 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3855 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3856 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3857 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3858 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3859 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3860 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3861 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3862 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3863 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3864 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3865 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3866 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3867 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3868 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3869 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3870 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3871 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3872 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3873 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3874 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3875 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3876 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3877 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3878 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3879 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3880 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3881 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3882 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3883 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3884 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3885 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3886 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3887 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3888 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3889 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3890 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3891 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3892 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3893 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3894 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3895 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3896 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3897 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3898 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3899 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3900 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3901 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3902 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3903 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3904 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3905 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3906 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3907 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3908 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3909 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3910 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3911 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3912 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3913 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3914 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3915 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3916 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3917 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3918 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3919 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3920 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3921 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3922 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3923 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3924 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3925 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3926 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3927 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3928 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3929 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3930 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3931 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3932 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3933 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3934 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3935 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3936 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3937 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3938 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3939 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3940 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3941 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3942 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3943 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3944 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3945 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3946 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3947 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3948 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3949 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3950 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3951 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3952 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3953 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3954 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3955 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3956 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3957 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3958 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3959 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3960 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3961 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3962 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3963 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3964 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3965 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3966 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3967 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3968 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3969 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3970 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3971 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3972 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3973 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3974 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3975 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3976 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3977 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3978 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3979 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3980 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3981 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3982 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3983 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3984 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3985 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3986 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3987 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3988 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3989 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3990 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3991 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3992 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3993 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3994 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3995 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3996 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3997 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3998 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3999 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4000 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4001 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4002 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4003 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4004 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4005 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4006 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4007 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4008 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4009 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4010 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4011 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4012 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4013 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4014 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4015 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4016 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4017 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4018 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4019 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4020 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4021 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4022 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4023 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4024 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4025 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4026 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4027 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4028 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4029 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4030 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4031 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4032 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4033 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4034 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4035 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4036 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4037 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4038 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4039 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4040 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4041 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4042 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4043 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4044 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4045 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4046 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4047 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4048 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4049 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4050 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4051 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4052 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4053 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4054 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4055 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4056 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4057 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4058 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4059 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4060 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4061 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4062 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4063 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4064 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4065 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4066 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4067 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4068 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4069 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4070 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4071 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4072 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4073 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4074 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4075 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4076 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4077 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4078 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4079 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4080 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4081 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4082 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4083 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4084 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4085 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4086 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4087 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4088 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4089 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4090 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4091 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4092 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4093 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4094 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4095 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4096 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4097 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4098 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4099 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4100 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4101 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4102 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4103 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4104 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4105 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4106 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4107 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4108 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4109 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4110 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4111 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4112 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4113 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4114 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4115 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4116 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4117 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4118 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4119 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4120 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4121 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4122 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4123 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4124 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4125 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4126 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4127 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4128 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4129 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4130 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4131 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4132 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4133 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4134 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4135 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4136 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4137 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4138 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4139 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4140 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4141 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4142 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4143 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4144 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4145 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4146 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4147 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4148 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4149 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4150 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4151 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4152 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4153 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4154 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4155 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4156 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4157 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4158 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4159 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4160 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4161 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4162 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4163 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4164 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4165 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4166 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4167 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4168 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4169 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4170 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4171 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4172 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4173 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4174 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4175 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4176 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4177 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4178 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4179 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4180 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4181 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4182 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4183 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4184 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4185 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4186 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4187 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4188 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4189 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4190 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4191 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4192 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4193 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4194 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4195 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4196 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4197 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4198 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4199 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4200 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4201 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4202 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4203 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4204 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4205 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4206 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4207 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4208 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4209 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4210 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4211 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4212 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4213 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4214 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4215 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4216 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4217 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4218 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4219 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4220 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4221 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4222 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4223 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4224 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4225 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4226 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4227 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4228 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4229 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4230 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4231 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4232 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4233 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4234 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4235 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4236 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4237 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4238 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4239 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4240 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4241 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4242 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4243 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4244 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4245 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4246 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4247 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4248 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4249 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4250 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4251 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4252 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4253 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4254 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4255 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4256 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4257 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4258 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4259 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4260 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4261 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4262 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4263 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4264 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4265 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4266 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4267 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4268 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4269 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4270 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4271 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4272 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4273 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4274 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4275 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4276 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4277 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4278 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4279 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4280 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4281 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4282 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4283 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4284 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4285 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4286 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4287 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4288 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4289 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4290 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4291 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4292 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4293 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4294 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4295 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4296 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4297 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4298 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4299 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4300 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4301 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4302 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4303 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4304 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4305 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4306 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4307 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4308 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4309 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4310 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4311 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4312 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4313 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4314 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4315 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4316 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4317 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4318 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4319 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4320 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4321
4322 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4323 {
4324     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4325     BOOL ret;
4326     BYTE *buf = NULL;
4327     DWORD size = 0, i;
4328
4329     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4330     {
4331         ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4332          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4333          (BYTE *)&buf, &size);
4334         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4335          GetLastError() == OSS_DATA_ERROR /* Win9x */),
4336          "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4337          GetLastError());
4338     }
4339     /* at a minimum, a CRL must contain an issuer: */
4340     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4341      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4342      (BYTE *)&buf, &size);
4343     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4344     if (buf)
4345     {
4346         CRL_INFO *info = (CRL_INFO *)buf;
4347
4348         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4349         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4350          info->cCRLEntry);
4351         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4352          "Wrong issuer size %d\n", info->Issuer.cbData);
4353         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4354          "Unexpected issuer\n");
4355         LocalFree(buf);
4356     }
4357     /* check decoding with an empty CRL entry */
4358     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4359      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4360      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4361     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4362      GetLastError() == OSS_DATA_ERROR /* Win9x */),
4363      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4364      GetLastError());
4365     /* with a real CRL entry */
4366     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4367      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4368      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4369     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4370     if (buf)
4371     {
4372         CRL_INFO *info = (CRL_INFO *)buf;
4373         CRL_ENTRY *entry;
4374
4375         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4376         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4377          info->cCRLEntry);
4378         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4379         entry = info->rgCRLEntry;
4380         ok(entry->SerialNumber.cbData == 1,
4381          "Expected serial number size 1, got %d\n",
4382          entry->SerialNumber.cbData);
4383         ok(*entry->SerialNumber.pbData == *serialNum,
4384          "Expected serial number %d, got %d\n", *serialNum,
4385          *entry->SerialNumber.pbData);
4386         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4387          "Wrong issuer size %d\n", info->Issuer.cbData);
4388         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4389          "Unexpected issuer\n");
4390         LocalFree(buf);
4391     }
4392     /* a real CRL from verisign that has extensions */
4393     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4394      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4395      NULL, (BYTE *)&buf, &size);
4396     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4397     if (buf)
4398     {
4399         CRL_INFO *info = (CRL_INFO *)buf;
4400         CRL_ENTRY *entry;
4401
4402         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4403         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4404          info->cCRLEntry);
4405         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4406         entry = info->rgCRLEntry;
4407         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4408          info->cExtension);
4409         LocalFree(buf);
4410     }
4411     /* another real CRL from verisign that has lots of entries */
4412     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4413      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4414      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4415     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4416     if (buf)
4417     {
4418         CRL_INFO *info = (CRL_INFO *)buf;
4419
4420         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4421         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4422          info->cCRLEntry);
4423         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4424          info->cExtension);
4425         LocalFree(buf);
4426     }
4427     /* and finally, with an extension */
4428     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4429      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4430      NULL, (BYTE *)&buf, &size);
4431     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4432     if (buf)
4433     {
4434         CRL_INFO *info = (CRL_INFO *)buf;
4435         CRL_ENTRY *entry;
4436
4437         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4438         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4439          info->cCRLEntry);
4440         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4441         entry = info->rgCRLEntry;
4442         ok(entry->SerialNumber.cbData == 1,
4443          "Expected serial number size 1, got %d\n",
4444          entry->SerialNumber.cbData);
4445         ok(*entry->SerialNumber.pbData == *serialNum,
4446          "Expected serial number %d, got %d\n", *serialNum,
4447          *entry->SerialNumber.pbData);
4448         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4449          "Wrong issuer size %d\n", info->Issuer.cbData);
4450         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4451          "Unexpected issuer\n");
4452         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4453          info->cExtension);
4454         LocalFree(buf);
4455     }
4456     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4457      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4458      NULL, (BYTE *)&buf, &size);
4459     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4460     if (buf)
4461     {
4462         CRL_INFO *info = (CRL_INFO *)buf;
4463
4464         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4465          info->cExtension);
4466         LocalFree(buf);
4467     }
4468     /* And again, with an issuing dist point */
4469     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4470      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4471      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4472     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4473     if (buf)
4474     {
4475         CRL_INFO *info = (CRL_INFO *)buf;
4476
4477         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4478          info->cExtension);
4479         LocalFree(buf);
4480     }
4481 }
4482
4483 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4484  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4485 static const BYTE encodedUsage[] = {
4486  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4487  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4488  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4489
4490 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4491 {
4492     BOOL ret;
4493     BYTE *buf = NULL;
4494     DWORD size = 0;
4495     CERT_ENHKEY_USAGE usage;
4496
4497     /* Test with empty usage */
4498     usage.cUsageIdentifier = 0;
4499     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4500      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4501     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4502     if (buf)
4503     {
4504         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4505         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4506         LocalFree(buf);
4507     }
4508     /* Test with a few usages */
4509     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4510     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4511     ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4512      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4513     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4514     if (buf)
4515     {
4516         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4517         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4518         LocalFree(buf);
4519     }
4520 }
4521
4522 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4523 {
4524     BOOL ret;
4525     LPBYTE buf = NULL;
4526     DWORD size = 0;
4527
4528     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4529      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4530      (BYTE *)&buf, &size);
4531     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4532     if (buf)
4533     {
4534         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4535
4536         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4537          "Wrong size %d\n", size);
4538         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4539          usage->cUsageIdentifier);
4540         LocalFree(buf);
4541     }
4542     ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4543      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4544      (BYTE *)&buf, &size);
4545     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4546     if (buf)
4547     {
4548         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4549         DWORD i;
4550
4551         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4552          "Wrong size %d\n", size);
4553         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4554          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4555         for (i = 0; i < usage->cUsageIdentifier; i++)
4556             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4557              "Expected OID %s, got %s\n", keyUsages[i],
4558              usage->rgpszUsageIdentifier[i]);
4559         LocalFree(buf);
4560     }
4561 }
4562
4563 static BYTE keyId[] = { 1,2,3,4 };
4564 static const BYTE authorityKeyIdWithId[] = {
4565  0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4566 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4567  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4568  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4569 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4570
4571 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4572 {
4573     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4574     BOOL ret;
4575     BYTE *buf = NULL;
4576     DWORD size = 0;
4577
4578     /* Test with empty id */
4579     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4580      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4581     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4582     if (buf)
4583     {
4584         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4585         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4586         LocalFree(buf);
4587     }
4588     /* With just a key id */
4589     info.KeyId.cbData = sizeof(keyId);
4590     info.KeyId.pbData = keyId;
4591     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4592      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4593     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4594     if (buf)
4595     {
4596         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4597         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4598         LocalFree(buf);
4599     }
4600     /* With just an issuer */
4601     info.KeyId.cbData = 0;
4602     info.CertIssuer.cbData = sizeof(encodedCommonName);
4603     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4604     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4605      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4606     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4607     if (buf)
4608     {
4609         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4610          size);
4611         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4612         LocalFree(buf);
4613     }
4614     /* With just a serial number */
4615     info.CertIssuer.cbData = 0;
4616     info.CertSerialNumber.cbData = sizeof(serialNum);
4617     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4618     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4619      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4620     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4621     if (buf)
4622     {
4623         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4624          size);
4625         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4626         LocalFree(buf);
4627     }
4628 }
4629
4630 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4631 {
4632     BOOL ret;
4633     LPBYTE buf = NULL;
4634     DWORD size = 0;
4635
4636     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4637      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4638      (BYTE *)&buf, &size);
4639     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4640     if (buf)
4641     {
4642         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4643
4644         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4645          size);
4646         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4647         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4648         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4649         LocalFree(buf);
4650     }
4651     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4652      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4653      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4654     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4655     if (buf)
4656     {
4657         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4658
4659         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4660          size);
4661         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4662         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4663          "Unexpected key id\n");
4664         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4665         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4666         LocalFree(buf);
4667     }
4668     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4669      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4670      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4671     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4672     if (buf)
4673     {
4674         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4675
4676         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4677          size);
4678         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4679         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4680          "Unexpected issuer len\n");
4681         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4682          sizeof(encodedCommonName)), "Unexpected issuer\n");
4683         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4684         LocalFree(buf);
4685     }
4686     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4687      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4688      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4689     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4690     if (buf)
4691     {
4692         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4693
4694         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4695          size);
4696         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4697         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4698         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4699          "Unexpected serial number len\n");
4700         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4701          "Unexpected serial number\n");
4702         LocalFree(buf);
4703     }
4704 }
4705
4706 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4707  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4708  0x6f,0x72,0x67 };
4709
4710 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4711 {
4712     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4713     CERT_ALT_NAME_ENTRY entry = { 0 };
4714     BOOL ret;
4715     BYTE *buf = NULL;
4716     DWORD size = 0;
4717
4718     /* Test with empty id */
4719     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4720      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4721     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4722     if (buf)
4723     {
4724         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4725         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4726         LocalFree(buf);
4727     }
4728     /* With just a key id */
4729     info.KeyId.cbData = sizeof(keyId);
4730     info.KeyId.pbData = keyId;
4731     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4732      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4733     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4734     if (buf)
4735     {
4736         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4737          size);
4738         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4739         LocalFree(buf);
4740     }
4741     /* With a bogus issuer name */
4742     info.KeyId.cbData = 0;
4743     info.AuthorityCertIssuer.cAltEntry = 1;
4744     info.AuthorityCertIssuer.rgAltEntry = &entry;
4745     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4746      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4747     ok(!ret && GetLastError() == E_INVALIDARG,
4748      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4749     /* With an issuer name */
4750     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4751     U(entry).pwszURL = (LPWSTR)url;
4752     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4753      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4754     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4755     if (buf)
4756     {
4757         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4758          size);
4759         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4760          "Unexpected value\n");
4761         LocalFree(buf);
4762     }
4763     /* With just a serial number */
4764     info.AuthorityCertIssuer.cAltEntry = 0;
4765     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4766     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4767     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4768      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4769     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4770     if (buf)
4771     {
4772         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4773          size);
4774         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4775         LocalFree(buf);
4776     }
4777 }
4778
4779 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4780 {
4781     BOOL ret;
4782     LPBYTE buf = NULL;
4783     DWORD size = 0;
4784
4785     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4786      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4787      (BYTE *)&buf, &size);
4788     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4789     if (buf)
4790     {
4791         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4792
4793         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4794          size);
4795         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4796         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4797          "Expected no issuer name entries\n");
4798         ok(info->AuthorityCertSerialNumber.cbData == 0,
4799          "Expected no serial number\n");
4800         LocalFree(buf);
4801     }
4802     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4803      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4804      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4805     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4806     if (buf)
4807     {
4808         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4809
4810         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4811          size);
4812         ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4813         ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4814          "Unexpected key id\n");
4815         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4816          "Expected no issuer name entries\n");
4817         ok(info->AuthorityCertSerialNumber.cbData == 0,
4818          "Expected no serial number\n");
4819         LocalFree(buf);
4820     }
4821     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4822      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4823      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4824     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4825     if (buf)
4826     {
4827         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4828
4829         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4830          size);
4831         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4832         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4833          "Expected 1 issuer entry, got %d\n",
4834          info->AuthorityCertIssuer.cAltEntry);
4835         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4836          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4837          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4838         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4839          url), "Unexpected URL\n");
4840         ok(info->AuthorityCertSerialNumber.cbData == 0,
4841          "Expected no serial number\n");
4842         LocalFree(buf);
4843     }
4844     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4845      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4846      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4847     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4848     if (buf)
4849     {
4850         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4851
4852         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4853          size);
4854         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4855         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4856          "Expected no issuer name entries\n");
4857         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4858          "Unexpected serial number len\n");
4859         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4860          sizeof(serialNum)), "Unexpected serial number\n");
4861         LocalFree(buf);
4862     }
4863 }
4864
4865 static const BYTE authorityInfoAccessWithUrl[] = {
4866 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4867 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4868 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4869 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4870 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4871 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4872
4873 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4874 {
4875     static char oid1[] = "1.2.3";
4876     static char oid2[] = "1.5.6";
4877     BOOL ret;
4878     BYTE *buf = NULL;
4879     DWORD size = 0;
4880     CERT_ACCESS_DESCRIPTION accessDescription[2];
4881     CERT_AUTHORITY_INFO_ACCESS aia;
4882
4883     memset(accessDescription, 0, sizeof(accessDescription));
4884     aia.cAccDescr = 0;
4885     aia.rgAccDescr = NULL;
4886     /* Having no access descriptions is allowed */
4887     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4888      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4889     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4890     if (buf)
4891     {
4892         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4893         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4894         LocalFree(buf);
4895         buf = NULL;
4896     }
4897     /* It can't have an empty access method */
4898     aia.cAccDescr = 1;
4899     aia.rgAccDescr = accessDescription;
4900     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4901      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4902     ok(!ret && (GetLastError() == E_INVALIDARG ||
4903      GetLastError() == OSS_LIMITED /* Win9x */),
4904      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
4905     /* It can't have an empty location */
4906     accessDescription[0].pszAccessMethod = oid1;
4907     SetLastError(0xdeadbeef);
4908     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4909      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4910     ok(!ret && GetLastError() == E_INVALIDARG,
4911      "expected E_INVALIDARG, got %08x\n", GetLastError());
4912     accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4913     U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4914     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4915      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4916     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4917     if (buf)
4918     {
4919         ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4920          size);
4921         ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4922          "unexpected value\n");
4923         LocalFree(buf);
4924         buf = NULL;
4925     }
4926     accessDescription[1].pszAccessMethod = oid2;
4927     accessDescription[1].AccessLocation.dwAltNameChoice =
4928      CERT_ALT_NAME_IP_ADDRESS;
4929     U(accessDescription[1].AccessLocation).IPAddress.cbData =
4930      sizeof(encodedIPAddr);
4931     U(accessDescription[1].AccessLocation).IPAddress.pbData =
4932      (LPBYTE)encodedIPAddr;
4933     aia.cAccDescr = 2;
4934     ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4935      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4936     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4937     if (buf)
4938     {
4939         ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4940          "unexpected size %d\n", size);
4941         ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4942          "unexpected value\n");
4943         LocalFree(buf);
4944         buf = NULL;
4945     }
4946 }
4947
4948 static void compareAuthorityInfoAccess(LPCSTR header,
4949  const CERT_AUTHORITY_INFO_ACCESS *expected,
4950  const CERT_AUTHORITY_INFO_ACCESS *got)
4951 {
4952     DWORD i;
4953
4954     ok(expected->cAccDescr == got->cAccDescr,
4955      "%s: expected %d access descriptions, got %d\n", header,
4956      expected->cAccDescr, got->cAccDescr);
4957     for (i = 0; i < expected->cAccDescr; i++)
4958     {
4959         ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4960          got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4961          header, i, expected->rgAccDescr[i].pszAccessMethod,
4962          got->rgAccDescr[i].pszAccessMethod);
4963         compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4964          &got->rgAccDescr[i].AccessLocation);
4965     }
4966 }
4967
4968 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4969 {
4970     static char oid1[] = "1.2.3";
4971     static char oid2[] = "1.5.6";
4972     BOOL ret;
4973     LPBYTE buf = NULL;
4974     DWORD size = 0;
4975
4976     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4977      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4978      (BYTE *)&buf, &size);
4979     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4980     if (buf)
4981     {
4982         CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4983
4984         compareAuthorityInfoAccess("empty AIA", &aia,
4985          (CERT_AUTHORITY_INFO_ACCESS *)buf);
4986         LocalFree(buf);
4987         buf = NULL;
4988     }
4989     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4990      authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4991      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4992     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4993     if (buf)
4994     {
4995         CERT_ACCESS_DESCRIPTION accessDescription;
4996         CERT_AUTHORITY_INFO_ACCESS aia;
4997
4998         accessDescription.pszAccessMethod = oid1;
4999         accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5000         U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5001         aia.cAccDescr = 1;
5002         aia.rgAccDescr = &accessDescription;
5003         compareAuthorityInfoAccess("AIA with URL", &aia,
5004          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5005         LocalFree(buf);
5006         buf = NULL;
5007     }
5008     ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5009      authorityInfoAccessWithUrlAndIPAddr,
5010      sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5011      NULL, (BYTE *)&buf, &size);
5012     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5013     if (buf)
5014     {
5015         CERT_ACCESS_DESCRIPTION accessDescription[2];
5016         CERT_AUTHORITY_INFO_ACCESS aia;
5017
5018         accessDescription[0].pszAccessMethod = oid1;
5019         accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5020         U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5021         accessDescription[1].pszAccessMethod = oid2;
5022         accessDescription[1].AccessLocation.dwAltNameChoice =
5023          CERT_ALT_NAME_IP_ADDRESS;
5024         U(accessDescription[1].AccessLocation).IPAddress.cbData =
5025          sizeof(encodedIPAddr);
5026         U(accessDescription[1].AccessLocation).IPAddress.pbData =
5027          (LPBYTE)encodedIPAddr;
5028         aia.cAccDescr = 2;
5029         aia.rgAccDescr = accessDescription;
5030         compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5031          (CERT_AUTHORITY_INFO_ACCESS *)buf);
5032         LocalFree(buf);
5033         buf = NULL;
5034     }
5035 }
5036
5037 static const BYTE emptyCTL[] = {
5038 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5039 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5040 static const BYTE emptyCTLWithVersion1[] = {
5041 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5042 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5043 static const BYTE ctlWithUsageIdentifier[] = {
5044 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5045 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5046 static const BYTE ctlWithListIdentifier[] = {
5047 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5048 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5049 static const BYTE ctlWithSequenceNumber[] = {
5050 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5051 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5052 static const BYTE ctlWithThisUpdate[] = {
5053 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5054 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5055 static const BYTE ctlWithThisAndNextUpdate[] = {
5056 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5057 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5058 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5059 static const BYTE ctlWithAlgId[] = {
5060 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5061 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5062 static const BYTE ctlWithBogusEntry[] = {
5063 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5064 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5065 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5066 static const BYTE ctlWithOneEntry[] = {
5067 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5068 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5069 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5070 static const BYTE ctlWithTwoEntries[] = {
5071 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5072 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5073 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5074 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5075 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5076
5077 static void test_encodeCTL(DWORD dwEncoding)
5078 {
5079     static char oid1[] = "1.2.3";
5080     static char oid2[] = "1.5.6";
5081     char *pOid1 = oid1;
5082     BOOL ret;
5083     BYTE *buf = NULL;
5084     DWORD size = 0;
5085     CTL_INFO info;
5086     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5087     CTL_ENTRY ctlEntry[2];
5088     CRYPT_ATTRIBUTE attr1, attr2;
5089     CRYPT_ATTR_BLOB value1, value2;
5090
5091     memset(&info, 0, sizeof(info));
5092     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5093      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5094     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5095     if (buf)
5096     {
5097         ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5098         ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5099         LocalFree(buf);
5100         buf = NULL;
5101     }
5102     info.dwVersion = 1;
5103     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5104      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5105     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5106     if (buf)
5107     {
5108         ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5109         ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5110         LocalFree(buf);
5111         buf = NULL;
5112     }
5113     info.dwVersion = 0;
5114     info.SubjectUsage.cUsageIdentifier = 1;
5115     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5116     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5117      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5118     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5119     if (buf)
5120     {
5121         ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5122          size);
5123         ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5124         LocalFree(buf);
5125         buf = NULL;
5126     }
5127     info.SubjectUsage.cUsageIdentifier = 0;
5128     info.ListIdentifier.cbData = sizeof(serialNum);
5129     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5130     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5131      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5132     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5133     if (buf)
5134     {
5135         ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5136         ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5137         LocalFree(buf);
5138         buf = NULL;
5139     }
5140     info.ListIdentifier.cbData = 0;
5141     info.SequenceNumber.cbData = sizeof(serialNum);
5142     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5143     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5144      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5145     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5146     if (buf)
5147     {
5148         ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5149          size);
5150         ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5151         LocalFree(buf);
5152         buf = NULL;
5153     }
5154     info.SequenceNumber.cbData = 0;
5155     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5156     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5157      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5158     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5159     if (buf)
5160     {
5161         ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5162         ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5163         LocalFree(buf);
5164         buf = NULL;
5165     }
5166     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5167     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5168      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5169     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5170     if (buf)
5171     {
5172         ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5173          size);
5174         ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5175         LocalFree(buf);
5176         buf = NULL;
5177     }
5178     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5179     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5180     info.SubjectAlgorithm.pszObjId = oid2;
5181     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5182      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5183     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5184     if (buf)
5185     {
5186         ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5187         ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5188         LocalFree(buf);
5189         buf = NULL;
5190     }
5191     /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5192      * (see tests below) but it'll encode fine.
5193      */
5194     info.SubjectAlgorithm.pszObjId = NULL;
5195     value1.cbData = sizeof(serialNum);
5196     value1.pbData = (LPBYTE)serialNum;
5197     attr1.pszObjId = oid1;
5198     attr1.cValue = 1;
5199     attr1.rgValue = &value1;
5200     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5201     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5202     ctlEntry[0].cAttribute = 1;
5203     ctlEntry[0].rgAttribute = &attr1;
5204     info.cCTLEntry = 1;
5205     info.rgCTLEntry = ctlEntry;
5206     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5207      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5208     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5209     if (buf)
5210     {
5211         ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5212         ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5213         LocalFree(buf);
5214         buf = NULL;
5215     }
5216     value1.cbData = sizeof(emptySequence);
5217     value1.pbData = (LPBYTE)emptySequence;
5218     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5219      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5220     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5221     if (buf)
5222     {
5223         ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5224         ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5225         LocalFree(buf);
5226         buf = NULL;
5227     }
5228     value2.cbData = sizeof(encodedIPAddr);
5229     value2.pbData = (LPBYTE)encodedIPAddr;
5230     attr2.pszObjId = oid2;
5231     attr2.cValue = 1;
5232     attr2.rgValue = &value2;
5233     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5234     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5235     ctlEntry[1].cAttribute = 1;
5236     ctlEntry[1].rgAttribute = &attr2;
5237     info.cCTLEntry = 2;
5238     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5239      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5240     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5241     if (buf)
5242     {
5243         ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5244         ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5245         LocalFree(buf);
5246         buf = NULL;
5247     }
5248 }
5249
5250 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5251  const CTL_INFO *got)
5252 {
5253     DWORD i, j, k;
5254
5255     ok(expected->dwVersion == got->dwVersion,
5256      "%s: expected version %d, got %d\n", header, expected->dwVersion,
5257      got->dwVersion);
5258     ok(expected->SubjectUsage.cUsageIdentifier ==
5259      got->SubjectUsage.cUsageIdentifier,
5260      "%s: expected %d usage identifiers, got %d\n", header,
5261      expected->SubjectUsage.cUsageIdentifier,
5262      got->SubjectUsage.cUsageIdentifier);
5263     for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5264         ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5265          got->SubjectUsage.rgpszUsageIdentifier[i]),
5266          "%s[%d]: expected %s, got %s\n", header, i,
5267          expected->SubjectUsage.rgpszUsageIdentifier[i],
5268          got->SubjectUsage.rgpszUsageIdentifier[i]);
5269     ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5270      "%s: expected list identifier of %d bytes, got %d\n", header,
5271      expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5272     if (expected->ListIdentifier.cbData)
5273         ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5274          expected->ListIdentifier.cbData),
5275          "%s: unexpected list identifier value\n", header);
5276     ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5277      "%s: expected sequence number of %d bytes, got %d\n", header,
5278      expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5279     if (expected->SequenceNumber.cbData)
5280         ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5281          expected->SequenceNumber.cbData),
5282          "%s: unexpected sequence number value\n", header);
5283     ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5284      "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5285      expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5286      got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5287     ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5288      "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5289      expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5290      got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5291     if (expected->SubjectAlgorithm.pszObjId &&
5292      *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5293         ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5294          expected->SubjectAlgorithm.pszObjId);
5295     if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5296         ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5297          got->SubjectAlgorithm.pszObjId),
5298          "%s: expected subject algorithm %s, got %s\n", header,
5299          expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5300     ok(expected->SubjectAlgorithm.Parameters.cbData ==
5301      got->SubjectAlgorithm.Parameters.cbData,
5302      "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5303      expected->SubjectAlgorithm.Parameters.cbData,
5304      got->SubjectAlgorithm.Parameters.cbData);
5305     if (expected->SubjectAlgorithm.Parameters.cbData)
5306         ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5307          got->SubjectAlgorithm.Parameters.pbData,
5308          expected->SubjectAlgorithm.Parameters.cbData),
5309          "%s: unexpected subject algorithm parameter value\n", header);
5310     ok(expected->cCTLEntry == got->cCTLEntry,
5311      "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5312      got->cCTLEntry);
5313     for (i = 0; i < expected->cCTLEntry; i++)
5314     {
5315         ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5316          got->rgCTLEntry[i].SubjectIdentifier.cbData,
5317          "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5318          header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5319          got->rgCTLEntry[i].SubjectIdentifier.cbData);
5320         if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5321             ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5322              got->rgCTLEntry[i].SubjectIdentifier.pbData,
5323              expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5324              "%s[%d]: unexpected subject identifier value\n",
5325              header, i);
5326         for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5327         {
5328             ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5329              got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5330              "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5331              expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5332              got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5333             for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5334             {
5335                 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5336                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5337                  "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5338                  header, i, j, k,
5339                  expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5340                  got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5341                 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5342                     ok(!memcmp(
5343                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5344                      got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5345                      expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5346                      "%s[%d][%d][%d]: unexpected value\n",
5347                      header, i, j, k);
5348             }
5349         }
5350     }
5351     ok(expected->cExtension == got->cExtension,
5352      "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5353      got->cExtension);
5354     for (i = 0; i < expected->cExtension; i++)
5355     {
5356         ok(!strcmp(expected->rgExtension[i].pszObjId,
5357          got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5358          header, i, expected->rgExtension[i].pszObjId,
5359          got->rgExtension[i].pszObjId);
5360         ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5361          "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5362          expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5363         ok(expected->rgExtension[i].Value.cbData ==
5364          got->rgExtension[i].Value.cbData,
5365          "%s[%d]: expected extension value to have %d bytes, got %d\n",
5366          header, i, expected->rgExtension[i].Value.cbData,
5367          got->rgExtension[i].Value.cbData);
5368         if (expected->rgExtension[i].Value.cbData)
5369             ok(!memcmp(expected->rgExtension[i].Value.pbData,
5370              got->rgExtension[i].Value.pbData,
5371              expected->rgExtension[i].Value.cbData),
5372              "%s[%d]: unexpected extension value\n", header, i);
5373     }
5374 }
5375
5376 static const BYTE signedCTL[] = {
5377 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5378 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5379 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5380 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5381 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5382 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5383 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5384 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5385 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5386 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5387 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5388 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5389 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5390 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5391 static const BYTE signedCTLWithCTLInnerContent[] = {
5392 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5393 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5394 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5395 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5396 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5397 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5398 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5399 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5400 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5401 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5402 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5403 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5404 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5405 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5406 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5407 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5408 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5409 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5410 0x57,0x6c,0x0b,0x47,0xb8 };
5411
5412 static void test_decodeCTL(DWORD dwEncoding)
5413 {
5414     static char oid1[] = "1.2.3";
5415     static char oid2[] = "1.5.6";
5416     static BYTE nullData[] = { 5,0 };
5417     char *pOid1 = oid1;
5418     BOOL ret;
5419     BYTE *buf = NULL;
5420     DWORD size = 0;
5421     CTL_INFO info;
5422     SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5423     CTL_ENTRY ctlEntry[2];
5424     CRYPT_ATTRIBUTE attr1, attr2;
5425     CRYPT_ATTR_BLOB value1, value2;
5426
5427     memset(&info, 0, sizeof(info));
5428     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5429      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5430     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5431     if (buf)
5432     {
5433         compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5434         LocalFree(buf);
5435         buf = NULL;
5436     }
5437     info.dwVersion = 1;
5438     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5439      sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
5440      &size);
5441     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5442     if (buf)
5443     {
5444         compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5445         LocalFree(buf);
5446         buf = NULL;
5447     }
5448     info.dwVersion = 0;
5449     info.SubjectUsage.cUsageIdentifier = 1;
5450     info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5451     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5452      sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5453      (BYTE *)&buf, &size);
5454     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5455     if (buf)
5456     {
5457         compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5458         LocalFree(buf);
5459         buf = NULL;
5460     }
5461     info.SubjectUsage.cUsageIdentifier = 0;
5462     info.ListIdentifier.cbData = sizeof(serialNum);
5463     info.ListIdentifier.pbData = (LPBYTE)serialNum;
5464     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5465      sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5466      (BYTE *)&buf, &size);
5467     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5468     if (buf)
5469     {
5470         compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5471         LocalFree(buf);
5472         buf = NULL;
5473     }
5474     info.ListIdentifier.cbData = 0;
5475     info.SequenceNumber.cbData = sizeof(serialNum);
5476     info.SequenceNumber.pbData = (LPBYTE)serialNum;
5477     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5478      sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL,
5479      (BYTE *)&buf, &size);
5480     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5481     if (buf)
5482     {
5483         compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5484         LocalFree(buf);
5485         buf = NULL;
5486     }
5487     info.SequenceNumber.cbData = 0;
5488     SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5489     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5490      sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5491      (BYTE *)&buf, &size);
5492     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5493     if (buf)
5494     {
5495         compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5496         LocalFree(buf);
5497         buf = NULL;
5498     }
5499     SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5500     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5501      sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5502      (BYTE *)&buf, &size);
5503     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5504     if (buf)
5505     {
5506         compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5507         LocalFree(buf);
5508         buf = NULL;
5509     }
5510     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5511     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5512     info.SubjectAlgorithm.pszObjId = oid2;
5513     info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5514     info.SubjectAlgorithm.Parameters.pbData = nullData;
5515     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5516      sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL,
5517      (BYTE *)&buf, &size);
5518     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5519     if (buf)
5520     {
5521         compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5522         LocalFree(buf);
5523         buf = NULL;
5524     }
5525     SetLastError(0xdeadbeef);
5526     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5527      sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5528      (BYTE *)&buf, &size);
5529     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || CRYPT_E_ASN1_CORRUPT),
5530      "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5531      GetLastError());
5532     info.SubjectAlgorithm.Parameters.cbData = 0;
5533     info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5534     info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5535     info.SubjectAlgorithm.pszObjId = oid2;
5536     info.SubjectAlgorithm.pszObjId = NULL;
5537     value1.cbData = sizeof(emptySequence);
5538     value1.pbData = (LPBYTE)emptySequence;
5539     attr1.pszObjId = oid1;
5540     attr1.cValue = 1;
5541     attr1.rgValue = &value1;
5542     ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5543     ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5544     ctlEntry[0].cAttribute = 1;
5545     ctlEntry[0].rgAttribute = &attr1;
5546     info.cCTLEntry = 1;
5547     info.rgCTLEntry = ctlEntry;
5548     SetLastError(0xdeadbeef);
5549     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5550      sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5551      (BYTE *)&buf, &size);
5552     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5553     if (buf)
5554     {
5555         compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5556         LocalFree(buf);
5557         buf = NULL;
5558     }
5559     value2.cbData = sizeof(encodedIPAddr);
5560     value2.pbData = (LPBYTE)encodedIPAddr;
5561     attr2.pszObjId = oid2;
5562     attr2.cValue = 1;
5563     attr2.rgValue = &value2;
5564     ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5565     ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5566     ctlEntry[1].cAttribute = 1;
5567     ctlEntry[1].rgAttribute = &attr2;
5568     info.cCTLEntry = 2;
5569     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5570      sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL,
5571      (BYTE *)&buf, &size);
5572     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5573     if (buf)
5574     {
5575         compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5576         LocalFree(buf);
5577         buf = NULL;
5578     }
5579     /* A signed CTL isn't decodable, even if the inner content is a CTL */
5580     SetLastError(0xdeadbeef);
5581     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5582      sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5583     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5584      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5585      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5586      GetLastError());
5587     SetLastError(0xdeadbeef);
5588     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5589      signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5590      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5591     ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5592      GetLastError() == OSS_DATA_ERROR /* Win9x */),
5593      "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5594      GetLastError());
5595 }
5596
5597 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5598 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5599  0x03,0,0,0,0,0,0 };
5600 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5601  0xa0,0x01,0x01 };
5602 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5603  0x03,0x02,0x01,0x01 };
5604 static BYTE bogusDER[] = { 1 };
5605
5606 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5607 {
5608     BOOL ret;
5609     BYTE *buf = NULL;
5610     DWORD size = 0;
5611     CRYPT_CONTENT_INFO info = { 0 };
5612     char oid1[] = "1.2.3";
5613
5614     if (0)
5615     {
5616         /* Crashes on win9x */
5617         SetLastError(0xdeadbeef);
5618         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5619          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5620         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5621          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5622     }
5623     SetLastError(0xdeadbeef);
5624     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5625      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5626     ok(!ret && (GetLastError() == E_INVALIDARG ||
5627      GetLastError() == OSS_LIMITED /* Win9x */),
5628      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5629     info.pszObjId = oid1;
5630     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5631      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5632     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5633     if (buf)
5634     {
5635         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5636         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5637         LocalFree(buf);
5638     }
5639     info.Content.pbData = bogusDER;
5640     info.Content.cbData = sizeof(bogusDER);
5641     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5642      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5643     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5644     if (buf)
5645     {
5646         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5647         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5648         LocalFree(buf);
5649     }
5650     info.Content.pbData = (BYTE *)ints[0].encoded;
5651     info.Content.cbData = ints[0].encoded[1] + 2;
5652     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5653      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5654     if (buf)
5655     {
5656         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5657         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5658         LocalFree(buf);
5659     }
5660 }
5661
5662 static const BYTE indefiniteSignedPKCSContent[] = {
5663 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5664 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5665 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5666 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5667 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5668 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5669 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5670 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5671 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5672 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5673 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5674 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5675 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5676 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5677 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5678 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5679 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5680 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5681 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5682 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5683 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5684 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5685 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5686 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5687 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5688 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5689 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5690 0x00,0x00,0x00,0x00,0x00,0x00 };
5691
5692 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5693 {
5694     BOOL ret;
5695     LPBYTE buf = NULL;
5696     DWORD size = 0;
5697     CRYPT_CONTENT_INFO *info;
5698
5699     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5700      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5701      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5702     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5703     if (buf)
5704     {
5705         info = (CRYPT_CONTENT_INFO *)buf;
5706
5707         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5708          info->pszObjId);
5709         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5710          info->Content.cbData);
5711         LocalFree(buf);
5712     }
5713     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5714      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5715      0, NULL, NULL, &size);
5716     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5717     SetLastError(0xdeadbeef);
5718     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5719      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5720      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5721     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5722      * I doubt an app depends on that.
5723      */
5724     ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5725      GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5726      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5727      GetLastError());
5728     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5729      intPKCSContentInfo, sizeof(intPKCSContentInfo),
5730      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5731     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5732     if (buf)
5733     {
5734         info = (CRYPT_CONTENT_INFO *)buf;
5735
5736         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5737          info->pszObjId);
5738         ok(info->Content.cbData == ints[0].encoded[1] + 2,
5739          "Unexpected size %d\n", info->Content.cbData);
5740         ok(!memcmp(info->Content.pbData, ints[0].encoded,
5741          info->Content.cbData), "Unexpected value\n");
5742         LocalFree(buf);
5743     }
5744     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5745      indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5746      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5747     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5748     if (buf)
5749     {
5750         info = (CRYPT_CONTENT_INFO *)buf;
5751
5752         ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5753          "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5754         ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5755          info->Content.cbData);
5756         LocalFree(buf);
5757     }
5758 }
5759
5760 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5761  0x00 };
5762 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5763  0x01 };
5764 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5765  0x02,0x01,0x01 };
5766
5767 static void test_encodePKCSAttribute(DWORD dwEncoding)
5768 {
5769     CRYPT_ATTRIBUTE attr = { 0 };
5770     BOOL ret;
5771     LPBYTE buf = NULL;
5772     DWORD size = 0;
5773     CRYPT_ATTR_BLOB blob;
5774     char oid[] = "1.2.3";
5775
5776     if (0)
5777     {
5778         /* Crashes on win9x */
5779         SetLastError(0xdeadbeef);
5780         ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5781          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5782         ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5783          "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5784     }
5785     SetLastError(0xdeadbeef);
5786     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5787      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5788     ok(!ret && (GetLastError() == E_INVALIDARG ||
5789      GetLastError() == OSS_LIMITED /* Win9x */),
5790      "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5791     attr.pszObjId = oid;
5792     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5793      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5794     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5795     if (buf)
5796     {
5797         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5798         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5799         LocalFree(buf);
5800     }
5801     blob.cbData = sizeof(bogusDER);
5802     blob.pbData = bogusDER;
5803     attr.cValue = 1;
5804     attr.rgValue = &blob;
5805     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5806      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5807     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5808     if (buf)
5809     {
5810         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5811         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5812         LocalFree(buf);
5813     }
5814     blob.pbData = (BYTE *)ints[0].encoded;
5815     blob.cbData = ints[0].encoded[1] + 2;
5816     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5817      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5818     if (buf)
5819     {
5820         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5821         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5822         LocalFree(buf);
5823     }
5824 }
5825
5826 static void test_decodePKCSAttribute(DWORD dwEncoding)
5827 {
5828     BOOL ret;
5829     LPBYTE buf = NULL;
5830     DWORD size = 0;
5831     CRYPT_ATTRIBUTE *attr;
5832
5833     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5834      emptyPKCSAttr, sizeof(emptyPKCSAttr),
5835      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5836     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5837     if (buf)
5838     {
5839         attr = (CRYPT_ATTRIBUTE *)buf;
5840
5841         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5842          attr->pszObjId);
5843         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5844         LocalFree(buf);
5845     }
5846     SetLastError(0xdeadbeef);
5847     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5848      bogusPKCSAttr, sizeof(bogusPKCSAttr),
5849      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5850     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5851      * I doubt an app depends on that.
5852      */
5853     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5854      GetLastError() == CRYPT_E_ASN1_CORRUPT || OSS_MORE_INPUT /* Win9x */),
5855      "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
5856      GetLastError());
5857     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5858      intPKCSAttr, sizeof(intPKCSAttr),
5859      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5860     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5861     if (buf)
5862     {
5863         attr = (CRYPT_ATTRIBUTE *)buf;
5864
5865         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5866          attr->pszObjId);
5867         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5868         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5869          "Unexpected size %d\n", attr->rgValue[0].cbData);
5870         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5871          attr->rgValue[0].cbData), "Unexpected value\n");
5872         LocalFree(buf);
5873     }
5874 }
5875
5876 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5877 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5878  0x2a,0x03,0x31,0x00 };
5879 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5880  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5881
5882 static void test_encodePKCSAttributes(DWORD dwEncoding)
5883 {
5884     CRYPT_ATTRIBUTES attributes = { 0 };
5885     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5886     CRYPT_ATTR_BLOB blob;
5887     BOOL ret;
5888     LPBYTE buf = NULL;
5889     DWORD size = 0;
5890     char oid1[] = "1.2.3", oid2[] = "1.5.6";
5891
5892     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5893      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5894     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5895     if (buf)
5896     {
5897         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5898         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5899         LocalFree(buf);
5900     }
5901     attributes.cAttr = 1;
5902     attributes.rgAttr = attr;
5903     SetLastError(0xdeadbeef);
5904     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5905      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5906     ok(!ret && (GetLastError() == E_INVALIDARG ||
5907      GetLastError() == OSS_LIMITED /* Win9x */),
5908      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5909     attr[0].pszObjId = oid1;
5910     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5911      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5912     if (buf)
5913     {
5914         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5915         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5916         LocalFree(buf);
5917     }
5918     attr[1].pszObjId = oid2;
5919     attr[1].cValue = 1;
5920     attr[1].rgValue = &blob;
5921     blob.pbData = (BYTE *)ints[0].encoded;
5922     blob.cbData = ints[0].encoded[1] + 2;
5923     attributes.cAttr = 2;
5924     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5925      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5926     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5927     if (buf)
5928     {
5929         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5930         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5931         LocalFree(buf);
5932     }
5933 }
5934
5935 static void test_decodePKCSAttributes(DWORD dwEncoding)
5936 {
5937     BOOL ret;
5938     LPBYTE buf = NULL;
5939     DWORD size = 0;
5940     CRYPT_ATTRIBUTES *attributes;
5941
5942     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5943      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5944      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5945     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5946     if (buf)
5947     {
5948         attributes = (CRYPT_ATTRIBUTES *)buf;
5949         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5950          attributes->cAttr);
5951         LocalFree(buf);
5952     }
5953     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5954      singlePKCSAttributes, sizeof(singlePKCSAttributes),
5955      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5956     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5957     if (buf)
5958     {
5959         attributes = (CRYPT_ATTRIBUTES *)buf;
5960         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5961          attributes->cAttr);
5962         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5963          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5964         ok(attributes->rgAttr[0].cValue == 0,
5965          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5966         LocalFree(buf);
5967     }
5968     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5969      doublePKCSAttributes, sizeof(doublePKCSAttributes),
5970      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5971     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5972     if (buf)
5973     {
5974         attributes = (CRYPT_ATTRIBUTES *)buf;
5975         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5976          attributes->cAttr);
5977         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5978          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5979         ok(attributes->rgAttr[0].cValue == 0,
5980          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5981         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5982          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5983         ok(attributes->rgAttr[1].cValue == 1,
5984          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5985         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5986          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5987         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5988          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5989         LocalFree(buf);
5990     }
5991 }
5992
5993 static const BYTE singleCapability[] = {
5994 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5995 static const BYTE twoCapabilities[] = {
5996 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5997 static const BYTE singleCapabilitywithNULL[] = {
5998 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5999
6000 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6001 {
6002     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6003     BOOL ret;
6004     LPBYTE buf = NULL;
6005     DWORD size = 0;
6006     CRYPT_SMIME_CAPABILITY capability[2];
6007     CRYPT_SMIME_CAPABILITIES capabilities;
6008
6009     /* An empty capabilities is allowed */
6010     capabilities.cCapability = 0;
6011     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6012      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6013     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6014     if (buf)
6015     {
6016         ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6017         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6018         LocalFree(buf);
6019     }
6020     /* A non-empty capabilities with an empty capability (lacking an OID) is
6021      * not allowed
6022      */
6023     capability[0].pszObjId = NULL;
6024     capability[0].Parameters.cbData = 0;
6025     capabilities.cCapability = 1;
6026     capabilities.rgCapability = capability;
6027     SetLastError(0xdeadbeef);
6028     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6029      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6030     ok(!ret && (GetLastError() == E_INVALIDARG ||
6031      GetLastError() == OSS_LIMITED /* Win9x */),
6032      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6033     capability[0].pszObjId = oid1;
6034     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6035      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6036     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6037     if (buf)
6038     {
6039         ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6040         ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6041         LocalFree(buf);
6042     }
6043     capability[1].pszObjId = oid2;
6044     capability[1].Parameters.cbData = 0;
6045     capabilities.cCapability = 2;
6046     ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6047      &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6048     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6049     if (buf)
6050     {
6051         ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6052         ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6053         LocalFree(buf);
6054     }
6055 }
6056
6057 static void compareSMimeCapabilities(LPCSTR header,
6058  const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6059 {
6060     DWORD i;
6061
6062     ok(got->cCapability == expected->cCapability,
6063      "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6064      got->cCapability);
6065     for (i = 0; i < expected->cCapability; i++)
6066     {
6067         ok(!strcmp(expected->rgCapability[i].pszObjId,
6068          got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6069          header, i, expected->rgCapability[i].pszObjId,
6070          got->rgCapability[i].pszObjId);
6071         ok(expected->rgCapability[i].Parameters.cbData ==
6072          got->rgCapability[i].Parameters.cbData,
6073          "%s[%d]: expected %d bytes, got %d\n", header, i,
6074          expected->rgCapability[i].Parameters.cbData,
6075          got->rgCapability[i].Parameters.cbData);
6076         if (expected->rgCapability[i].Parameters.cbData)
6077             ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6078              got->rgCapability[i].Parameters.pbData,
6079              expected->rgCapability[i].Parameters.cbData),
6080              "%s[%d]: unexpected value\n", header, i);
6081     }
6082 }
6083
6084 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6085 {
6086     static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6087     BOOL ret;
6088     DWORD size = 0;
6089     CRYPT_SMIME_CAPABILITY capability[2];
6090     CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6091
6092     SetLastError(0xdeadbeef);
6093     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6094      emptySequence, sizeof(emptySequence),
6095      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6096     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6097     if (ret)
6098     {
6099         capabilities.cCapability = 0;
6100         compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6101         LocalFree(ptr);
6102     }
6103     SetLastError(0xdeadbeef);
6104     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6105      singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6106      (BYTE *)&ptr, &size);
6107     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6108     if (ret)
6109     {
6110         capability[0].pszObjId = oid1;
6111         capability[0].Parameters.cbData = 0;
6112         capabilities.cCapability = 1;
6113         capabilities.rgCapability = capability;
6114         compareSMimeCapabilities("single capability", &capabilities, ptr);
6115         LocalFree(ptr);
6116     }
6117     SetLastError(0xdeadbeef);
6118     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6119      singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6120      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
6121     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6122     if (ret)
6123     {
6124         BYTE NULLparam[] = {0x05, 0x00};
6125         capability[0].pszObjId = oid1;
6126         capability[0].Parameters.cbData = 2;
6127         capability[0].Parameters.pbData = NULLparam;
6128         capabilities.cCapability = 1;
6129         capabilities.rgCapability = capability;
6130         compareSMimeCapabilities("single capability with NULL", &capabilities,
6131          ptr);
6132         LocalFree(ptr);
6133     }
6134     SetLastError(0xdeadbeef);
6135     ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6136     twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6137     (BYTE *)&ptr, &size);
6138     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6139     if (ret)
6140     {
6141         capability[0].Parameters.cbData = 0;
6142         capability[1].pszObjId = oid2;
6143         capability[1].Parameters.cbData = 0;
6144         capabilities.cCapability = 2;
6145         compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6146         LocalFree(ptr);
6147     }
6148 }
6149
6150 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6151  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6152  0x67 };
6153 static const BYTE minimalPKCSSigner[] = {
6154  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6155  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6156  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6157 static const BYTE PKCSSignerWithSerial[] = {
6158  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6159  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6160  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6161  0x00 };
6162 static const BYTE PKCSSignerWithHashAlgo[] = {
6163  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6164  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6165  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6166  0x00,0x04,0x00 };
6167 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6168  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6169  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6170  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6171  0x06,0x05,0x00,0x04,0x00 };
6172 static const BYTE PKCSSignerWithHash[] = {
6173  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6174  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6175  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6176  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6177  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6178 static const BYTE PKCSSignerWithAuthAttr[] = {
6179 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6180 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6181 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6182 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6183 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6184 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6185 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6186
6187 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6188 {
6189     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6190     BOOL ret;
6191     LPBYTE buf = NULL;
6192     DWORD size = 0;
6193     CMSG_SIGNER_INFO info = { 0 };
6194     char oid_common_name[] = szOID_COMMON_NAME;
6195     CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6196      (LPBYTE)encodedCommonName };
6197     CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6198
6199     SetLastError(0xdeadbeef);
6200     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6201      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6202     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6203     {
6204         skip("no PKCS7_SIGNER_INFO encode support\n");
6205         return;
6206     }
6207     ok(!ret && (GetLastError() == E_INVALIDARG ||
6208      GetLastError() == OSS_LIMITED /* Win9x */),
6209      "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6210     /* To be encoded, a signer must have an issuer at least, and the encoding
6211      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
6212      * see decoding tests.)
6213      */
6214     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6215     info.Issuer.pbData = encodedCommonNameNoNull;
6216     SetLastError(0xdeadbeef);
6217     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6218      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6219     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6220         ok(!ret && GetLastError() == E_INVALIDARG,
6221          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6222     else
6223     {
6224         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6225          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6226         if (buf)
6227         {
6228             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6229             if (size == sizeof(minimalPKCSSigner))
6230                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6231             else
6232                 ok(0, "Unexpected value\n");
6233             LocalFree(buf);
6234         }
6235     }
6236     info.SerialNumber.cbData = sizeof(serialNum);
6237     info.SerialNumber.pbData = (BYTE *)serialNum;
6238     SetLastError(0xdeadbeef);
6239     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6240      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6241     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6242         ok(!ret && GetLastError() == E_INVALIDARG,
6243          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6244     else
6245     {
6246         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6247          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6248         if (buf)
6249         {
6250             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6251              size);
6252             if (size == sizeof(PKCSSignerWithSerial))
6253                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6254                  "Unexpected value\n");
6255             else
6256                 ok(0, "Unexpected value\n");
6257             LocalFree(buf);
6258         }
6259     }
6260     info.HashAlgorithm.pszObjId = oid1;
6261     SetLastError(0xdeadbeef);
6262     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6263      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6264     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6265         ok(!ret && GetLastError() == E_INVALIDARG,
6266          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6267     else
6268     {
6269         ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6270          "CryptEncodeObjectEx failed: %x\n", GetLastError());
6271         if (buf)
6272         {
6273             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6274              size);
6275             if (size == sizeof(PKCSSignerWithHashAlgo))
6276                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6277                  "Unexpected value\n");
6278             else
6279                 ok(0, "Unexpected value\n");
6280             LocalFree(buf);
6281         }
6282     }
6283     info.HashEncryptionAlgorithm.pszObjId = oid2;
6284     SetLastError(0xdeadbeef);
6285     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6286      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6287     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6288         ok(!ret && GetLastError() == E_INVALIDARG,
6289          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6290     else
6291     {
6292         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6293         if (buf)
6294         {
6295             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6296              "Unexpected size %d\n", size);
6297             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6298                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6299                  "Unexpected value\n");
6300             else
6301                 ok(0, "Unexpected value\n");
6302             LocalFree(buf);
6303         }
6304     }
6305     info.EncryptedHash.cbData = sizeof(hash);
6306     info.EncryptedHash.pbData = (BYTE *)hash;
6307     SetLastError(0xdeadbeef);
6308     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6309      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6310     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6311         ok(!ret && GetLastError() == E_INVALIDARG,
6312          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6313     else
6314     {
6315         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6316         if (buf)
6317         {
6318             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6319              size);
6320             if (size == sizeof(PKCSSignerWithHash))
6321                 ok(!memcmp(buf, PKCSSignerWithHash, size),
6322                  "Unexpected value\n");
6323             else
6324                 ok(0, "Unexpected value\n");
6325             LocalFree(buf);
6326         }
6327     }
6328     info.AuthAttrs.cAttr = 1;
6329     info.AuthAttrs.rgAttr = &attr;
6330     SetLastError(0xdeadbeef);
6331     ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6332      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6333     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6334         ok(!ret && GetLastError() == E_INVALIDARG,
6335          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6336     else
6337     {
6338         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6339         if (buf)
6340         {
6341             ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6342              size);
6343             if (size == sizeof(PKCSSignerWithAuthAttr))
6344                 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6345                  "Unexpected value\n");
6346             else
6347                 ok(0, "Unexpected value\n");
6348             LocalFree(buf);
6349         }
6350     }
6351 }
6352
6353 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6354 {
6355     BOOL ret;
6356     LPBYTE buf = NULL;
6357     DWORD size = 0;
6358     CMSG_SIGNER_INFO *info;
6359
6360     /* A PKCS signer can't be decoded without a serial number. */
6361     SetLastError(0xdeadbeef);
6362     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6363      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6364      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6365     ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6366      GetLastError() == OSS_DATA_ERROR /* Win9x */),
6367      "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6368      GetLastError());
6369     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6370      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6371      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6372     ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6373      "CryptDecodeObjectEx failed: %x\n", GetLastError());
6374     if (buf)
6375     {
6376         info = (CMSG_SIGNER_INFO *)buf;
6377         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6378          info->dwVersion);
6379         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6380          "Unexpected size %d\n", info->Issuer.cbData);
6381         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6382          info->Issuer.cbData), "Unexpected value\n");
6383         ok(info->SerialNumber.cbData == sizeof(serialNum),
6384          "Unexpected size %d\n", info->SerialNumber.cbData);
6385         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6386          "Unexpected value\n");
6387         LocalFree(buf);
6388     }
6389     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6390      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6391      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6392     if (buf)
6393     {
6394         info = (CMSG_SIGNER_INFO *)buf;
6395         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6396          info->dwVersion);
6397         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6398          "Unexpected size %d\n", info->Issuer.cbData);
6399         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6400          info->Issuer.cbData), "Unexpected value\n");
6401         ok(info->SerialNumber.cbData == sizeof(serialNum),
6402          "Unexpected size %d\n", info->SerialNumber.cbData);
6403         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6404          "Unexpected value\n");
6405         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6406          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6407         LocalFree(buf);
6408     }
6409     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6410      PKCSSignerWithHashAndEncryptionAlgo,
6411      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6412      NULL, (BYTE *)&buf, &size);
6413     if (buf)
6414     {
6415         info = (CMSG_SIGNER_INFO *)buf;
6416         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6417          info->dwVersion);
6418         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6419          "Unexpected size %d\n", info->Issuer.cbData);
6420         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6421          info->Issuer.cbData), "Unexpected value\n");
6422         ok(info->SerialNumber.cbData == sizeof(serialNum),
6423          "Unexpected size %d\n", info->SerialNumber.cbData);
6424         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6425          "Unexpected value\n");
6426         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6427          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6428         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6429          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6430         LocalFree(buf);
6431     }
6432     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6433      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6434      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6435     if (buf)
6436     {
6437         info = (CMSG_SIGNER_INFO *)buf;
6438         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6439          info->dwVersion);
6440         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6441          "Unexpected size %d\n", info->Issuer.cbData);
6442         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6443          info->Issuer.cbData), "Unexpected value\n");
6444         ok(info->SerialNumber.cbData == sizeof(serialNum),
6445          "Unexpected size %d\n", info->SerialNumber.cbData);
6446         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6447          "Unexpected value\n");
6448         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6449          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6450         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6451          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6452         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6453          info->EncryptedHash.cbData);
6454         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6455          "Unexpected value\n");
6456         LocalFree(buf);
6457     }
6458     ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6459      PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6460      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6461     if (buf)
6462     {
6463         info = (CMSG_SIGNER_INFO *)buf;
6464         ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6465          info->AuthAttrs.cAttr);
6466         ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6467          "Expected %s, got %s\n", szOID_COMMON_NAME,
6468          info->AuthAttrs.rgAttr[0].pszObjId);
6469         ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6470          info->AuthAttrs.rgAttr[0].cValue);
6471         ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6472          sizeof(encodedCommonName), "Unexpected size %d\n",
6473          info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6474         ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6475          encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6476         LocalFree(buf);
6477     }
6478 }
6479
6480 static const BYTE CMSSignerWithKeyId[] = {
6481 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6482 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6483
6484 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6485 {
6486     BOOL ret;
6487     LPBYTE buf = NULL;
6488     DWORD size = 0;
6489     CMSG_CMS_SIGNER_INFO info = { 0 };
6490     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6491
6492     SetLastError(0xdeadbeef);
6493     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6494      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6495     ok(!ret, "Expected failure, got %d\n", ret);
6496     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6497     {
6498         skip("no CMS_SIGNER_INFO encode support\n");
6499         return;
6500     }
6501     ok(GetLastError() == E_INVALIDARG,
6502        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6503     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6504     SetLastError(0xdeadbeef);
6505     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6506      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6507     ok(!ret, "Expected failure, got %d\n", ret);
6508     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6509     {
6510         skip("no CMS_SIGNER_INFO encode support\n");
6511         return;
6512     }
6513     ok(GetLastError() == E_INVALIDARG,
6514        "Expected E_INVALIDARG, got %08x\n", GetLastError());
6515     /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6516      * be a key id or a issuer serial number with at least the issuer set, and
6517      * the encoding must include PKCS_7_ASN_ENCODING.
6518      * (That isn't enough to be decoded, see decoding tests.)
6519      */
6520     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6521      sizeof(encodedCommonNameNoNull);
6522     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6523     SetLastError(0xdeadbeef);
6524     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6525      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6526     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6527         ok(!ret && GetLastError() == E_INVALIDARG,
6528          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6529     else
6530     {
6531         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6532         if (buf)
6533         {
6534             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6535             ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6536             LocalFree(buf);
6537         }
6538     }
6539     U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6540     U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6541     SetLastError(0xdeadbeef);
6542     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6543      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6544     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6545         ok(!ret && GetLastError() == E_INVALIDARG,
6546          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6547     else
6548     {
6549         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6550         if (buf)
6551         {
6552             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6553              size);
6554             ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6555             LocalFree(buf);
6556         }
6557     }
6558     info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6559     U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6560     U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6561     SetLastError(0xdeadbeef);
6562     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6563      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6564     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6565         ok(!ret && GetLastError() == E_INVALIDARG,
6566          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6567     else
6568     {
6569         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6570         if (buf)
6571         {
6572             ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6573              size);
6574             ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6575             LocalFree(buf);
6576         }
6577     }
6578     /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6579      * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6580      * (see RFC 3852, section 5.3.)
6581      */
6582     info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6583     U(info.SignerId).HashId.cbData = sizeof(hash);
6584     U(info.SignerId).HashId.pbData = (BYTE *)hash;
6585     SetLastError(0xdeadbeef);
6586     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6587      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6588     ok(!ret && GetLastError() == E_INVALIDARG,
6589      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6590     /* Now with a hash algo */
6591     info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6592     U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6593      sizeof(encodedCommonNameNoNull);
6594     U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6595     info.HashAlgorithm.pszObjId = oid1;
6596     SetLastError(0xdeadbeef);
6597     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6598      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6599     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6600         ok(!ret && GetLastError() == E_INVALIDARG,
6601          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6602     else
6603     {
6604         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6605         if (buf)
6606         {
6607             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6608              size);
6609             ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6610              "Unexpected value\n");
6611             LocalFree(buf);
6612         }
6613     }
6614     info.HashEncryptionAlgorithm.pszObjId = oid2;
6615     SetLastError(0xdeadbeef);
6616     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6617      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6618     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6619         ok(!ret && GetLastError() == E_INVALIDARG,
6620          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6621     else
6622     {
6623         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6624         if (buf)
6625         {
6626             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6627              "Unexpected size %d\n", size);
6628             ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6629              "Unexpected value\n");
6630             LocalFree(buf);
6631         }
6632     }
6633     info.EncryptedHash.cbData = sizeof(hash);
6634     info.EncryptedHash.pbData = (BYTE *)hash;
6635     SetLastError(0xdeadbeef);
6636     ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6637      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6638     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6639         ok(!ret && GetLastError() == E_INVALIDARG,
6640          "Expected E_INVALIDARG, got %08x\n", GetLastError());
6641     else
6642     {
6643         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6644         if (buf)
6645         {
6646             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6647              size);
6648             ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6649             LocalFree(buf);
6650         }
6651     }
6652 }
6653
6654 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6655 {
6656     BOOL ret;
6657     LPBYTE buf = NULL;
6658     DWORD size = 0;
6659     CMSG_CMS_SIGNER_INFO *info;
6660     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6661
6662     /* A CMS signer can't be decoded without a serial number. */
6663     SetLastError(0xdeadbeef);
6664     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6665      minimalPKCSSigner, sizeof(minimalPKCSSigner),
6666      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6667     ok(!ret, "expected failure\n");
6668     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6669     {
6670         skip("no CMS_SIGNER_INFO decode support\n");
6671         return;
6672     }
6673     ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6674      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6675     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6676      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6677      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6678     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6679     if (buf)
6680     {
6681         info = (CMSG_CMS_SIGNER_INFO *)buf;
6682         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6683          info->dwVersion);
6684         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6685          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6686          info->SignerId.dwIdChoice);
6687         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6688          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6689          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6690         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6691          encodedCommonNameNoNull,
6692          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6693          "Unexpected value\n");
6694         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6695          sizeof(serialNum), "Unexpected size %d\n",
6696          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6697         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6698          serialNum, sizeof(serialNum)), "Unexpected value\n");
6699         LocalFree(buf);
6700     }
6701     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6702      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6703      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6704     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6705     if (buf)
6706     {
6707         info = (CMSG_CMS_SIGNER_INFO *)buf;
6708         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6709          info->dwVersion);
6710         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6711          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6712          info->SignerId.dwIdChoice);
6713         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6714          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6715          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6716         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6717          encodedCommonNameNoNull,
6718          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6719          "Unexpected value\n");
6720         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6721          sizeof(serialNum), "Unexpected size %d\n",
6722          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6723         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6724          serialNum, sizeof(serialNum)), "Unexpected value\n");
6725         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6726          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6727         LocalFree(buf);
6728     }
6729     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6730      PKCSSignerWithHashAndEncryptionAlgo,
6731      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6732      NULL, (BYTE *)&buf, &size);
6733     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6734     if (buf)
6735     {
6736         info = (CMSG_CMS_SIGNER_INFO *)buf;
6737         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6738          info->dwVersion);
6739         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6740          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6741          info->SignerId.dwIdChoice);
6742         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6743          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6744          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6745         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6746          encodedCommonNameNoNull,
6747          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6748          "Unexpected value\n");
6749         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6750          sizeof(serialNum), "Unexpected size %d\n",
6751          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6752         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6753          serialNum, sizeof(serialNum)), "Unexpected value\n");
6754         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6755          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6756         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6757          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6758         LocalFree(buf);
6759     }
6760     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6761      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6762      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6763     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6764     if (buf)
6765     {
6766         info = (CMSG_CMS_SIGNER_INFO *)buf;
6767         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6768          info->dwVersion);
6769         ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6770          "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6771          info->SignerId.dwIdChoice);
6772         ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6773          sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6774          U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6775         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6776          encodedCommonNameNoNull,
6777          U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6778          "Unexpected value\n");
6779         ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6780          sizeof(serialNum), "Unexpected size %d\n",
6781          U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6782         ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6783          serialNum, sizeof(serialNum)), "Unexpected value\n");
6784         ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6785          "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6786         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6787          "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6788         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6789          info->EncryptedHash.cbData);
6790         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6791          "Unexpected value\n");
6792         LocalFree(buf);
6793     }
6794     ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6795      CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6796      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6797     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6798     if (buf)
6799     {
6800         info = (CMSG_CMS_SIGNER_INFO *)buf;
6801         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6802          info->dwVersion);
6803         ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6804          "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6805          info->SignerId.dwIdChoice);
6806         ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6807          "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6808         ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6809          "Unexpected value\n");
6810         LocalFree(buf);
6811     }
6812 }
6813
6814 static BYTE emptyDNSPermittedConstraints[] = {
6815 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6816 static BYTE emptyDNSExcludedConstraints[] = {
6817 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6818 static BYTE DNSExcludedConstraints[] = {
6819 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6820 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6821 static BYTE permittedAndExcludedConstraints[] = {
6822 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6823 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6824 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6825 static BYTE permittedAndExcludedWithMinConstraints[] = {
6826 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6827 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6828 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6829 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6830 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6831 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6832 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6833
6834 static void test_encodeNameConstraints(DWORD dwEncoding)
6835 {
6836     BOOL ret;
6837     CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6838     CERT_GENERAL_SUBTREE permitted = { { 0 } };
6839     CERT_GENERAL_SUBTREE excluded = { { 0 } };
6840     LPBYTE buf;
6841     DWORD size;
6842
6843     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6844      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6845     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6846     {
6847         skip("no X509_NAME_CONSTRAINTS encode support\n");
6848         return;
6849     }
6850     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6851     if (ret)
6852     {
6853         ok(size == sizeof(emptySequence), "Unexpected size\n");
6854         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6855         LocalFree(buf);
6856     }
6857     constraints.cPermittedSubtree = 1;
6858     constraints.rgPermittedSubtree = &permitted;
6859     SetLastError(0xdeadbeef);
6860     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6861      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6862     ok(!ret && GetLastError() == E_INVALIDARG,
6863      "Expected E_INVALIDARG, got %08x\n", GetLastError());
6864     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6865     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6866      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6867     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6868     if (ret)
6869     {
6870         ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6871         ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6872          "Unexpected value\n");
6873         LocalFree(buf);
6874     }
6875     constraints.cPermittedSubtree = 0;
6876     constraints.cExcludedSubtree = 1;
6877     constraints.rgExcludedSubtree = &excluded;
6878     excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6879     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6880      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6881     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6882     if (ret)
6883     {
6884         ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6885         ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6886          "Unexpected value\n");
6887         LocalFree(buf);
6888     }
6889     U(excluded.Base).pwszURL = (LPWSTR)url;
6890     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6891      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6892     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6893     if (ret)
6894     {
6895         ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6896         ok(!memcmp(buf, DNSExcludedConstraints, size),
6897          "Unexpected value\n");
6898         LocalFree(buf);
6899     }
6900     permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6901     U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6902     U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6903     constraints.cPermittedSubtree = 1;
6904     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6905      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6906     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6907     if (ret)
6908     {
6909         ok(size == sizeof(permittedAndExcludedConstraints),
6910          "Unexpected size\n");
6911         ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6912          "Unexpected value\n");
6913         LocalFree(buf);
6914     }
6915     permitted.dwMinimum = 5;
6916     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6917      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6918     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6919     if (ret)
6920     {
6921         ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6922          "Unexpected size\n");
6923         ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6924          "Unexpected value\n");
6925         LocalFree(buf);
6926     }
6927     permitted.fMaximum = TRUE;
6928     permitted.dwMaximum = 3;
6929     SetLastError(0xdeadbeef);
6930     ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6931      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6932     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6933     if (ret)
6934     {
6935         ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6936          "Unexpected size\n");
6937         ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6938          "Unexpected value\n");
6939         LocalFree(buf);
6940     }
6941 }
6942
6943 struct EncodedNameConstraints
6944 {
6945     CRYPT_DATA_BLOB            encoded;
6946     CERT_NAME_CONSTRAINTS_INFO constraints;
6947 };
6948
6949 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6950  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6951 static CERT_GENERAL_SUBTREE DNSSubtree = {
6952  { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6953 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6954  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6955 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6956  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6957 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6958  { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6959
6960 struct EncodedNameConstraints encodedNameConstraints[] = {
6961  { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6962  { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6963    { 1, &emptyDNSSubtree, 0, NULL } },
6964  { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6965    { 0, NULL, 1, &emptyDNSSubtree } },
6966  { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6967    { 0, NULL, 1, &DNSSubtree } },
6968  { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6969    { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6970  { { sizeof(permittedAndExcludedWithMinConstraints),
6971      permittedAndExcludedWithMinConstraints },
6972    { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6973  { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6974      permittedAndExcludedWithMinMaxConstraints },
6975    { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6976 };
6977
6978 static void test_decodeNameConstraints(DWORD dwEncoding)
6979 {
6980     BOOL ret;
6981     DWORD i;
6982     CERT_NAME_CONSTRAINTS_INFO *constraints;
6983
6984     U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6985     U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6986     U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6987     U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6988     U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6989     U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6990     U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6991     for (i = 0;
6992      i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6993      i++)
6994     {
6995         DWORD size;
6996
6997         ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6998          encodedNameConstraints[i].encoded.pbData,
6999          encodedNameConstraints[i].encoded.cbData,
7000          CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7001         if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7002         {
7003             skip("no X509_NAME_CONSTRAINTS decode support\n");
7004             return;
7005         }
7006         ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7007         if (ret)
7008         {
7009             DWORD j;
7010
7011             if (constraints->cPermittedSubtree !=
7012              encodedNameConstraints[i].constraints.cPermittedSubtree)
7013                 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7014                  encodedNameConstraints[i].constraints.cPermittedSubtree,
7015                  constraints->cPermittedSubtree);
7016             if (constraints->cPermittedSubtree ==
7017              encodedNameConstraints[i].constraints.cPermittedSubtree)
7018             {
7019                 for (j = 0; j < constraints->cPermittedSubtree; j++)
7020                 {
7021                     compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7022                      &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7023                 }
7024             }
7025             if (constraints->cExcludedSubtree !=
7026              encodedNameConstraints[i].constraints.cExcludedSubtree)
7027                 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7028                  encodedNameConstraints[i].constraints.cExcludedSubtree,
7029                  constraints->cExcludedSubtree);
7030             if (constraints->cExcludedSubtree ==
7031              encodedNameConstraints[i].constraints.cExcludedSubtree)
7032             {
7033                 for (j = 0; j < constraints->cExcludedSubtree; j++)
7034                 {
7035                     compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7036                      &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7037                 }
7038             }
7039             LocalFree(constraints);
7040         }
7041     }
7042 }
7043
7044 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7045  'n','o','t','i','c','e',0 };
7046 static const BYTE noticeWithDisplayText[] = {
7047  0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7048  0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7049  0x00,0x69,0x00,0x63,0x00,0x65
7050 };
7051 static char org[] = "Wine";
7052 static int noticeNumbers[] = { 2,3 };
7053 static BYTE noticeWithReference[] = {
7054  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7055  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7056  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7057  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7058 };
7059
7060 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7061 {
7062     BOOL ret;
7063     LPBYTE buf;
7064     DWORD size;
7065     CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7066     CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7067
7068     memset(&notice, 0, sizeof(notice));
7069     ret = pCryptEncodeObjectEx(dwEncoding,
7070      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7071      NULL, &buf, &size);
7072     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7073     {
7074         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7075         return;
7076     }
7077     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7078     if (ret)
7079     {
7080         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7081         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7082         LocalFree(buf);
7083     }
7084     notice.pszDisplayText = noticeText;
7085     ret = pCryptEncodeObjectEx(dwEncoding,
7086      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7087      NULL, &buf, &size);
7088     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7089     if (ret)
7090     {
7091         ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7092         ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7093         LocalFree(buf);
7094     }
7095     reference.pszOrganization = org;
7096     reference.cNoticeNumbers = 2;
7097     reference.rgNoticeNumbers = noticeNumbers;
7098     notice.pNoticeReference = &reference;
7099     ret = pCryptEncodeObjectEx(dwEncoding,
7100      X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7101      NULL, &buf, &size);
7102     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7103     if (ret)
7104     {
7105         ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7106         ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7107         LocalFree(buf);
7108     }
7109 }
7110
7111 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7112 {
7113     BOOL ret;
7114     CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7115     DWORD size;
7116
7117     ret = pCryptDecodeObjectEx(dwEncoding,
7118      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7119      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7120      &notice, &size);
7121     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7122     {
7123         skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7124         return;
7125     }
7126     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7127     if (ret)
7128     {
7129         ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7130         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7131         LocalFree(notice);
7132     }
7133     ret = pCryptDecodeObjectEx(dwEncoding,
7134      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7135      noticeWithDisplayText, sizeof(noticeWithDisplayText),
7136      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7137     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7138     if (ret)
7139     {
7140         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7141          "unexpected display text\n");
7142         ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7143         LocalFree(notice);
7144     }
7145     ret = pCryptDecodeObjectEx(dwEncoding,
7146      X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7147      noticeWithReference, sizeof(noticeWithReference),
7148      CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7149     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7150     if (ret)
7151     {
7152         ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7153          "unexpected display text\n");
7154         ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7155         if (notice->pNoticeReference)
7156         {
7157             ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7158              "unexpected organization %s\n",
7159              notice->pNoticeReference->pszOrganization);
7160             ok(notice->pNoticeReference->cNoticeNumbers == 2,
7161              "expected 2 notice numbers, got %d\n",
7162              notice->pNoticeReference->cNoticeNumbers);
7163             ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7164              "unexpected notice number %d\n",
7165              notice->pNoticeReference->rgNoticeNumbers[0]);
7166             ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7167              "unexpected notice number %d\n",
7168              notice->pNoticeReference->rgNoticeNumbers[1]);
7169         }
7170         LocalFree(notice);
7171     }
7172 }
7173
7174 static char oid_any_policy[] = "2.5.29.32.0";
7175 static const BYTE policiesWithAnyPolicy[] = {
7176  0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7177 };
7178 static char oid1[] = "1.2.3";
7179 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7180 static const BYTE twoPolicies[] = {
7181  0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7182  0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7183  0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7184  0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7185  0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7186  0x74,0x00,0x69,0x00,0x63,0x00,0x65
7187 };
7188
7189 static void test_encodeCertPolicies(DWORD dwEncoding)
7190 {
7191     BOOL ret;
7192     CERT_POLICIES_INFO info;
7193     CERT_POLICY_INFO policy[2];
7194     CERT_POLICY_QUALIFIER_INFO qualifier;
7195     LPBYTE buf;
7196     DWORD size;
7197
7198     memset(&info, 0, sizeof(info));
7199     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7200      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7201     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7202     if (ret)
7203     {
7204         ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7205         ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7206         LocalFree(buf);
7207     }
7208     memset(policy, 0, sizeof(policy));
7209     info.cPolicyInfo = 1;
7210     info.rgPolicyInfo = policy;
7211     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7212      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7213     ok(!ret && (GetLastError() == E_INVALIDARG ||
7214      GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7215      "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7216     policy[0].pszPolicyIdentifier = oid_any_policy;
7217     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7218      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7219     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7220     if (ret)
7221     {
7222         ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7223         ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7224         LocalFree(buf);
7225     }
7226     policy[1].pszPolicyIdentifier = oid1;
7227     memset(&qualifier, 0, sizeof(qualifier));
7228     qualifier.pszPolicyQualifierId = oid_user_notice;
7229     qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7230     qualifier.Qualifier.pbData = noticeWithReference;
7231     policy[1].cPolicyQualifier = 1;
7232     policy[1].rgPolicyQualifier = &qualifier;
7233     info.cPolicyInfo = 2;
7234     ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7235      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7236     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7237     if (ret)
7238     {
7239         ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7240         ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7241         LocalFree(buf);
7242     }
7243 }
7244
7245 static void test_decodeCertPolicies(DWORD dwEncoding)
7246 {
7247     BOOL ret;
7248     CERT_POLICIES_INFO *info;
7249     DWORD size;
7250
7251     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7252      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7253      &info, &size);
7254     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7255     if (ret)
7256     {
7257         ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7258          info->cPolicyInfo);
7259         LocalFree(info);
7260     }
7261     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7262      policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7263      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7264     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7265     if (ret)
7266     {
7267         ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7268          info->cPolicyInfo);
7269         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7270          "unexpected policy id %s\n",
7271          info->rgPolicyInfo[0].pszPolicyIdentifier);
7272         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7273          "unexpected policy qualifier count %d\n",
7274          info->rgPolicyInfo[0].cPolicyQualifier);
7275         LocalFree(info);
7276     }
7277     ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7278      twoPolicies, sizeof(twoPolicies),
7279      CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7280     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7281     if (ret)
7282     {
7283         ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7284          info->cPolicyInfo);
7285         ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7286          "unexpected policy id %s\n",
7287          info->rgPolicyInfo[0].pszPolicyIdentifier);
7288         ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7289          "unexpected policy qualifier count %d\n",
7290          info->rgPolicyInfo[0].cPolicyQualifier);
7291         ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7292          "unexpected policy id %s\n",
7293          info->rgPolicyInfo[1].pszPolicyIdentifier);
7294         ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7295          "unexpected policy qualifier count %d\n",
7296          info->rgPolicyInfo[1].cPolicyQualifier);
7297         ok(!strcmp(
7298          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7299          oid_user_notice), "unexpected policy qualifier id %s\n",
7300          info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7301         ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7302          sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7303          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7304         ok(!memcmp(
7305          info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7306          noticeWithReference, sizeof(noticeWithReference)),
7307          "unexpected qualifier value\n");
7308         LocalFree(info);
7309     }
7310 }
7311
7312 /* Free *pInfo with HeapFree */
7313 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7314 {
7315     BOOL ret;
7316     DWORD size = 0;
7317     HCRYPTKEY key;
7318
7319     /* This crashes
7320     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7321      */
7322     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7323     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7324      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7325     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7326      &size);
7327     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7328      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7329     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7330      NULL, &size);
7331     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7332      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7333     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7334      0, NULL, NULL, &size);
7335     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7336      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7337     /* Test with no key */
7338     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7339      0, NULL, NULL, &size);
7340     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7341      GetLastError());
7342     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7343     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7344     if (ret)
7345     {
7346         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7347          NULL, 0, NULL, NULL, &size);
7348         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7349         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7350         if (*pInfo)
7351         {
7352             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7353              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7354             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7355              GetLastError());
7356             if (ret)
7357             {
7358                 /* By default (we passed NULL as the OID) the OID is
7359                  * szOID_RSA_RSA.
7360                  */
7361                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7362                  "Expected %s, got %s\n", szOID_RSA_RSA,
7363                  (*pInfo)->Algorithm.pszObjId);
7364             }
7365         }
7366     }
7367     CryptDestroyKey(key);
7368 }
7369
7370 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7371  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7372  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7373  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7374  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7375  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7376  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7377  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7378  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7379  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7380  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7381  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7382  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7383  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7384  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7385  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7386  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7387  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7388  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7389  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7390  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7391  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7392  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7393  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7394  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7395
7396 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7397 {
7398     BOOL ret;
7399     HCRYPTKEY key;
7400     PCCERT_CONTEXT context;
7401     DWORD dwSize;
7402     ALG_ID ai;
7403
7404     /* These crash
7405     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7406     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7407     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7408     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7409      NULL);
7410      */
7411     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7412     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7413      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7414     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7415     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7416      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7417     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7418      &key);
7419     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7420      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7421
7422     /* Export key with standard algorithm (CALG_RSA_KEYX) */
7423     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7424      &key);
7425     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7426
7427     dwSize = sizeof(ai);
7428     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7429     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7430     if(ret)
7431     {
7432       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7433       ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7434     }
7435
7436     CryptDestroyKey(key);
7437
7438     /* Repeat with forced algorithm */
7439     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7440      &key);
7441     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7442
7443     dwSize = sizeof(ai);
7444     CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7445     ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7446     if(ret)
7447     {
7448       ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7449       ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7450     }
7451
7452     CryptDestroyKey(key);
7453
7454     /* Test importing a public key from a certificate context */
7455     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7456      sizeof(expiredCert));
7457     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7458      GetLastError());
7459     if (context)
7460     {
7461         ok(!strcmp(szOID_RSA_RSA,
7462          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7463          "Expected %s, got %s\n", szOID_RSA_RSA,
7464          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7465         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7466          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7467         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7468         CryptDestroyKey(key);
7469         CertFreeCertificateContext(context);
7470     }
7471 }
7472
7473 static const char cspName[] = "WineCryptTemp";
7474
7475 static void testPortPublicKeyInfo(void)
7476 {
7477     HCRYPTPROV csp;
7478     BOOL ret;
7479     PCERT_PUBLIC_KEY_INFO info = NULL;
7480
7481     /* Just in case a previous run failed, delete this thing */
7482     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7483      CRYPT_DELETEKEYSET);
7484     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7485      CRYPT_NEWKEYSET);
7486
7487     testExportPublicKey(csp, &info);
7488     testImportPublicKey(csp, info);
7489
7490     HeapFree(GetProcessHeap(), 0, info);
7491     CryptReleaseContext(csp, 0);
7492     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7493      CRYPT_DELETEKEYSET);
7494 }
7495
7496 START_TEST(encode)
7497 {
7498     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7499      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7500     HMODULE hCrypt32;
7501     DWORD i;
7502
7503     hCrypt32 = GetModuleHandleA("crypt32.dll");
7504     pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7505     pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7506     if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7507     {
7508         skip("CryptDecodeObjectEx() is not available\n");
7509         return;
7510     }
7511
7512     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7513     {
7514         test_encodeInt(encodings[i]);
7515         test_decodeInt(encodings[i]);
7516         test_encodeEnumerated(encodings[i]);
7517         test_decodeEnumerated(encodings[i]);
7518         test_encodeFiletime(encodings[i]);
7519         test_decodeFiletime(encodings[i]);
7520         test_encodeName(encodings[i]);
7521         test_decodeName(encodings[i]);
7522         test_encodeUnicodeName(encodings[i]);
7523         test_decodeUnicodeName(encodings[i]);
7524         test_encodeNameValue(encodings[i]);
7525         test_decodeNameValue(encodings[i]);
7526         test_encodeUnicodeNameValue(encodings[i]);
7527         test_decodeUnicodeNameValue(encodings[i]);
7528         test_encodeAltName(encodings[i]);
7529         test_decodeAltName(encodings[i]);
7530         test_encodeOctets(encodings[i]);
7531         test_decodeOctets(encodings[i]);
7532         test_encodeBits(encodings[i]);
7533         test_decodeBits(encodings[i]);
7534         test_encodeBasicConstraints(encodings[i]);
7535         test_decodeBasicConstraints(encodings[i]);
7536         test_encodeRsaPublicKey(encodings[i]);
7537         test_decodeRsaPublicKey(encodings[i]);
7538         test_encodeSequenceOfAny(encodings[i]);
7539         test_decodeSequenceOfAny(encodings[i]);
7540         test_encodeExtensions(encodings[i]);
7541         test_decodeExtensions(encodings[i]);
7542         test_encodePublicKeyInfo(encodings[i]);
7543         test_decodePublicKeyInfo(encodings[i]);
7544         test_encodeCertToBeSigned(encodings[i]);
7545         test_decodeCertToBeSigned(encodings[i]);
7546         test_encodeCert(encodings[i]);
7547         test_decodeCert(encodings[i]);
7548         test_encodeCRLDistPoints(encodings[i]);
7549         test_decodeCRLDistPoints(encodings[i]);
7550         test_encodeCRLIssuingDistPoint(encodings[i]);
7551         test_decodeCRLIssuingDistPoint(encodings[i]);
7552         test_encodeCRLToBeSigned(encodings[i]);
7553         test_decodeCRLToBeSigned(encodings[i]);
7554         test_encodeEnhancedKeyUsage(encodings[i]);
7555         test_decodeEnhancedKeyUsage(encodings[i]);
7556         test_encodeAuthorityKeyId(encodings[i]);
7557         test_decodeAuthorityKeyId(encodings[i]);
7558         test_encodeAuthorityKeyId2(encodings[i]);
7559         test_decodeAuthorityKeyId2(encodings[i]);
7560         test_encodeAuthorityInfoAccess(encodings[i]);
7561         test_decodeAuthorityInfoAccess(encodings[i]);
7562         test_encodeCTL(encodings[i]);
7563         test_decodeCTL(encodings[i]);
7564         test_encodePKCSContentInfo(encodings[i]);
7565         test_decodePKCSContentInfo(encodings[i]);
7566         test_encodePKCSAttribute(encodings[i]);
7567         test_decodePKCSAttribute(encodings[i]);
7568         test_encodePKCSAttributes(encodings[i]);
7569         test_decodePKCSAttributes(encodings[i]);
7570         test_encodePKCSSMimeCapabilities(encodings[i]);
7571         test_decodePKCSSMimeCapabilities(encodings[i]);
7572         test_encodePKCSSignerInfo(encodings[i]);
7573         test_decodePKCSSignerInfo(encodings[i]);
7574         test_encodeCMSSignerInfo(encodings[i]);
7575         test_decodeCMSSignerInfo(encodings[i]);
7576         test_encodeNameConstraints(encodings[i]);
7577         test_decodeNameConstraints(encodings[i]);
7578         test_encodePolicyQualifierUserNotice(encodings[i]);
7579         test_decodePolicyQualifierUserNotice(encodings[i]);
7580         test_encodeCertPolicies(encodings[i]);
7581         test_decodeCertPolicies(encodings[i]);
7582     }
7583     testPortPublicKeyInfo();
7584 }