crypt32: Introduce function to encode an array of items as a set.
[wine] / dlls / crypt32 / tests / encode.c
1 /*
2  * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3  *
4  * Copyright 2005 Juan Lang
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
26
27 #include "wine/test.h"
28
29 struct encodedInt
30 {
31     int val;
32     const BYTE *encoded;
33 };
34
35 static const BYTE bin1[] = {0x02,0x01,0x01};
36 static const BYTE bin2[] = {0x02,0x01,0x7f};
37 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
38 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
39 static const BYTE bin5[] = {0x02,0x01,0x80};
40 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
41 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
42
43 static const struct encodedInt ints[] = {
44  { 1,          bin1 },
45  { 127,        bin2 },
46  { 128,        bin3 },
47  { 256,        bin4 },
48  { -128,       bin5 },
49  { -129,       bin6 },
50  { 0xbaddf00d, bin7 },
51 };
52
53 struct encodedBigInt
54 {
55     const BYTE *val;
56     const BYTE *encoded;
57     const BYTE *decoded;
58 };
59
60 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
61 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
62 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
63
64 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
65 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
66 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
67
68 static const struct encodedBigInt bigInts[] = {
69  { bin8, bin9, bin10 },
70  { bin11, bin12, bin13 },
71 };
72
73 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
74 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
75 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
76 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
77
78 /* Decoded is the same as original, so don't bother storing a separate copy */
79 static const struct encodedBigInt bigUInts[] = {
80  { bin14, bin15, NULL },
81  { bin16, bin17, NULL },
82 };
83
84 static void test_encodeInt(DWORD dwEncoding)
85 {
86     DWORD bufSize = 0;
87     int i;
88     BOOL ret;
89     CRYPT_INTEGER_BLOB blob;
90     BYTE *buf = NULL;
91
92     /* CryptEncodeObjectEx with NULL bufSize crashes..
93     ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
94      NULL);
95      */
96     /* check bogus encoding */
97     ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98      &bufSize);
99     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
100      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
101     /* check with NULL integer buffer.  Windows XP incorrectly returns an
102      * NTSTATUS.
103      */
104     ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
105      &bufSize);
106     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
107      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
108     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
109     {
110         /* encode as normal integer */
111         ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
112          NULL, NULL, &bufSize);
113         ok(ret, "Expected success, got %d\n", GetLastError());
114         ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
115          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
116         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
117         if (buf)
118         {
119             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
120              buf[0]);
121             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
122              buf[1], ints[i].encoded[1]);
123             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
124              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
125             LocalFree(buf);
126         }
127         /* encode as multibyte integer */
128         blob.cbData = sizeof(ints[i].val);
129         blob.pbData = (BYTE *)&ints[i].val;
130         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
131          0, NULL, NULL, &bufSize);
132         ok(ret, "Expected success, got %d\n", GetLastError());
133         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
134          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
135         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
136         if (buf)
137         {
138             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
139              buf[0]);
140             ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
141              buf[1], ints[i].encoded[1]);
142             ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
143              "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
144             LocalFree(buf);
145         }
146     }
147     /* encode a couple bigger ints, just to show it's little-endian and leading
148      * sign bytes are dropped
149      */
150     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
151     {
152         blob.cbData = strlen((const char*)bigInts[i].val);
153         blob.pbData = (BYTE *)bigInts[i].val;
154         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
155          0, NULL, NULL, &bufSize);
156         ok(ret, "Expected success, got %d\n", GetLastError());
157         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
158          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
159         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
160         if (buf)
161         {
162             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
163              buf[0]);
164             ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
165              buf[1], bigInts[i].encoded[1]);
166             ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
167              bigInts[i].encoded[1] + 1),
168              "Encoded value didn't match expected\n");
169             LocalFree(buf);
170         }
171     }
172     /* and, encode some uints */
173     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
174     {
175         blob.cbData = strlen((const char*)bigUInts[i].val);
176         blob.pbData = (BYTE*)bigUInts[i].val;
177         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
178          0, NULL, NULL, &bufSize);
179         ok(ret, "Expected success, got %d\n", GetLastError());
180         ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
181          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
182         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
183         if (buf)
184         {
185             ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
186              buf[0]);
187             ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
188              buf[1], bigUInts[i].encoded[1]);
189             ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
190              bigUInts[i].encoded[1] + 1),
191              "Encoded value didn't match expected\n");
192             LocalFree(buf);
193         }
194     }
195 }
196
197 static void test_decodeInt(DWORD dwEncoding)
198 {
199     static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
200     static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
201     static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
202     static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
203     static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
204     BYTE *buf = NULL;
205     DWORD bufSize = 0;
206     int i;
207     BOOL ret;
208
209     /* CryptDecodeObjectEx with NULL bufSize crashes..
210     ret = CryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded, 
211      ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
212      */
213     /* check bogus encoding */
214     ret = CryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded, 
215      ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
216     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
217      "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
218     /* check with NULL integer buffer */
219     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
220      &bufSize);
221     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
222      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
223     /* check with a valid, but too large, integer */
224     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
225      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
226     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
227      "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
228     /* check with a DER-encoded string */
229     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
230      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
231     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
232      "Expected CRYPT_E_ASN1_BADTAG, got %d\n", GetLastError());
233     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
234     {
235         /* When the output buffer is NULL, this always succeeds */
236         SetLastError(0xdeadbeef);
237         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
238          ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
239          &bufSize);
240         ok(ret && GetLastError() == NOERROR,
241          "Expected success and NOERROR, got %d\n", GetLastError());
242         ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
243          ints[i].encoded, ints[i].encoded[1] + 2,
244          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
245         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
246         ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
247         ok(buf != NULL, "Expected allocated buffer\n");
248         if (buf)
249         {
250             ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
251              ints[i].val, *(int *)buf);
252             LocalFree(buf);
253         }
254     }
255     for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
256     {
257         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
258          bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
259          &bufSize);
260         ok(ret && GetLastError() == NOERROR,
261          "Expected success and NOERROR, got %d\n", GetLastError());
262         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
263          bigInts[i].encoded, bigInts[i].encoded[1] + 2,
264          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
265         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
266         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
267         ok(buf != NULL, "Expected allocated buffer\n");
268         if (buf)
269         {
270             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
271
272             ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
273              "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
274              blob->cbData);
275             ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
276              "Unexpected value\n");
277             LocalFree(buf);
278         }
279     }
280     for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
281     {
282         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
283          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
284          &bufSize);
285         ok(ret && GetLastError() == NOERROR,
286          "Expected success and NOERROR, got %d\n", GetLastError());
287         ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
288          bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
289          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
290         ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
291         ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
292         ok(buf != NULL, "Expected allocated buffer\n");
293         if (buf)
294         {
295             CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
296
297             ok(blob->cbData == strlen((const char*)bigUInts[i].val),
298              "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
299              blob->cbData);
300             ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
301              "Unexpected value\n");
302             LocalFree(buf);
303         }
304     }
305     /* Decode the value 1 with long-form length */
306     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
307      sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
308     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
309     if (buf)
310     {
311         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
312         LocalFree(buf);
313     }
314     /* check with extra bytes at the end */
315     ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
316      sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
317     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
318     if (buf)
319     {
320         ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
321         LocalFree(buf);
322     }
323     /* Try to decode some bogus large items */
324     /* The buffer size is smaller than the encoded length, so this should fail
325      * with CRYPT_E_ASN1_EOD if it's being decoded.
326      * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
327      * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
328      * So this test unfortunately isn't useful.
329     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
330      0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
331     ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
332      "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
333      */
334     /* This will try to decode the buffer and overflow it, check that it's
335      * caught.
336      */
337     if (0)
338     {
339     /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
340     ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
341      0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
342     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
343      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
344     }
345 }
346
347 static const BYTE bin18[] = {0x0a,0x01,0x01};
348 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
349
350 /* These are always encoded unsigned, and aren't constrained to be any
351  * particular value
352  */
353 static const struct encodedInt enums[] = {
354  { 1,    bin18 },
355  { -128, bin19 },
356 };
357
358 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
359  * X509_ENUMERATED.
360  */
361 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
362  szOID_CRL_REASON_CODE };
363
364 static void test_encodeEnumerated(DWORD dwEncoding)
365 {
366     DWORD i, j;
367
368     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
369     {
370         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
371         {
372             BOOL ret;
373             BYTE *buf = NULL;
374             DWORD bufSize = 0;
375
376             ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
377              &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
378              &bufSize);
379             ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
380             if (buf)
381             {
382                 ok(buf[0] == 0xa,
383                  "Got unexpected type %d for enumerated (expected 0xa)\n",
384                  buf[0]);
385                 ok(buf[1] == enums[j].encoded[1],
386                  "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
387                 ok(!memcmp(buf + 1, enums[j].encoded + 1,
388                  enums[j].encoded[1] + 1),
389                  "Encoded value of 0x%08x didn't match expected\n",
390                  enums[j].val);
391                 LocalFree(buf);
392             }
393         }
394     }
395 }
396
397 static void test_decodeEnumerated(DWORD dwEncoding)
398 {
399     DWORD i, j;
400
401     for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
402     {
403         for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
404         {
405             BOOL ret;
406             DWORD bufSize = sizeof(int);
407             int val;
408
409             ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
410              enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
411              (BYTE *)&val, &bufSize);
412             ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
413             ok(bufSize == sizeof(int),
414              "Got unexpected size %d for enumerated\n", bufSize);
415             ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
416              val, enums[j].val);
417         }
418     }
419 }
420
421 struct encodedFiletime
422 {
423     SYSTEMTIME sysTime;
424     const BYTE *encodedTime;
425 };
426
427 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
428  const struct encodedFiletime *time)
429 {
430     FILETIME ft = { 0 };
431     BYTE *buf = NULL;
432     DWORD bufSize = 0;
433     BOOL ret;
434
435     ret = SystemTimeToFileTime(&time->sysTime, &ft);
436     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
437     ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
438      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
439     /* years other than 1950-2050 are not allowed for encodings other than
440      * X509_CHOICE_OF_TIME.
441      */
442     if (structType == X509_CHOICE_OF_TIME ||
443      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
444     {
445         ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
446          GetLastError());
447         ok(buf != NULL, "Expected an allocated buffer\n");
448         if (buf)
449         {
450             ok(buf[0] == time->encodedTime[0],
451              "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
452              buf[0]);
453             ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
454              time->encodedTime[1], bufSize);
455             ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
456              "Got unexpected value for time encoding\n");
457             LocalFree(buf);
458         }
459     }
460     else
461         ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
462          "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
463 }
464
465 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
466  const struct encodedFiletime *time)
467 {
468     FILETIME ft1 = { 0 }, ft2 = { 0 };
469     DWORD size = sizeof(ft2);
470     BOOL ret;
471
472     ret = SystemTimeToFileTime(&time->sysTime, &ft1);
473     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
474     ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
475      time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
476     /* years other than 1950-2050 are not allowed for encodings other than
477      * X509_CHOICE_OF_TIME.
478      */
479     if (structType == X509_CHOICE_OF_TIME ||
480      (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
481     {
482         ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
483          GetLastError());
484         ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
485          "Got unexpected value for time decoding\n");
486     }
487     else
488         ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
489          "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
490 }
491
492 static const BYTE bin20[] = {
493     0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
494 static const BYTE bin21[] = {
495     0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
496 static const BYTE bin22[] = {
497     0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
498
499 static const struct encodedFiletime times[] = {
500  { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
501  { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
502  { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
503 };
504
505 static void test_encodeFiletime(DWORD dwEncoding)
506 {
507     DWORD i;
508
509     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
510     {
511         testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
512         testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
513         testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
514     }
515 }
516
517 static const BYTE bin23[] = {
518     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
519 static const BYTE bin24[] = {
520     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
521 static const BYTE bin25[] = {
522     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
523 static const BYTE bin26[] = {
524     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
525 static const BYTE bin27[] = {
526     0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
527 static const BYTE bin28[] = {
528     0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
529 static const BYTE bin29[] = {
530     0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
531 static const BYTE bin30[] = {
532     0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
533 static const BYTE bin31[] = {
534     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
535 static const BYTE bin32[] = {
536     0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
537 static const BYTE bin33[] = {
538     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
539 static const BYTE bin34[] = {
540     0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
541 static const BYTE bin35[] = {
542     0x17,0x08, '4','5','0','6','0','6','1','6'};
543 static const BYTE bin36[] = {
544     0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
545 static const BYTE bin37[] = {
546     0x18,0x04, '2','1','4','5'};
547 static const BYTE bin38[] = {
548     0x18,0x08, '2','1','4','5','0','6','0','6'};
549
550 static void test_decodeFiletime(DWORD dwEncoding)
551 {
552     static const struct encodedFiletime otherTimes[] = {
553      { { 1945, 6, 1, 6, 16, 10, 0, 0 },   bin23 },
554      { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
555      { { 1945, 6, 1, 6, 17, 10, 0, 0 },   bin25 },
556      { { 1945, 6, 1, 6, 15, 10, 0, 0 },   bin26 },
557      { { 1945, 6, 1, 6, 14, 55, 0, 0 },   bin27 },
558      { { 2145, 6, 1, 6, 16,  0, 0, 0 },   bin28 },
559      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin29 },
560      { { 2045, 6, 1, 6, 16, 10, 0, 0 },   bin30 },
561      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin31 },
562      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin32 },
563      { { 2045, 6, 1, 6, 17, 10, 0, 0 },   bin33 },
564      { { 2045, 6, 1, 6, 15, 10, 0, 0 },   bin34 },
565     };
566     /* An oddball case that succeeds in Windows, but doesn't seem correct
567      { { 2145, 6, 1, 2, 11, 31, 0, 0 },   "\x18" "\x13" "21450606161000-9999" },
568      */
569     static const unsigned char *bogusTimes[] = {
570      /* oddly, this succeeds on Windows, with year 2765
571      "\x18" "\x0f" "21r50606161000Z",
572       */
573      bin35,
574      bin36,
575      bin37,
576      bin38,
577     };
578     DWORD i, size;
579     FILETIME ft1 = { 0 }, ft2 = { 0 };
580     BOOL ret;
581
582     /* Check bogus length with non-NULL buffer */
583     ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
584     ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
585     size = 1;
586     ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
587      times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
588     ok(!ret && GetLastError() == ERROR_MORE_DATA,
589      "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
590     /* Normal tests */
591     for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
592     {
593         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
594         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
595         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
596     }
597     for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
598     {
599         testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
600         testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
601         testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
602     }
603     for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
604     {
605         size = sizeof(ft1);
606         ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
607          bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
608         ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
609          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
610     }
611 }
612
613 static const char commonName[] = "Juan Lang";
614 static const char surName[] = "Lang";
615
616 static const BYTE emptySequence[] = { 0x30, 0 };
617 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
618 static const BYTE twoRDNs[] = {
619     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
620     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
621     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
622 static const BYTE encodedTwoRDNs[] = {
623 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
624 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
625 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
626 0x6e,0x67,0x00,
627 };
628
629 static const BYTE us[] = { 0x55, 0x53 };
630 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
631  0x74, 0x61 };
632 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
633  0x6f, 0x6c, 0x69, 0x73 };
634 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
635  0x76, 0x65, 0x72, 0x73 };
636 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
637  0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
638 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
639  0x73, 0x74 };
640 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
641  0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
642
643 #define RDNA(arr)   oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
644 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING,       { sizeof(arr), (LPBYTE)arr }
645
646 static CHAR oid_us[]            = "2.5.4.6",
647             oid_minnesota[]     = "2.5.4.8",
648             oid_minneapolis[]   = "2.5.4.7",
649             oid_codeweavers[]   = "2.5.4.10",
650             oid_wine[]          = "2.5.4.11",
651             oid_localhostAttr[] = "2.5.4.3",
652             oid_aric[]          = "1.2.840.113549.1.9.1";
653 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
654                                     { RDNA(minnesota) },
655                                     { RDNA(minneapolis) },
656                                     { RDNA(codeweavers) },
657                                     { RDNA(wine) },
658                                     { RDNA(localhostAttr) },
659                                     { RDNIA5(aric) } };
660 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
661                                            { RDNA(localhostAttr) },
662                                            { RDNA(minnesota) },
663                                            { RDNA(minneapolis) },
664                                            { RDNA(codeweavers) },
665                                            { RDNA(wine) },
666                                            { RDNIA5(aric) } };
667
668 #undef RDNIA5
669 #undef RDNA
670
671 static const BYTE encodedRDNAttrs[] = {
672 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
673 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
674 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
675 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
676 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
677 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
678 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
679 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
680 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
681 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
682 };
683
684 static void test_encodeName(DWORD dwEncoding)
685 {
686     CERT_RDN_ATTR attrs[2];
687     CERT_RDN rdn;
688     CERT_NAME_INFO info;
689     static CHAR oid_common_name[] = szOID_COMMON_NAME,
690                 oid_sur_name[]    = szOID_SUR_NAME;
691     BYTE *buf = NULL;
692     DWORD size = 0;
693     BOOL ret;
694
695     /* Test with NULL pvStructInfo */
696     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
697      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
698     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
699      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
700     /* Test with empty CERT_NAME_INFO */
701     info.cRDN = 0;
702     info.rgRDN = NULL;
703     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
704      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
705     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
706     if (buf)
707     {
708         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
709          "Got unexpected encoding for empty name\n");
710         LocalFree(buf);
711     }
712     /* Test with bogus CERT_RDN */
713     info.cRDN = 1;
714     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
715      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
716     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
717      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
718     /* Test with empty CERT_RDN */
719     rdn.cRDNAttr = 0;
720     rdn.rgRDNAttr = NULL;
721     info.cRDN = 1;
722     info.rgRDN = &rdn;
723     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
724      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
725     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
726     if (buf)
727     {
728         ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
729          "Got unexpected encoding for empty RDN array\n");
730         LocalFree(buf);
731     }
732     /* Test with bogus attr array */
733     rdn.cRDNAttr = 1;
734     rdn.rgRDNAttr = NULL;
735     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
736      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
737     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
738      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
739     /* oddly, a bogus OID is accepted by Windows XP; not testing.
740     attrs[0].pszObjId = "bogus";
741     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
742     attrs[0].Value.cbData = sizeof(commonName);
743     attrs[0].Value.pbData = (BYTE *)commonName;
744     rdn.cRDNAttr = 1;
745     rdn.rgRDNAttr = attrs;
746     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
747      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
748     ok(!ret, "Expected failure, got success\n");
749      */
750     /* Check with two CERT_RDN_ATTRs.  Note DER encoding forces the order of
751      * the encoded attributes to be swapped.
752      */
753     attrs[0].pszObjId = oid_common_name;
754     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
755     attrs[0].Value.cbData = sizeof(commonName);
756     attrs[0].Value.pbData = (BYTE *)commonName;
757     attrs[1].pszObjId = oid_sur_name;
758     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
759     attrs[1].Value.cbData = sizeof(surName);
760     attrs[1].Value.pbData = (BYTE *)surName;
761     rdn.cRDNAttr = 2;
762     rdn.rgRDNAttr = attrs;
763     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
764      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
765     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
766     if (buf)
767     {
768         ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
769          "Got unexpected encoding for two RDN array\n");
770         LocalFree(buf);
771     }
772     /* A name can be "encoded" with previously encoded RDN attrs. */
773     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
774     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
775     attrs[0].Value.cbData = sizeof(twoRDNs);
776     rdn.cRDNAttr = 1;
777     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
778      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
779     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
780     if (buf)
781     {
782         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
783         ok(!memcmp(buf, encodedTwoRDNs, size),
784          "Unexpected value for re-endoded two RDN array\n");
785         LocalFree(buf);
786     }
787     /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
788     rdn.cRDNAttr = 1;
789     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
790     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
791      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
792     ok(!ret && GetLastError() == E_INVALIDARG,
793      "Expected E_INVALIDARG, got %08x\n", GetLastError());
794     /* Test a more complex name */
795     rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
796     rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
797     info.cRDN = 1;
798     info.rgRDN = &rdn;
799     buf = NULL;
800     size = 0;
801     ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
802      CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
803     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
804     if (ret)
805     {
806         ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
807         ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
808         LocalFree(buf);
809     }
810 }
811
812 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
813 static WCHAR surNameW[] = { 'L','a','n','g',0 };
814
815 static const BYTE twoRDNsNoNull[] = {
816  0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
817  0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
818  0x20,0x4c,0x61,0x6e,0x67 };
819 static const BYTE anyType[] = {
820  0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
821  0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
822  0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
823  0x61,0x4c,0x67,0x6e };
824
825 static void test_encodeUnicodeName(DWORD dwEncoding)
826 {
827     CERT_RDN_ATTR attrs[2];
828     CERT_RDN rdn;
829     CERT_NAME_INFO info;
830     static CHAR oid_common_name[] = szOID_COMMON_NAME,
831                 oid_sur_name[]    = szOID_SUR_NAME;
832     BYTE *buf = NULL;
833     DWORD size = 0;
834     BOOL ret;
835
836     /* Test with NULL pvStructInfo */
837     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
838      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
839     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
840      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
841     /* Test with empty CERT_NAME_INFO */
842     info.cRDN = 0;
843     info.rgRDN = NULL;
844     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
845      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
846     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
847     if (buf)
848     {
849         ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
850          "Got unexpected encoding for empty name\n");
851         LocalFree(buf);
852     }
853     /* Check with one CERT_RDN_ATTR, that has an invalid character for the
854      * encoding (the NULL).
855      */
856     attrs[0].pszObjId = oid_common_name;
857     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
858     attrs[0].Value.cbData = sizeof(commonNameW);
859     attrs[0].Value.pbData = (BYTE *)commonNameW;
860     rdn.cRDNAttr = 1;
861     rdn.rgRDNAttr = attrs;
862     info.cRDN = 1;
863     info.rgRDN = &rdn;
864     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
865      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
866     ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
867      "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
868     ok(size == 9, "Unexpected error index %08x\n", size);
869     /* Check with two NULL-terminated CERT_RDN_ATTRs.  Note DER encoding
870      * forces the order of the encoded attributes to be swapped.
871      */
872     attrs[0].pszObjId = oid_common_name;
873     attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
874     attrs[0].Value.cbData = 0;
875     attrs[0].Value.pbData = (BYTE *)commonNameW;
876     attrs[1].pszObjId = oid_sur_name;
877     attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
878     attrs[1].Value.cbData = 0;
879     attrs[1].Value.pbData = (BYTE *)surNameW;
880     rdn.cRDNAttr = 2;
881     rdn.rgRDNAttr = attrs;
882     info.cRDN = 1;
883     info.rgRDN = &rdn;
884     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
885      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
886     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
887     if (buf)
888     {
889         ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
890          "Got unexpected encoding for two RDN array\n");
891         LocalFree(buf);
892     }
893     /* A name can be "encoded" with previously encoded RDN attrs. */
894     attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
895     attrs[0].Value.pbData = (LPBYTE)twoRDNs;
896     attrs[0].Value.cbData = sizeof(twoRDNs);
897     rdn.cRDNAttr = 1;
898     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
899      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
900     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
901     if (buf)
902     {
903         ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
904         ok(!memcmp(buf, encodedTwoRDNs, size),
905          "Unexpected value for re-endoded two RDN array\n");
906         LocalFree(buf);
907     }
908     /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
909     rdn.cRDNAttr = 1;
910     attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
911     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
912      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
913     todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
914     if (buf)
915     {
916         ok(size == sizeof(anyType), "Unexpected size %d\n", size);
917         ok(!memcmp(buf, anyType, size), "Unexpected value\n");
918         LocalFree(buf);
919     }
920 }
921
922 static void compareNameValues(const CERT_NAME_VALUE *expected,
923  const CERT_NAME_VALUE *got)
924 {
925     ok(got->dwValueType == expected->dwValueType,
926      "Expected string type %d, got %d\n", expected->dwValueType,
927      got->dwValueType);
928     ok(got->Value.cbData == expected->Value.cbData,
929      "String type %d: unexpected data size, got %d, expected %d\n",
930      expected->dwValueType, got->Value.cbData, expected->Value.cbData);
931     if (got->Value.cbData && got->Value.pbData)
932         ok(!memcmp(got->Value.pbData, expected->Value.pbData,
933          min(got->Value.cbData, expected->Value.cbData)),
934          "String type %d: unexpected value\n", expected->dwValueType);
935 }
936
937 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
938  const CERT_RDN_ATTR *got)
939 {
940     if (expected->pszObjId && strlen(expected->pszObjId))
941     {
942         ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
943          expected->pszObjId);
944         if (got->pszObjId)
945         {
946             ok(!strcmp(got->pszObjId, expected->pszObjId),
947              "Got unexpected OID %s, expected %s\n", got->pszObjId,
948              expected->pszObjId);
949         }
950     }
951     compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
952      (const CERT_NAME_VALUE *)&got->dwValueType);
953 }
954
955 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
956 {
957     ok(got->cRDNAttr == expected->cRDNAttr,
958      "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
959     if (got->cRDNAttr)
960     {
961         DWORD i;
962
963         for (i = 0; i < got->cRDNAttr; i++)
964             compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
965     }
966 }
967
968 static void compareNames(const CERT_NAME_INFO *expected,
969  const CERT_NAME_INFO *got)
970 {
971     ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
972      expected->cRDN, got->cRDN);
973     if (got->cRDN)
974     {
975         DWORD i;
976
977         for (i = 0; i < got->cRDN; i++)
978             compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
979     }
980 }
981
982 static const BYTE twoRDNsExtraBytes[] = {
983     0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
984     0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
985     0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
986
987 static void test_decodeName(DWORD dwEncoding)
988 {
989     BYTE *buf = NULL;
990     DWORD bufSize = 0;
991     BOOL ret;
992     CERT_RDN rdn;
993     CERT_NAME_INFO info = { 1, &rdn };
994
995     /* test empty name */
996     bufSize = 0;
997     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
998      emptySequence[1] + 2,
999      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1000      (BYTE *)&buf, &bufSize);
1001     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1002     /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL.  My
1003      * decoder works the same way, so only test the count.
1004      */
1005     if (buf)
1006     {
1007         ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1008         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1009          "Expected 0 RDNs in empty info, got %d\n",
1010          ((CERT_NAME_INFO *)buf)->cRDN);
1011         LocalFree(buf);
1012     }
1013     /* test empty RDN */
1014     bufSize = 0;
1015     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1016      emptyRDNs[1] + 2,
1017      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1018      (BYTE *)&buf, &bufSize);
1019     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1020     if (buf)
1021     {
1022         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1023
1024         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1025          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1026          "Got unexpected value for empty RDN\n");
1027         LocalFree(buf);
1028     }
1029     /* test two RDN attrs */
1030     bufSize = 0;
1031     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1032      twoRDNs[1] + 2,
1033      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1034      (BYTE *)&buf, &bufSize);
1035     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1036     if (buf)
1037     {
1038         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1039                     oid_common_name[] = szOID_COMMON_NAME;
1040
1041         CERT_RDN_ATTR attrs[] = {
1042          { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1043           (BYTE *)surName } },
1044          { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1045           (BYTE *)commonName } },
1046         };
1047
1048         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1049         rdn.rgRDNAttr = attrs;
1050         compareNames(&info, (CERT_NAME_INFO *)buf);
1051         LocalFree(buf);
1052     }
1053     /* test that two RDN attrs with extra bytes succeeds */
1054     bufSize = 0;
1055     ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1056      sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1057     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1058     /* And, a slightly more complicated name */
1059     buf = NULL;
1060     bufSize = 0;
1061     ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1062      sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1063     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1064     if (ret)
1065     {
1066         rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1067         rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1068         compareNames(&info, (CERT_NAME_INFO *)buf);
1069         LocalFree(buf);
1070     }
1071 }
1072
1073 static void test_decodeUnicodeName(DWORD dwEncoding)
1074 {
1075     BYTE *buf = NULL;
1076     DWORD bufSize = 0;
1077     BOOL ret;
1078     CERT_RDN rdn;
1079     CERT_NAME_INFO info = { 1, &rdn };
1080
1081     /* test empty name */
1082     bufSize = 0;
1083     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1084      emptySequence[1] + 2,
1085      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1086      (BYTE *)&buf, &bufSize);
1087     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1088     if (buf)
1089     {
1090         ok(bufSize == sizeof(CERT_NAME_INFO),
1091          "Got wrong bufSize %d\n", bufSize);
1092         ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1093          "Expected 0 RDNs in empty info, got %d\n",
1094          ((CERT_NAME_INFO *)buf)->cRDN);
1095         LocalFree(buf);
1096     }
1097     /* test empty RDN */
1098     bufSize = 0;
1099     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1100      emptyRDNs[1] + 2,
1101      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1102      (BYTE *)&buf, &bufSize);
1103     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1104     if (buf)
1105     {
1106         CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1107
1108         ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1109          info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1110          "Got unexpected value for empty RDN\n");
1111         LocalFree(buf);
1112     }
1113     /* test two RDN attrs */
1114     bufSize = 0;
1115     ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1116      sizeof(twoRDNsNoNull),
1117      CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1118      (BYTE *)&buf, &bufSize);
1119     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1120     if (buf)
1121     {
1122         static CHAR oid_sur_name[]    = szOID_SUR_NAME,
1123                     oid_common_name[] = szOID_COMMON_NAME;
1124
1125         CERT_RDN_ATTR attrs[] = {
1126          { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1127          { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1128          { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1129          { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1130         };
1131
1132         rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1133         rdn.rgRDNAttr = attrs;
1134         compareNames(&info, (CERT_NAME_INFO *)buf);
1135         LocalFree(buf);
1136     }
1137 }
1138
1139 struct EncodedNameValue
1140 {
1141     CERT_NAME_VALUE value;
1142     const BYTE *encoded;
1143     DWORD encodedSize;
1144 };
1145
1146 static const char bogusIA5[] = "\x80";
1147 static const char bogusPrintable[] = "~";
1148 static const char bogusNumeric[] = "A";
1149 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1150 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1151 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1152 static BYTE octetCommonNameValue[] = {
1153  0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1154 static BYTE numericCommonNameValue[] = {
1155  0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1156 static BYTE printableCommonNameValue[] = {
1157  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1158 static BYTE t61CommonNameValue[] = {
1159  0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1160 static BYTE videotexCommonNameValue[] = {
1161  0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1162 static BYTE ia5CommonNameValue[] = {
1163  0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1164 static BYTE graphicCommonNameValue[] = {
1165  0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1166 static BYTE visibleCommonNameValue[] = {
1167  0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1168 static BYTE generalCommonNameValue[] = {
1169  0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1170 static BYTE bmpCommonNameValue[] = {
1171  0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1172  0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1173 static BYTE utf8CommonNameValue[] = {
1174  0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1175
1176 static struct EncodedNameValue nameValues[] = {
1177  { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1178      octetCommonNameValue, sizeof(octetCommonNameValue) },
1179  { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1180      numericCommonNameValue, sizeof(numericCommonNameValue) },
1181  { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1182      printableCommonNameValue, sizeof(printableCommonNameValue) },
1183  { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1184      t61CommonNameValue, sizeof(t61CommonNameValue) },
1185  { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1186      videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1187  { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1188      ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1189  { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1190      graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1191  { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1192      visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1193  { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1194      generalCommonNameValue, sizeof(generalCommonNameValue) },
1195  { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1196      bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1197  { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1198      utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1199  /* The following tests succeed under Windows, but really should fail,
1200   * they contain characters that are illegal for the encoding.  I'm
1201   * including them to justify my lazy encoding.
1202   */
1203  { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1204      sizeof(bin42) },
1205  { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1206      (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1207  { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1208      bin44, sizeof(bin44) },
1209 };
1210
1211 static void test_encodeNameValue(DWORD dwEncoding)
1212 {
1213     BYTE *buf = NULL;
1214     DWORD size = 0, i;
1215     BOOL ret;
1216     CERT_NAME_VALUE value = { 0, { 0, NULL } };
1217
1218     value.dwValueType = 14;
1219     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1220      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1221     ok(!ret && GetLastError() == CRYPT_E_ASN1_CHOICE,
1222      "Expected CRYPT_E_ASN1_CHOICE, got %08x\n", GetLastError());
1223     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1224     value.Value.pbData = printableCommonNameValue;
1225     value.Value.cbData = sizeof(printableCommonNameValue);
1226     ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1227      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1228     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1229     if (buf)
1230     {
1231         ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1232          size);
1233         ok(!memcmp(buf, printableCommonNameValue, size),
1234          "Unexpected encoding\n");
1235         LocalFree(buf);
1236     }
1237     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1238     {
1239         ret = CryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1240          &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1241          &size);
1242         ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1243          nameValues[i].value.dwValueType, GetLastError());
1244         if (buf)
1245         {
1246             ok(size == nameValues[i].encodedSize,
1247              "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1248             ok(!memcmp(buf, nameValues[i].encoded, size),
1249              "Got unexpected encoding\n");
1250             LocalFree(buf);
1251         }
1252     }
1253 }
1254
1255 static void test_decodeNameValue(DWORD dwEncoding)
1256 {
1257     int i;
1258     BYTE *buf = NULL;
1259     DWORD bufSize = 0;
1260     BOOL ret;
1261
1262     for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1263     {
1264         ret = CryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1265          nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1266          CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1267          (BYTE *)&buf, &bufSize);
1268         ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1269          nameValues[i].value.dwValueType, GetLastError());
1270         if (buf)
1271         {
1272             compareNameValues(&nameValues[i].value,
1273              (const CERT_NAME_VALUE *)buf);
1274             LocalFree(buf);
1275         }
1276     }
1277 }
1278
1279 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1280 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1281 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1282  'h','q','.','o','r','g',0 };
1283 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1284  0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1285  0x6f, 0x72, 0x67 };
1286 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1287  0x575b, 0 };
1288 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1289 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1290  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1291 static const BYTE localhost[] = { 127, 0, 0, 1 };
1292 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1293  0x01 };
1294
1295 static void test_encodeAltName(DWORD dwEncoding)
1296 {
1297     CERT_ALT_NAME_INFO info = { 0 };
1298     CERT_ALT_NAME_ENTRY entry = { 0 };
1299     BYTE *buf = NULL;
1300     DWORD size = 0;
1301     BOOL ret;
1302
1303     /* Test with empty info */
1304     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1305      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1306     if (buf)
1307     {
1308         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1309         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1310         LocalFree(buf);
1311     }
1312     /* Test with an empty entry */
1313     info.cAltEntry = 1;
1314     info.rgAltEntry = &entry;
1315     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1316      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1317     ok(!ret && GetLastError() == E_INVALIDARG,
1318      "Expected E_INVALIDARG, got %08x\n", GetLastError());
1319     /* Test with an empty pointer */
1320     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1321     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1322      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1323     if (buf)
1324     {
1325         ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1326         ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1327         LocalFree(buf);
1328     }
1329     /* Test with a real URL */
1330     U(entry).pwszURL = (LPWSTR)url;
1331     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1332      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1333     if (buf)
1334     {
1335         ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1336         ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1337         LocalFree(buf);
1338     }
1339     /* Now with the URL containing an invalid IA5 char */
1340     U(entry).pwszURL = (LPWSTR)nihongoURL;
1341     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1342      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1343     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1344      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1345     /* The first invalid character is at index 7 */
1346     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1347      "Expected invalid char at index 7, got %d\n",
1348      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1349     /* Now with the URL missing a scheme */
1350     U(entry).pwszURL = (LPWSTR)dnsName;
1351     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1352      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1353     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1354     if (buf)
1355     {
1356         /* This succeeds, but it shouldn't, so don't worry about conforming */
1357         LocalFree(buf);
1358     }
1359     /* Now with a DNS name */
1360     entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1361     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1362      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1363     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1364     if (buf)
1365     {
1366         ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1367         ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1368         LocalFree(buf);
1369     }
1370     /* Test with an IP address */
1371     entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1372     U(entry).IPAddress.cbData = sizeof(localhost);
1373     U(entry).IPAddress.pbData = (LPBYTE)localhost;
1374     ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1375      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1376     if (buf)
1377     {
1378         ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1379         ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1380         LocalFree(buf);
1381     }
1382 }
1383
1384 static void test_decodeAltName(DWORD dwEncoding)
1385 {
1386     static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1387      0x00, 0x00, 0x01 };
1388     static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1389      0x01 };
1390     BOOL ret;
1391     BYTE *buf = NULL;
1392     DWORD bufSize = 0;
1393     CERT_ALT_NAME_INFO *info;
1394
1395     /* Test some bogus ones first */
1396     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1397      unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1398      NULL, (BYTE *)&buf, &bufSize);
1399     ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1400      "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1401     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1402      bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1403      &bufSize);
1404     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1405      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1406     /* Now expected cases */
1407     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1408      emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1409      &bufSize);
1410     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1411     if (buf)
1412     {
1413         info = (CERT_ALT_NAME_INFO *)buf;
1414
1415         ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1416          info->cAltEntry);
1417         LocalFree(buf);
1418     }
1419     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1420      emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1421      &bufSize);
1422     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1423     if (buf)
1424     {
1425         info = (CERT_ALT_NAME_INFO *)buf;
1426
1427         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1428          info->cAltEntry);
1429         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1430          "Expected CERT_ALT_NAME_URL, got %d\n",
1431          info->rgAltEntry[0].dwAltNameChoice);
1432         ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1433          "Expected empty URL\n");
1434         LocalFree(buf);
1435     }
1436     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1437      emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1438     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1439     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1440      encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1441      &bufSize);
1442     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1443     if (buf)
1444     {
1445         info = (CERT_ALT_NAME_INFO *)buf;
1446
1447         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1448          info->cAltEntry);
1449         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1450          "Expected CERT_ALT_NAME_URL, got %d\n",
1451          info->rgAltEntry[0].dwAltNameChoice);
1452         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1453         LocalFree(buf);
1454     }
1455     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1456      encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1457      &bufSize);
1458     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1459     if (buf)
1460     {
1461         info = (CERT_ALT_NAME_INFO *)buf;
1462
1463         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1464          info->cAltEntry);
1465         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1466          "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1467          info->rgAltEntry[0].dwAltNameChoice);
1468         ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1469          "Unexpected DNS name\n");
1470         LocalFree(buf);
1471     }
1472     ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1473      encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1474      &bufSize);
1475     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1476     if (buf)
1477     {
1478         info = (CERT_ALT_NAME_INFO *)buf;
1479
1480         ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1481          info->cAltEntry);
1482         ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1483          "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1484          info->rgAltEntry[0].dwAltNameChoice);
1485         ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1486          "Unexpected IP address length %d\n",
1487           U(info->rgAltEntry[0]).IPAddress.cbData);
1488         ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1489          sizeof(localhost)), "Unexpected IP address value\n");
1490         LocalFree(buf);
1491     }
1492 }
1493
1494 struct UnicodeExpectedError
1495 {
1496     DWORD   valueType;
1497     LPCWSTR str;
1498     DWORD   errorIndex;
1499     DWORD   error;
1500 };
1501
1502 static const WCHAR oneW[] = { '1',0 };
1503 static const WCHAR aW[] = { 'a',0 };
1504 static const WCHAR quoteW[] = { '"', 0 };
1505
1506 static struct UnicodeExpectedError unicodeErrors[] = {
1507  { CERT_RDN_ANY_TYPE,         oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1508  { CERT_RDN_ENCODED_BLOB,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1509  { CERT_RDN_OCTET_STRING,     oneW,       0, CRYPT_E_NOT_CHAR_STRING },
1510  { 14,                        oneW,       0, CRYPT_E_ASN1_CHOICE },
1511  { CERT_RDN_NUMERIC_STRING,   aW,         0, CRYPT_E_INVALID_NUMERIC_STRING },
1512  { CERT_RDN_PRINTABLE_STRING, quoteW,     0, CRYPT_E_INVALID_PRINTABLE_STRING },
1513  { CERT_RDN_IA5_STRING,       nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1514 };
1515
1516 struct UnicodeExpectedResult
1517 {
1518     DWORD           valueType;
1519     LPCWSTR         str;
1520     CRYPT_DATA_BLOB encoded;
1521 };
1522
1523 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1524 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1525 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1526 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1527 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1528 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1529 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1530 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1531 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1532 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1533 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1534 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1535  0x5b };
1536 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1537  0x6f,0x5b };
1538 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1539  0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1540 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1541  0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1542
1543 static struct UnicodeExpectedResult unicodeResults[] = {
1544  { CERT_RDN_NUMERIC_STRING,   oneW, { sizeof(oneNumeric), oneNumeric } },
1545  { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1546  { CERT_RDN_TELETEX_STRING,   oneW, { sizeof(oneTeletex), oneTeletex } },
1547  { CERT_RDN_VIDEOTEX_STRING,  oneW, { sizeof(oneVideotex), oneVideotex } },
1548  { CERT_RDN_IA5_STRING,       oneW, { sizeof(oneIA5), oneIA5 } },
1549  { CERT_RDN_GRAPHIC_STRING,   oneW, { sizeof(oneGraphic), oneGraphic } },
1550  { CERT_RDN_VISIBLE_STRING,   oneW, { sizeof(oneVisible), oneVisible } },
1551  { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1552  { CERT_RDN_GENERAL_STRING,   oneW, { sizeof(oneGeneral), oneGeneral } },
1553  { CERT_RDN_BMP_STRING,       oneW, { sizeof(oneBMP), oneBMP } },
1554  { CERT_RDN_UTF8_STRING,      oneW, { sizeof(oneUTF8), oneUTF8 } },
1555  { CERT_RDN_BMP_STRING,     nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1556  { CERT_RDN_UTF8_STRING,    nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1557 };
1558
1559 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1560  { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1561  { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1562 };
1563
1564 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1565 {
1566     BYTE *buf = NULL;
1567     DWORD size = 0, i;
1568     BOOL ret;
1569     CERT_NAME_VALUE value;
1570
1571     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1572      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1573     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1574      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1575     /* Have to have a string of some sort */
1576     value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1577     value.Value.pbData = NULL;
1578     value.Value.cbData = 0;
1579     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1580      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1581     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1582      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1583     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1584     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1585      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1586     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1587      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1588     value.dwValueType = CERT_RDN_ANY_TYPE;
1589     value.Value.pbData = (LPBYTE)oneW;
1590     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1591      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1592     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1593      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1594     value.Value.cbData = sizeof(oneW);
1595     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1596      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1597     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1598      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1599     /* An encoded string with specified length isn't good enough either */
1600     value.dwValueType = CERT_RDN_ENCODED_BLOB;
1601     value.Value.pbData = oneUniversal;
1602     value.Value.cbData = sizeof(oneUniversal);
1603     ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1604      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1605     ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1606      "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1607     /* More failure checking */
1608     value.Value.cbData = 0;
1609     for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1610     {
1611         value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1612         value.dwValueType = unicodeErrors[i].valueType;
1613         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1614          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1615         ok(!ret && GetLastError() == unicodeErrors[i].error,
1616          "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1617          unicodeErrors[i].error, GetLastError());
1618         ok(size == unicodeErrors[i].errorIndex,
1619          "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1620          size);
1621     }
1622     /* cbData can be zero if the string is NULL-terminated */
1623     value.Value.cbData = 0;
1624     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1625     {
1626         value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1627         value.dwValueType = unicodeResults[i].valueType;
1628         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1629          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1630         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1631         if (buf)
1632         {
1633             ok(size == unicodeResults[i].encoded.cbData,
1634              "Value type %d: expected size %d, got %d\n",
1635              value.dwValueType, unicodeResults[i].encoded.cbData, size);
1636             ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1637              "Value type %d: unexpected value\n", value.dwValueType);
1638             LocalFree(buf);
1639         }
1640     }
1641     /* These "encode," but they do so by truncating each unicode character
1642      * rather than properly encoding it.  Kept separate from the proper results,
1643      * because the encoded forms won't decode to their original strings.
1644      */
1645     for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1646     {
1647         value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1648         value.dwValueType = unicodeWeirdness[i].valueType;
1649         ret = CryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1650          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1651         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1652         if (buf)
1653         {
1654             ok(size == unicodeWeirdness[i].encoded.cbData,
1655              "Value type %d: expected size %d, got %d\n",
1656              value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1657             ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1658              "Value type %d: unexpected value\n", value.dwValueType);
1659             LocalFree(buf);
1660         }
1661     }
1662 }
1663
1664 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1665 {
1666     if (n <= 0) return 0;
1667     while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1668     return *str1 - *str2;
1669 }
1670
1671 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1672 {
1673     DWORD i;
1674
1675     for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1676     {
1677         BYTE *buf = NULL;
1678         BOOL ret;
1679         DWORD size = 0;
1680
1681         ret = CryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1682          unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1683          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1684         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1685         if (ret && buf)
1686         {
1687             PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1688
1689             ok(value->dwValueType == unicodeResults[i].valueType,
1690              "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1691              value->dwValueType);
1692             ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1693              value->Value.cbData / sizeof(WCHAR)),
1694              "Unexpected decoded value for index %d (value type %d)\n", i,
1695              unicodeResults[i].valueType);
1696             LocalFree(buf);
1697         }
1698     }
1699 }
1700
1701 struct encodedOctets
1702 {
1703     const BYTE *val;
1704     const BYTE *encoded;
1705 };
1706
1707 static const unsigned char bin46[] = { 'h','i',0 };
1708 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1709 static const unsigned char bin48[] = {
1710      's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1711 static const unsigned char bin49[] = {
1712      0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1713 static const unsigned char bin50[] = { 0 };
1714 static const unsigned char bin51[] = { 0x04,0x00,0 };
1715
1716 static const struct encodedOctets octets[] = {
1717     { bin46, bin47 },
1718     { bin48, bin49 },
1719     { bin50, bin51 },
1720 };
1721
1722 static void test_encodeOctets(DWORD dwEncoding)
1723 {
1724     CRYPT_DATA_BLOB blob;
1725     DWORD i;
1726
1727     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1728     {
1729         BYTE *buf = NULL;
1730         BOOL ret;
1731         DWORD bufSize = 0;
1732
1733         blob.cbData = strlen((const char*)octets[i].val);
1734         blob.pbData = (BYTE*)octets[i].val;
1735         ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1736          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1737         ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1738         if (buf)
1739         {
1740             ok(buf[0] == 4,
1741              "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1742             ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1743              buf[1], octets[i].encoded[1]);
1744             ok(!memcmp(buf + 1, octets[i].encoded + 1,
1745              octets[i].encoded[1] + 1), "Got unexpected value\n");
1746             LocalFree(buf);
1747         }
1748     }
1749 }
1750
1751 static void test_decodeOctets(DWORD dwEncoding)
1752 {
1753     DWORD i;
1754
1755     for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1756     {
1757         BYTE *buf = NULL;
1758         BOOL ret;
1759         DWORD bufSize = 0;
1760
1761         ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1762          (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1763          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1764         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1765         ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1766          "Expected size >= %d, got %d\n",
1767            (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1768         ok(buf != NULL, "Expected allocated buffer\n");
1769         if (buf)
1770         {
1771             CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1772
1773             if (blob->cbData)
1774                 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1775                  "Unexpected value\n");
1776             LocalFree(buf);
1777         }
1778     }
1779 }
1780
1781 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1782
1783 struct encodedBits
1784 {
1785     DWORD cUnusedBits;
1786     const BYTE *encoded;
1787     DWORD cbDecoded;
1788     const BYTE *decoded;
1789 };
1790
1791 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1792 static const unsigned char bin53[] = { 0xff,0xff };
1793 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1794 static const unsigned char bin55[] = { 0xff,0xfe };
1795 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1796 static const unsigned char bin57[] = { 0xfe };
1797 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1798
1799 static const struct encodedBits bits[] = {
1800     /* normal test cases */
1801     { 0, bin52, 2, bin53 },
1802     { 1, bin54, 2, bin55 },
1803     /* strange test case, showing cUnusedBits >= 8 is allowed */
1804     { 9, bin56, 1, bin57 },
1805     /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1806     { 17, bin58, 0, NULL },
1807 };
1808
1809 static void test_encodeBits(DWORD dwEncoding)
1810 {
1811     DWORD i;
1812
1813     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1814     {
1815         CRYPT_BIT_BLOB blob;
1816         BOOL ret;
1817         BYTE *buf = NULL;
1818         DWORD bufSize = 0;
1819
1820         blob.cbData = sizeof(bytesToEncode);
1821         blob.pbData = (BYTE *)bytesToEncode;
1822         blob.cUnusedBits = bits[i].cUnusedBits;
1823         ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1824          CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1825         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1826         if (buf)
1827         {
1828             ok(bufSize == bits[i].encoded[1] + 2,
1829              "Got unexpected size %d, expected %d\n", bufSize,
1830              bits[i].encoded[1] + 2);
1831             ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1832              "Unexpected value\n");
1833             LocalFree(buf);
1834         }
1835     }
1836 }
1837
1838 static void test_decodeBits(DWORD dwEncoding)
1839 {
1840     static const BYTE ber[] = "\x03\x02\x01\xff";
1841     static const BYTE berDecoded = 0xfe;
1842     DWORD i;
1843     BOOL ret;
1844     BYTE *buf = NULL;
1845     DWORD bufSize = 0;
1846
1847     /* normal cases */
1848     for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1849     {
1850         ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1851          bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1852          &bufSize);
1853         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1854         if (buf)
1855         {
1856             CRYPT_BIT_BLOB *blob;
1857
1858             ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1859                "Got unexpected size %d\n", bufSize);
1860             blob = (CRYPT_BIT_BLOB *)buf;
1861             ok(blob->cbData == bits[i].cbDecoded,
1862              "Got unexpected length %d, expected %d\n", blob->cbData,
1863              bits[i].cbDecoded);
1864             if (blob->cbData && bits[i].cbDecoded)
1865                 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1866                  "Unexpected value\n");
1867             LocalFree(buf);
1868         }
1869     }
1870     /* special case: check that something that's valid in BER but not in DER
1871      * decodes successfully
1872      */
1873     ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1874      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1875     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1876     if (buf)
1877     {
1878         CRYPT_BIT_BLOB *blob;
1879
1880         ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1881            "Got unexpected size %d\n", bufSize);
1882         blob = (CRYPT_BIT_BLOB *)buf;
1883         ok(blob->cbData == sizeof(berDecoded),
1884            "Got unexpected length %d\n", blob->cbData);
1885         if (blob->cbData)
1886             ok(*blob->pbData == berDecoded, "Unexpected value\n");
1887         LocalFree(buf);
1888     }
1889 }
1890
1891 struct Constraints2
1892 {
1893     CERT_BASIC_CONSTRAINTS2_INFO info;
1894     const BYTE *encoded;
1895 };
1896
1897 static const unsigned char bin59[] = { 0x30,0x00 };
1898 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1899 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1900 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1901 static const struct Constraints2 constraints2[] = {
1902  /* empty constraints */
1903  { { FALSE, FALSE, 0}, bin59 },
1904  /* can be a CA */
1905  { { TRUE,  FALSE, 0}, bin60 },
1906  /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1907   * but that's not the case
1908   */
1909  { { FALSE, TRUE,  0}, bin61 },
1910  /* can be a CA and has path length constraints set */
1911  { { TRUE,  TRUE,  1}, bin62 },
1912 };
1913
1914 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1915 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1916  0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1917  0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1918  0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1919 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1920  0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1921  0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1922  0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1923  0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1924
1925 static void test_encodeBasicConstraints(DWORD dwEncoding)
1926 {
1927     DWORD i, bufSize = 0;
1928     CERT_BASIC_CONSTRAINTS_INFO info;
1929     CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1930      (LPBYTE)encodedDomainName };
1931     BOOL ret;
1932     BYTE *buf = NULL;
1933
1934     /* First test with the simpler info2 */
1935     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1936     {
1937         ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1938          &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1939          &bufSize);
1940         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1941         if (buf)
1942         {
1943             ok(bufSize == constraints2[i].encoded[1] + 2,
1944              "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
1945              bufSize);
1946             ok(!memcmp(buf, constraints2[i].encoded,
1947              constraints2[i].encoded[1] + 2), "Unexpected value\n");
1948             LocalFree(buf);
1949         }
1950     }
1951     /* Now test with more complex basic constraints */
1952     info.SubjectType.cbData = 0;
1953     info.fPathLenConstraint = FALSE;
1954     info.cSubtreesConstraint = 0;
1955     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1956      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1957     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1958     if (buf)
1959     {
1960         ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
1961         ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1962          "Unexpected value\n");
1963         LocalFree(buf);
1964     }
1965     /* None of the certs I examined had any subtree constraint, but I test one
1966      * anyway just in case.
1967      */
1968     info.cSubtreesConstraint = 1;
1969     info.rgSubtreesConstraint = &nameBlob;
1970     ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1971      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1972     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1973     if (buf)
1974     {
1975         ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
1976         ok(!memcmp(buf, constraintWithDomainName,
1977          sizeof(constraintWithDomainName)), "Unexpected value\n");
1978         LocalFree(buf);
1979     }
1980     /* FIXME: test encoding with subject type. */
1981 }
1982
1983 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1984 static const unsigned char encodedCommonName[] = {
1985     0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1986
1987 static void test_decodeBasicConstraints(DWORD dwEncoding)
1988 {
1989     static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1990      0xff };
1991     static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1992     DWORD i;
1993     BOOL ret;
1994     BYTE *buf = NULL;
1995     DWORD bufSize = 0;
1996
1997     /* First test with simpler info2 */
1998     for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1999     {
2000         ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2001          constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2002          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2003         ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2004          GetLastError());
2005         if (buf)
2006         {
2007             CERT_BASIC_CONSTRAINTS2_INFO *info =
2008              (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2009
2010             ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2011              "Unexpected value for item %d\n", i);
2012             LocalFree(buf);
2013         }
2014     }
2015     /* Check with the order of encoded elements inverted */
2016     buf = (PBYTE)1;
2017     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2018      inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2019      &bufSize);
2020     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2021      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2022     ok(!buf, "Expected buf to be set to NULL\n");
2023     /* Check with a non-DER bool */
2024     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2025      badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2026      (BYTE *)&buf, &bufSize);
2027     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2028     if (buf)
2029     {
2030         CERT_BASIC_CONSTRAINTS2_INFO *info =
2031          (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2032
2033         ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2034         LocalFree(buf);
2035     }
2036     /* Check with a non-basic constraints value */
2037     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2038      (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2039      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2040     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2041      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2042     /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2043     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2044      emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2045      (BYTE *)&buf, &bufSize);
2046     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2047     if (buf)
2048     {
2049         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2050
2051         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2052         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2053         ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2054         LocalFree(buf);
2055     }
2056     ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2057      constraintWithDomainName, sizeof(constraintWithDomainName),
2058      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2059     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2060     if (buf)
2061     {
2062         CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2063
2064         ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2065         ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2066         ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2067         if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2068         {
2069             ok(info->rgSubtreesConstraint[0].cbData ==
2070              sizeof(encodedDomainName), "Wrong size %d\n",
2071              info->rgSubtreesConstraint[0].cbData);
2072             ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2073              sizeof(encodedDomainName)), "Unexpected value\n");
2074         }
2075         LocalFree(buf);
2076     }
2077 }
2078
2079 /* These are terrible public keys of course, I'm just testing encoding */
2080 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2081 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2082 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2083 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2084 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2085 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2086 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2087 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2088
2089 struct EncodedRSAPubKey
2090 {
2091     const BYTE *modulus;
2092     size_t modulusLen;
2093     const BYTE *encoded;
2094     size_t decodedModulusLen;
2095 };
2096
2097 struct EncodedRSAPubKey rsaPubKeys[] = {
2098     { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2099     { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2100     { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2101     { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2102 };
2103
2104 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2105 {
2106     BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2107     BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2108     RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2109     BOOL ret;
2110     BYTE *buf = NULL;
2111     DWORD bufSize = 0, i;
2112
2113     /* Try with a bogus blob type */
2114     hdr->bType = 2;
2115     hdr->bVersion = CUR_BLOB_VERSION;
2116     hdr->reserved = 0;
2117     hdr->aiKeyAlg = CALG_RSA_KEYX;
2118     rsaPubKey->magic = 0x31415352;
2119     rsaPubKey->bitlen = sizeof(modulus1) * 8;
2120     rsaPubKey->pubexp = 65537;
2121     memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2122      sizeof(modulus1));
2123
2124     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2125      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2126      &bufSize);
2127     ok(!ret && GetLastError() == E_INVALIDARG,
2128      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2129     /* Now with a bogus reserved field */
2130     hdr->bType = PUBLICKEYBLOB;
2131     hdr->reserved = 1;
2132     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2133      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2134      &bufSize);
2135     if (buf)
2136     {
2137         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2138          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2139         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2140         LocalFree(buf);
2141     }
2142     /* Now with a bogus blob version */
2143     hdr->reserved = 0;
2144     hdr->bVersion = 0;
2145     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2146      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2147      &bufSize);
2148     if (buf)
2149     {
2150         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2151          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2152         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2153         LocalFree(buf);
2154     }
2155     /* And with a bogus alg ID */
2156     hdr->bVersion = CUR_BLOB_VERSION;
2157     hdr->aiKeyAlg = CALG_DES;
2158     ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2159      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2160      &bufSize);
2161     if (buf)
2162     {
2163         ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2164          "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2165         ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2166         LocalFree(buf);
2167     }
2168     /* Check a couple of RSA-related OIDs */
2169     hdr->aiKeyAlg = CALG_RSA_KEYX;
2170     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2171      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2172     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2173      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2174     ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2175      toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2176     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2177      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2178     /* Finally, all valid */
2179     hdr->aiKeyAlg = CALG_RSA_KEYX;
2180     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2181     {
2182         memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2183          rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2184         ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2185          toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2186         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2187         if (buf)
2188         {
2189             ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2190              "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2191              bufSize);
2192             ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2193              "Unexpected value\n");
2194             LocalFree(buf);
2195         }
2196     }
2197 }
2198
2199 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2200 {
2201     DWORD i;
2202     LPBYTE buf = NULL;
2203     DWORD bufSize = 0;
2204     BOOL ret;
2205
2206     /* Try with a bad length */
2207     ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2208      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2209      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2210     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2211      "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2212     /* Try with a couple of RSA-related OIDs */
2213     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2214      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2215      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2216     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2217      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2218     ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2219      rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2220      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2221     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2222      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2223     /* Now try success cases */
2224     for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2225     {
2226         bufSize = 0;
2227         ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2228          rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2229          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2230         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2231         if (buf)
2232         {
2233             BLOBHEADER *hdr = (BLOBHEADER *)buf;
2234             RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2235
2236             ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2237              rsaPubKeys[i].decodedModulusLen,
2238              "Wrong size %d\n", bufSize);
2239             ok(hdr->bType == PUBLICKEYBLOB,
2240              "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2241              hdr->bType);
2242             ok(hdr->bVersion == CUR_BLOB_VERSION,
2243              "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2244              CUR_BLOB_VERSION, hdr->bVersion);
2245             ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2246              hdr->reserved);
2247             ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2248              "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2249             ok(rsaPubKey->magic == 0x31415352,
2250              "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2251             ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2252              "Wrong bit len %d\n", rsaPubKey->bitlen);
2253             ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2254              rsaPubKey->pubexp);
2255             ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2256              rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2257              "Unexpected modulus\n");
2258             LocalFree(buf);
2259         }
2260     }
2261 }
2262
2263 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2264  0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2265  0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2266
2267 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2268  0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2269  0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2270  0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2271
2272 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2273 {
2274     CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2275     CRYPT_SEQUENCE_OF_ANY seq;
2276     DWORD i;
2277     BOOL ret;
2278     BYTE *buf = NULL;
2279     DWORD bufSize = 0;
2280
2281     /* Encode a homogenous sequence */
2282     for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2283     {
2284         blobs[i].cbData = ints[i].encoded[1] + 2;
2285         blobs[i].pbData = (BYTE *)ints[i].encoded;
2286     }
2287     seq.cValue = sizeof(ints) / sizeof(ints[0]);
2288     seq.rgValue = blobs;
2289
2290     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2291      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2292     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2293     if (buf)
2294     {
2295         ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2296         ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2297         LocalFree(buf);
2298     }
2299     /* Change the type of the first element in the sequence, and give it
2300      * another go
2301      */
2302     blobs[0].cbData = times[0].encodedTime[1] + 2;
2303     blobs[0].pbData = (BYTE *)times[0].encodedTime;
2304     ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2305      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2306     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2307     if (buf)
2308     {
2309         ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2310         ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2311          "Unexpected value\n");
2312         LocalFree(buf);
2313     }
2314 }
2315
2316 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2317 {
2318     BOOL ret;
2319     BYTE *buf = NULL;
2320     DWORD bufSize = 0;
2321
2322     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2323      intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2324     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2325     if (buf)
2326     {
2327         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2328         DWORD i;
2329
2330         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2331          "Wrong elements %d\n", seq->cValue);
2332         for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2333         {
2334             ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2335              "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2336              seq->rgValue[i].cbData);
2337             ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2338              ints[i].encoded[1] + 2), "Unexpected value\n");
2339         }
2340         LocalFree(buf);
2341     }
2342     ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2343      mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2344      &bufSize);
2345     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2346     if (buf)
2347     {
2348         CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2349
2350         ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2351          "Wrong elements %d\n", seq->cValue);
2352         /* Just check the first element since it's all that changed */
2353         ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2354          "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2355          seq->rgValue[0].cbData);
2356         ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2357          times[0].encodedTime[1] + 2), "Unexpected value\n");
2358         LocalFree(buf);
2359     }
2360 }
2361
2362 struct encodedExtensions
2363 {
2364     CERT_EXTENSIONS exts;
2365     const BYTE *encoded;
2366 };
2367
2368 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2369 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2370 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2371 static CERT_EXTENSION criticalExt =
2372  { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2373 static CERT_EXTENSION nonCriticalExt =
2374  { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2375
2376 static const BYTE ext0[] = { 0x30,0x00 };
2377 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2378                              0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2379 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2380                              0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2381
2382 static const struct encodedExtensions exts[] = {
2383  { { 0, NULL }, ext0 },
2384  { { 1, &criticalExt }, ext1 },
2385  { { 1, &nonCriticalExt }, ext2 },
2386 };
2387
2388 static void test_encodeExtensions(DWORD dwEncoding)
2389 {
2390     DWORD i;
2391
2392     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2393     {
2394         BOOL ret;
2395         BYTE *buf = NULL;
2396         DWORD bufSize = 0;
2397
2398         ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2399          CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2400         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2401         if (buf)
2402         {
2403             ok(bufSize == exts[i].encoded[1] + 2,
2404              "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2405             ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2406              "Unexpected value\n");
2407             LocalFree(buf);
2408         }
2409     }
2410 }
2411
2412 static void test_decodeExtensions(DWORD dwEncoding)
2413 {
2414     DWORD i;
2415
2416     for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2417     {
2418         BOOL ret;
2419         BYTE *buf = NULL;
2420         DWORD bufSize = 0;
2421
2422         ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2423          exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2424          NULL, (BYTE *)&buf, &bufSize);
2425         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2426         if (buf)
2427         {
2428             CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2429             DWORD j;
2430
2431             ok(ext->cExtension == exts[i].exts.cExtension,
2432              "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2433              ext->cExtension);
2434             for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2435             {
2436                 ok(!strcmp(ext->rgExtension[j].pszObjId,
2437                  exts[i].exts.rgExtension[j].pszObjId),
2438                  "Expected OID %s, got %s\n",
2439                  exts[i].exts.rgExtension[j].pszObjId,
2440                  ext->rgExtension[j].pszObjId);
2441                 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2442                  exts[i].exts.rgExtension[j].Value.pbData,
2443                  exts[i].exts.rgExtension[j].Value.cbData),
2444                  "Unexpected value\n");
2445             }
2446             LocalFree(buf);
2447         }
2448     }
2449 }
2450
2451 /* MS encodes public key info with a NULL if the algorithm identifier's
2452  * parameters are empty.  However, when encoding an algorithm in a CERT_INFO,
2453  * it encodes them by omitting the algorithm parameters.  This latter approach
2454  * seems more correct, so accept either form.
2455  */
2456 struct encodedPublicKey
2457 {
2458     CERT_PUBLIC_KEY_INFO info;
2459     const BYTE *encoded;
2460     const BYTE *encodedNoNull;
2461     CERT_PUBLIC_KEY_INFO decoded;
2462 };
2463
2464 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2465  0xe, 0xf };
2466 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2467
2468 static const unsigned char bin64[] = {
2469     0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2470 static const unsigned char bin65[] = {
2471     0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2472 static const unsigned char bin66[] = {
2473     0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2474 static const unsigned char bin67[] = {
2475     0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2476 static const unsigned char bin68[] = {
2477     0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2478     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2479 static const unsigned char bin69[] = {
2480     0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2481     0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2482 static const unsigned char bin70[] = {
2483     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2484     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2485     0x0f};
2486 static const unsigned char bin71[] = {
2487     0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2488     0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2489     0x0f};
2490 static unsigned char bin72[] = { 0x05,0x00};
2491
2492 static CHAR oid_bogus[] = "1.2.3",
2493             oid_rsa[]   = szOID_RSA;
2494
2495 static const struct encodedPublicKey pubKeys[] = {
2496  /* with a bogus OID */
2497  { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2498   bin64, bin65,
2499   { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2500  /* some normal keys */
2501  { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2502   bin66, bin67,
2503   { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2504  { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2505   bin68, bin69,
2506   { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2507  /* with add'l parameters--note they must be DER-encoded */
2508  { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2509   (BYTE *)aKey, 0 } },
2510   bin70, bin71,
2511   { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2512   (BYTE *)aKey, 0 } } },
2513 };
2514
2515 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2516 {
2517     DWORD i;
2518
2519     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2520     {
2521         BOOL ret;
2522         BYTE *buf = NULL;
2523         DWORD bufSize = 0;
2524
2525         ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2526          &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2527          &bufSize);
2528         ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2529         if (buf)
2530         {
2531             ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2532              bufSize == pubKeys[i].encodedNoNull[1] + 2,
2533              "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2534              pubKeys[i].encodedNoNull[1] + 2, bufSize);
2535             if (bufSize == pubKeys[i].encoded[1] + 2)
2536                 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2537                  "Unexpected value\n");
2538             else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2539                 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2540                  pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2541             LocalFree(buf);
2542         }
2543     }
2544 }
2545
2546 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2547  const CERT_PUBLIC_KEY_INFO *got)
2548 {
2549     ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2550      "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2551      got->Algorithm.pszObjId);
2552     ok(expected->Algorithm.Parameters.cbData ==
2553      got->Algorithm.Parameters.cbData,
2554      "Expected parameters of %d bytes, got %d\n",
2555      expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2556     if (expected->Algorithm.Parameters.cbData)
2557         ok(!memcmp(expected->Algorithm.Parameters.pbData,
2558          got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2559          "Unexpected algorithm parameters\n");
2560     ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2561      "Expected public key of %d bytes, got %d\n",
2562      expected->PublicKey.cbData, got->PublicKey.cbData);
2563     if (expected->PublicKey.cbData)
2564         ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2565          got->PublicKey.cbData), "Unexpected public key value\n");
2566 }
2567
2568 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2569 {
2570     static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2571      0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2572      0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2573      0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2574     DWORD i;
2575     BOOL ret;
2576     BYTE *buf = NULL;
2577     DWORD bufSize = 0;
2578
2579     for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2580     {
2581         /* The NULL form decodes to the decoded member */
2582         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2583          pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2584          NULL, (BYTE *)&buf, &bufSize);
2585         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2586         if (buf)
2587         {
2588             comparePublicKeyInfo(&pubKeys[i].decoded,
2589              (CERT_PUBLIC_KEY_INFO *)buf);
2590             LocalFree(buf);
2591         }
2592         /* The non-NULL form decodes to the original */
2593         ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2594          pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2595          CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2596         ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2597         if (buf)
2598         {
2599             comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2600             LocalFree(buf);
2601         }
2602     }
2603     /* Test with bogus (not valid DER) parameters */
2604     ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2605      bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2606      NULL, (BYTE *)&buf, &bufSize);
2607     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2608      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2609 }
2610
2611 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2612  0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2613  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2614  0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2615  0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2616 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2617  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2618  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2619  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2620  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2621 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2622  0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2623  0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2624  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2625  0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2626 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2627  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2628  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2629  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2630  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2631  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2632  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2633 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2634  0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2635  0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2636  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2637  0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2638  0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2639  0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2640 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2641  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2642  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2643  0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2644  0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2645  0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2646  0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2647  0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2648  0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2649  0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2650
2651 static const BYTE serialNum[] = { 0x01 };
2652
2653 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2654 {
2655     BOOL ret;
2656     BYTE *buf = NULL;
2657     DWORD size = 0;
2658     CERT_INFO info = { 0 };
2659
2660     /* Test with NULL pvStructInfo */
2661     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2662      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2663     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2664      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2665     /* Test with a V1 cert */
2666     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2667      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2668     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2669     if (buf)
2670     {
2671         ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2672          v1Cert[1] + 2, size);
2673         ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2674         LocalFree(buf);
2675     }
2676     /* Test v2 cert */
2677     info.dwVersion = CERT_V2;
2678     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2679      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2680     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2681     if (buf)
2682     {
2683         ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2684         ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2685         LocalFree(buf);
2686     }
2687     /* Test v3 cert */
2688     info.dwVersion = CERT_V3;
2689     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2690      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2691     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2692     if (buf)
2693     {
2694         ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2695         ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2696         LocalFree(buf);
2697     }
2698     /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2699      * API doesn't prevent it)
2700      */
2701     info.dwVersion = CERT_V1;
2702     info.cExtension = 1;
2703     info.rgExtension = &criticalExt;
2704     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2705      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2706     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2707     if (buf)
2708     {
2709         ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2710         ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2711         LocalFree(buf);
2712     }
2713     /* test v1 cert with a serial number */
2714     info.SerialNumber.cbData = sizeof(serialNum);
2715     info.SerialNumber.pbData = (BYTE *)serialNum;
2716     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2717      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2718     if (buf)
2719     {
2720         ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2721         ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2722         LocalFree(buf);
2723     }
2724     /* Test v1 cert with an issuer name, a subject name, and a serial number */
2725     info.Issuer.cbData = sizeof(encodedCommonName);
2726     info.Issuer.pbData = (BYTE *)encodedCommonName;
2727     info.Subject.cbData = sizeof(encodedCommonName);
2728     info.Subject.pbData = (BYTE *)encodedCommonName;
2729     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2730      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2731     if (buf)
2732     {
2733         ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2734         ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2735         LocalFree(buf);
2736     }
2737     /* for now, I let more interesting tests be done for each subcomponent,
2738      * rather than retesting them all here.
2739      */
2740 }
2741
2742 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2743 {
2744     static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2745      v1CertWithConstraints, v1CertWithSerial };
2746     BOOL ret;
2747     BYTE *buf = NULL;
2748     DWORD size = 0, i;
2749
2750     /* Test with NULL pbEncoded */
2751     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2752      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2753     ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2754      "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2755     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2756      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2757     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2758      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2759     /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2760      * minimum a cert must have a non-zero serial number, an issuer, and a
2761      * subject.
2762      */
2763     for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2764     {
2765         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2766          corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2767          (BYTE *)&buf, &size);
2768         ok(!ret, "Expected failure\n");
2769     }
2770     /* Now check with serial number, subject and issuer specified */
2771     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2772      sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2773     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2774     if (buf)
2775     {
2776         CERT_INFO *info = (CERT_INFO *)buf;
2777
2778         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2779         ok(info->SerialNumber.cbData == 1,
2780          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2781         ok(*info->SerialNumber.pbData == *serialNum,
2782          "Expected serial number %d, got %d\n", *serialNum,
2783          *info->SerialNumber.pbData);
2784         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2785          "Wrong size %d\n", info->Issuer.cbData);
2786         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2787          "Unexpected issuer\n");
2788         ok(info->Subject.cbData == sizeof(encodedCommonName),
2789          "Wrong size %d\n", info->Subject.cbData);
2790         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2791          info->Subject.cbData), "Unexpected subject\n");
2792         LocalFree(buf);
2793     }
2794 }
2795
2796 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2797  0xe, 0xf };
2798
2799 static const BYTE signedBigCert[] = {
2800  0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2801  0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2802  0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2803  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2804  0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2805  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2806  0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2807  0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2808  0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2809  0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2810  0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2811  0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2812
2813 static void test_encodeCert(DWORD dwEncoding)
2814 {
2815     /* Note the SignatureAlgorithm must match that in the encoded cert.  Note
2816      * also that bigCert is a NULL-terminated string, so don't count its
2817      * last byte (otherwise the signed cert won't decode.)
2818      */
2819     CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2820      { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2821     BOOL ret;
2822     BYTE *buf = NULL;
2823     DWORD bufSize = 0;
2824
2825     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2826      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2827     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2828     if (buf)
2829     {
2830         ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
2831         ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2832         LocalFree(buf);
2833     }
2834 }
2835
2836 static void test_decodeCert(DWORD dwEncoding)
2837 {
2838     BOOL ret;
2839     BYTE *buf = NULL;
2840     DWORD size = 0;
2841
2842     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2843      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2844     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2845     if (buf)
2846     {
2847         CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2848
2849         ok(info->ToBeSigned.cbData == sizeof(bigCert),
2850          "Wrong cert size %d\n", info->ToBeSigned.cbData);
2851         ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2852          "Unexpected cert\n");
2853         ok(info->Signature.cbData == sizeof(hash),
2854          "Wrong signature size %d\n", info->Signature.cbData);
2855         ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2856          "Unexpected signature\n");
2857         LocalFree(buf);
2858     }
2859     /* A signed cert decodes as a CERT_INFO too */
2860     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
2861      sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2862     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2863     if (buf)
2864     {
2865         CERT_INFO *info = (CERT_INFO *)buf;
2866
2867         ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2868         ok(info->SerialNumber.cbData == 1,
2869          "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2870         ok(*info->SerialNumber.pbData == *serialNum,
2871          "Expected serial number %d, got %d\n", *serialNum,
2872          *info->SerialNumber.pbData);
2873         ok(info->Issuer.cbData == sizeof(encodedCommonName),
2874          "Wrong size %d\n", info->Issuer.cbData);
2875         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2876          "Unexpected issuer\n");
2877         ok(info->Subject.cbData == sizeof(encodedCommonName),
2878          "Wrong size %d\n", info->Subject.cbData);
2879         ok(!memcmp(info->Subject.pbData, encodedCommonName,
2880          info->Subject.cbData), "Unexpected subject\n");
2881         LocalFree(buf);
2882     }
2883 }
2884
2885 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2886 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2887  0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2888  0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2889 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2890  0x00, 0x03 };
2891 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2892  0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2893  0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2894 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2895  0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2896  0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2897  0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2898  0x2e, 0x6f, 0x72, 0x67 };
2899 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2900  CRL_REASON_AFFILIATION_CHANGED;
2901
2902 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2903 {
2904     CRL_DIST_POINTS_INFO info = { 0 };
2905     CRL_DIST_POINT point = { { 0 } };
2906     CERT_ALT_NAME_ENTRY entry = { 0 };
2907     BOOL ret;
2908     BYTE *buf = NULL;
2909     DWORD size = 0;
2910
2911     /* Test with an empty info */
2912     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2913      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2914     ok(!ret && GetLastError() == E_INVALIDARG,
2915      "Expected E_INVALIDARG, got %08x\n", GetLastError());
2916     /* Test with one empty dist point */
2917     info.cDistPoint = 1;
2918     info.rgDistPoint = &point;
2919     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2920      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2921     if (buf)
2922     {
2923         ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
2924         ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2925         LocalFree(buf);
2926     }
2927     /* A dist point with an invalid name */
2928     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2929     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2930     U(entry).pwszURL = (LPWSTR)nihongoURL;
2931     U(point.DistPointName).FullName.cAltEntry = 1;
2932     U(point.DistPointName).FullName.rgAltEntry = &entry;
2933     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2934      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2935     ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2936      "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
2937     /* The first invalid character is at index 7 */
2938     ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2939      "Expected invalid char at index 7, got %d\n",
2940      GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2941     /* A dist point with (just) a valid name */
2942     U(entry).pwszURL = (LPWSTR)url;
2943     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2944      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2945     if (buf)
2946     {
2947         ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
2948         ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2949         LocalFree(buf);
2950     }
2951     /* A dist point with (just) reason flags */
2952     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2953     point.ReasonFlags.cbData = sizeof(crlReason);
2954     point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2955     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2956      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2957     if (buf)
2958     {
2959         ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
2960         ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2961         LocalFree(buf);
2962     }
2963     /* A dist point with just an issuer */
2964     point.ReasonFlags.cbData = 0;
2965     point.CRLIssuer.cAltEntry = 1;
2966     point.CRLIssuer.rgAltEntry = &entry;
2967     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2968      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2969     if (buf)
2970     {
2971         ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
2972         ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2973         LocalFree(buf);
2974     }
2975     /* A dist point with both a name and an issuer */
2976     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2977     ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2978      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2979     if (buf)
2980     {
2981         ok(size == sizeof(distPointWithUrlAndIssuer),
2982          "Wrong size %d\n", size);
2983         ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2984         LocalFree(buf);
2985     }
2986 }
2987
2988 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2989 {
2990     BOOL ret;
2991     BYTE *buf = NULL;
2992     DWORD size = 0;
2993     PCRL_DIST_POINTS_INFO info;
2994     PCRL_DIST_POINT point;
2995     PCERT_ALT_NAME_ENTRY entry;
2996
2997     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2998      emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2999      (BYTE *)&buf, &size);
3000     if (ret)
3001     {
3002         info = (PCRL_DIST_POINTS_INFO)buf;
3003         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3004          "Wrong size %d\n", size);
3005         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3006          info->cDistPoint);
3007         point = info->rgDistPoint;
3008         ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3009          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3010          point->DistPointName.dwDistPointNameChoice);
3011         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3012         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3013         LocalFree(buf);
3014     }
3015     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3016      distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3017      (BYTE *)&buf, &size);
3018     if (ret)
3019     {
3020         info = (PCRL_DIST_POINTS_INFO)buf;
3021         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3022          "Wrong size %d\n", size);
3023         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3024          info->cDistPoint);
3025         point = info->rgDistPoint;
3026         ok(point->DistPointName.dwDistPointNameChoice ==
3027          CRL_DIST_POINT_FULL_NAME,
3028          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3029          point->DistPointName.dwDistPointNameChoice);
3030         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3031          "Expected 1 name entry, got %d\n",
3032          U(point->DistPointName).FullName.cAltEntry);
3033         entry = U(point->DistPointName).FullName.rgAltEntry;
3034         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3035          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3036         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3037         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3038         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3039         LocalFree(buf);
3040     }
3041     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3042      distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3043      NULL, (BYTE *)&buf, &size);
3044     if (ret)
3045     {
3046         info = (PCRL_DIST_POINTS_INFO)buf;
3047         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3048          "Wrong size %d\n", size);
3049         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3050          info->cDistPoint);
3051         point = info->rgDistPoint;
3052         ok(point->DistPointName.dwDistPointNameChoice ==
3053          CRL_DIST_POINT_NO_NAME,
3054          "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3055          point->DistPointName.dwDistPointNameChoice);
3056         ok(point->ReasonFlags.cbData == sizeof(crlReason),
3057          "Expected reason length\n");
3058         ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3059          "Unexpected reason\n");
3060         ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3061         LocalFree(buf);
3062     }
3063     ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3064      distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3065      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3066     if (ret)
3067     {
3068         info = (PCRL_DIST_POINTS_INFO)buf;
3069         ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3070          "Wrong size %d\n", size);
3071         ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3072          info->cDistPoint);
3073         point = info->rgDistPoint;
3074         ok(point->DistPointName.dwDistPointNameChoice ==
3075          CRL_DIST_POINT_FULL_NAME,
3076          "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3077          point->DistPointName.dwDistPointNameChoice);
3078         ok(U(point->DistPointName).FullName.cAltEntry == 1,
3079          "Expected 1 name entry, got %d\n",
3080          U(point->DistPointName).FullName.cAltEntry);
3081         entry = U(point->DistPointName).FullName.rgAltEntry;
3082         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3083          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3084         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3085         ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3086         ok(point->CRLIssuer.cAltEntry == 1,
3087          "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3088         entry = point->CRLIssuer.rgAltEntry;
3089         ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3090          "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3091         ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3092         LocalFree(buf);
3093     }
3094 }
3095
3096 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3097 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3098 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3099  0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3100  0x67 };
3101
3102 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3103 {
3104     BOOL ret;
3105     BYTE *buf = NULL;
3106     DWORD size = 0;
3107     CRL_ISSUING_DIST_POINT point = { { 0 } };
3108     CERT_ALT_NAME_ENTRY entry;
3109
3110     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3111      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3112     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3113     {
3114         skip("no X509_ISSUING_DIST_POINT encode support\n");
3115         return;
3116     }
3117     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3118      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3119     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3120      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3121     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3122     if (buf)
3123     {
3124         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3125         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3126         LocalFree(buf);
3127     }
3128     /* nonsensical flags */
3129     point.fOnlyContainsUserCerts = TRUE;
3130     point.fOnlyContainsCACerts = TRUE;
3131     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3132      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3133     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3134     if (buf)
3135     {
3136         ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3137         ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3138         LocalFree(buf);
3139     }
3140     /* unimplemented name type */
3141     point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3142     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3143     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3144      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3145     ok(!ret && GetLastError() == E_INVALIDARG,
3146      "Expected E_INVALIDARG, got %08x\n", GetLastError());
3147     /* empty name */
3148     point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3149     U(point.DistPointName).FullName.cAltEntry = 0;
3150     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3151      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3152     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3153     if (buf)
3154     {
3155         ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3156         ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3157         LocalFree(buf);
3158     }
3159     /* name with URL entry */
3160     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3161     U(entry).pwszURL = (LPWSTR)url;
3162     U(point.DistPointName).FullName.cAltEntry = 1;
3163     U(point.DistPointName).FullName.rgAltEntry = &entry;
3164     ret = CryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3165      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3166     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3167     if (buf)
3168     {
3169         ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3170         ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3171         LocalFree(buf);
3172     }
3173 }
3174
3175 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3176  const CERT_ALT_NAME_ENTRY *got)
3177 {
3178     ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3179      "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3180      got->dwAltNameChoice);
3181     if (expected->dwAltNameChoice == got->dwAltNameChoice)
3182     {
3183         switch (got->dwAltNameChoice)
3184         {
3185         case CERT_ALT_NAME_RFC822_NAME:
3186         case CERT_ALT_NAME_DNS_NAME:
3187         case CERT_ALT_NAME_EDI_PARTY_NAME:
3188         case CERT_ALT_NAME_URL:
3189         case CERT_ALT_NAME_REGISTERED_ID:
3190             ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3191                !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), "Unexpected name\n");
3192             break;
3193         case CERT_ALT_NAME_X400_ADDRESS:
3194         case CERT_ALT_NAME_DIRECTORY_NAME:
3195         case CERT_ALT_NAME_IP_ADDRESS:
3196             ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3197                "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3198             ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3199                        U(*got).IPAddress.cbData), "Unexpected value\n");
3200             break;
3201         }
3202     }
3203 }
3204
3205 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3206  const CERT_ALT_NAME_INFO *got)
3207 {
3208     DWORD i;
3209
3210     ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3211      expected->cAltEntry, got->cAltEntry);
3212     for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3213         compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3214 }
3215
3216 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3217  const CRL_DIST_POINT_NAME *got)
3218 {
3219     ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3220      "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3221     if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3222         compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3223 }
3224
3225 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3226  const CRL_ISSUING_DIST_POINT *got)
3227 {
3228     compareDistPointName(&expected->DistPointName, &got->DistPointName);
3229     ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3230      "Unexpected fOnlyContainsUserCerts\n");
3231     ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3232      "Unexpected fOnlyContainsCACerts\n");
3233     ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3234      "Unexpected reason flags\n");
3235     ok(got->fIndirectCRL == expected->fIndirectCRL,
3236      "Unexpected fIndirectCRL\n");
3237 }
3238
3239 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3240 {
3241     BOOL ret;
3242     BYTE *buf = NULL;
3243     DWORD size = 0;
3244     CRL_ISSUING_DIST_POINT point = { { 0 } };
3245
3246     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3247      emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3248      (BYTE *)&buf, &size);
3249     if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3250     {
3251         skip("no X509_ISSUING_DIST_POINT decode support\n");
3252         return;
3253     }
3254     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3255     if (ret)
3256     {
3257         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3258         LocalFree(buf);
3259     }
3260     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3261      badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3262      (BYTE *)&buf, &size);
3263     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3264     if (ret)
3265     {
3266         point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3267         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3268         LocalFree(buf);
3269     }
3270     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3271      emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3272      (BYTE *)&buf, &size);
3273     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3274     if (ret)
3275     {
3276         point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3277         point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3278         U(point.DistPointName).FullName.cAltEntry = 0;
3279         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3280         LocalFree(buf);
3281     }
3282     ret = CryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3283      urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3284     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3285     if (ret)
3286     {
3287         CERT_ALT_NAME_ENTRY entry;
3288
3289         entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3290         U(entry).pwszURL = (LPWSTR)url;
3291         U(point.DistPointName).FullName.cAltEntry = 1;
3292         U(point.DistPointName).FullName.rgAltEntry = &entry;
3293         compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3294         LocalFree(buf);
3295     }
3296 }
3297
3298 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3299  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3300  0x30, 0x5a };
3301 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3302  0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3303  0x30, 0x30, 0x30, 0x30, 0x5a };
3304 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3305  0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3306  0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3307  0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3308  0x5a };
3309 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3310  0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3311  0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3312  0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3313  0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3314  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3315 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3316  0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3317  0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3318  0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3319  0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3320  0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3321 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3322  0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3323  0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3324  0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3325  0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3326  0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3327  0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3328 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3329  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3330  0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3331  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3332  0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3333  0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3334  0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3335 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3336  0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3337  0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3338  0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3339  0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3340  0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3341  0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3342 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3343  0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3344  0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3345  0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3346  0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3347  0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3348  0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3349
3350 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3351 {
3352     BOOL ret;
3353     BYTE *buf = NULL;
3354     static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3355     DWORD size = 0;
3356     CRL_INFO info = { 0 };
3357     CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3358     CERT_EXTENSION ext;
3359
3360     /* Test with a V1 CRL */
3361     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3362      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3363     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3364     if (buf)
3365     {
3366         ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3367         ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3368         LocalFree(buf);
3369     }
3370     /* Test v2 CRL */
3371     info.dwVersion = CRL_V2;
3372     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3373      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3374     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3375     if (buf)
3376     {
3377         ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3378          v2CRL[1] + 2, size);
3379         ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3380         LocalFree(buf);
3381     }
3382     /* v1 CRL with a name */
3383     info.dwVersion = CRL_V1;
3384     info.Issuer.cbData = sizeof(encodedCommonName);
3385     info.Issuer.pbData = (BYTE *)encodedCommonName;
3386     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3387      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3388     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3389     if (buf)
3390     {
3391         ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3392         ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3393         LocalFree(buf);
3394     }
3395     /* v1 CRL with a name and a NULL entry pointer */
3396     info.cCRLEntry = 1;
3397     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3398      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3399     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3400      "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3401     /* now set an empty entry */
3402     info.rgCRLEntry = &entry;
3403     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3404      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3405     if (buf)
3406     {
3407         ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3408          "Wrong size %d\n", size);
3409         ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3410          "Got unexpected value\n");
3411         LocalFree(buf);
3412     }
3413     /* an entry with a serial number */
3414     entry.SerialNumber.cbData = sizeof(serialNum);
3415     entry.SerialNumber.pbData = (BYTE *)serialNum;
3416     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3417      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3418     if (buf)
3419     {
3420         ok(size == sizeof(v1CRLWithIssuerAndEntry),
3421          "Wrong size %d\n", size);
3422         ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3423          "Got unexpected value\n");
3424         LocalFree(buf);
3425     }
3426     /* an entry with an extension */
3427     entry.cExtension = 1;
3428     entry.rgExtension = &criticalExt;
3429     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3430      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3431     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3432     if (buf)
3433     {
3434         ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3435         ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3436         LocalFree(buf);
3437     }
3438     /* a CRL with an extension */
3439     entry.cExtension = 0;
3440     info.cExtension = 1;
3441     info.rgExtension = &criticalExt;
3442     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3443      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3444     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3445     if (buf)
3446     {
3447         ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3448         ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3449         LocalFree(buf);
3450     }
3451     /* a v2 CRL with an extension, this time non-critical */
3452     info.dwVersion = CRL_V2;
3453     info.rgExtension = &nonCriticalExt;
3454     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3455      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3456     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3457     if (buf)
3458     {
3459         ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3460         ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3461         LocalFree(buf);
3462     }
3463     /* a v2 CRL with an issuing dist point extension */
3464     ext.pszObjId = oid_issuing_dist_point;
3465     ext.fCritical = TRUE;
3466     ext.Value.cbData = sizeof(urlIDP);
3467     ext.Value.pbData = (LPBYTE)urlIDP;
3468     entry.rgExtension = &ext;
3469     ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3470      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3471     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3472     if (buf)
3473     {
3474         ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3475         ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3476         LocalFree(buf);
3477     }
3478 }
3479
3480 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3481  0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3482  0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3483  0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3484  0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3485  0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3486  0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3487  0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3488  0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3489  0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3490  0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3491  0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3492  0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3493  0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3494  0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3495  0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3496  0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3497  0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3498  0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3499  0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3500  0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3501  0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3502  0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3503  0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3504  0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3505  0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3506  0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3507  0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3508  0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3509  0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3510  0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3511  0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3512  0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3513  0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3514  0xcd };
3515 static const BYTE verisignCRLWithLotsOfEntries[] = {
3516 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3517 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3518 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3519 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3520 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3521 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3522 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3523 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3524 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3525 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3526 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3527 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3528 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3529 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3530 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3531 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3532 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3533 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3534 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3535 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3536 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3537 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3538 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3539 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3540 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3541 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3542 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3543 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3544 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3545 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3546 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3547 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3548 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3549 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3550 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3551 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3552 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3553 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3554 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3555 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3556 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3557 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3558 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3559 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3560 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3561 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3562 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3563 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3564 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3565 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3566 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3567 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3568 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3569 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3570 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3571 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3572 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3573 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3574 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3575 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3576 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3577 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3578 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3579 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3580 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3581 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3582 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3583 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3584 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3585 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3586 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3587 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3588 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3589 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3590 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3591 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3592 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3593 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3594 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3595 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3596 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3597 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3598 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3599 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3600 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3601 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3602 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3603 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3604 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3605 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3606 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3607 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3608 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3609 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3610 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3611 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3612 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3613 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3614 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3615 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3616 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3617 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3618 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3619 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3620 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3621 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3622 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3623 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3624 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3625 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3626 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3627 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3628 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3629 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3630 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3631 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3632 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3633 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3634 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3635 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3636 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3637 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3638 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3639 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3640 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3641 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3642 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3643 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3644 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3645 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3646 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3647 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3648 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3649 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3650 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3651 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3652 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3653 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3654 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3655 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3656 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3657 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3658 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3659 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3660 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3661 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3662 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3663 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3664 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3665 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3666 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3667 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3668 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3669 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3670 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3671 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3672 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3673 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3674 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3675 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3676 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3677 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3678 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3679 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3680 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3681 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3682 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3683 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3684 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3685 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3686 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3687 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3688 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3689 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3690 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3691 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3692 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3693 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3694 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3695 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3696 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3697 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3698 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3699 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3700 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3701 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3702 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3703 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3704 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3705 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3706 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3707 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3708 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3709 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3710 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3711 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3712 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3713 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3714 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3715 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3716 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3717 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3718 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3719 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3720 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3721 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3722 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3723 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3724 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3725 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3726 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3727 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3728 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3729 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3730 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3731 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3732 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3733 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3734 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3735 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3736 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3737 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3738 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3739 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3740 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3741 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3742 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3743 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3744 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3745 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3746 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3747 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3748 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3749 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3750 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3751 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3752 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3753 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3754 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3755 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3756 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3757 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3758 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3759 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3760 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3761 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3762 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3763 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3764 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3765 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3766 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3767 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3768 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3769 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3770 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3771 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3772 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3773 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3774 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3775 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3776 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3777 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3778 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3779 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3780 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3781 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3782 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3783 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3784 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3785 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
3786 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
3787 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
3788 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
3789 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
3790 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
3791 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
3792 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
3793 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
3794 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
3795 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
3796 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
3797 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
3798 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
3799 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
3800 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
3801 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
3802 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
3803 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
3804 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
3805 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
3806 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
3807 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
3808 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
3809 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
3810 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
3811 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
3812 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
3813 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
3814 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
3815 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
3816 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
3817 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
3818 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
3819 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
3820 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
3821 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
3822 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
3823 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
3824 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
3825 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
3826 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
3827 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
3828 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
3829 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
3830 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
3831 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
3832 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
3833 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
3834 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
3835 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
3836 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
3837 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
3838 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
3839 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
3840 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
3841 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
3842 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
3843 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
3844 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
3845 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
3846 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
3847 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
3848 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
3849 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
3850 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
3851 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
3852 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
3853 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
3854 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
3855 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
3856 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
3857 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
3858 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
3859 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
3860 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
3861 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
3862 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
3863 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
3864 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
3865 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
3866 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
3867 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
3868 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
3869 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
3870 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
3871 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
3872 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
3873 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
3874 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
3875 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
3876 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
3877 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
3878 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
3879 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
3880 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
3881 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
3882 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
3883 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
3884 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
3885 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
3886 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
3887 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
3888 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
3889 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
3890 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
3891 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
3892 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
3893 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
3894 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
3895 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
3896 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
3897 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
3898 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
3899 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
3900 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
3901 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
3902 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
3903 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
3904 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
3905 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
3906 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
3907 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
3908 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
3909 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
3910 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
3911 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
3912 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
3913 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
3914 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
3915 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
3916 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
3917 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
3918 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
3919 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
3920 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
3921 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
3922 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
3923 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
3924 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
3925 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
3926 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
3927 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
3928 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
3929 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
3930 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
3931 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
3932 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
3933 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
3934 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
3935 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
3936 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
3937 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
3938 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
3939 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
3940 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
3941 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
3942 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
3943 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
3944 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
3945 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
3946 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
3947 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
3948 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
3949 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
3950 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
3951 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
3952 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
3953 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
3954 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
3955 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
3956 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
3957 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
3958 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
3959 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
3960 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
3961 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
3962 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
3963 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
3964 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
3965 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
3966 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
3967 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
3968 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
3969 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
3970 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
3971 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
3972 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
3973 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
3974 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
3975 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
3976 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
3977 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
3978 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
3979 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
3980 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
3981 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
3982 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
3983 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
3984 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
3985 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
3986 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
3987 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
3988 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
3989 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
3990 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
3991 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
3992 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
3993 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
3994 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
3995 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
3996 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
3997 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
3998 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
3999 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4000 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4001 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4002 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4003 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4004 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4005 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4006 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4007 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4008 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4009 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4010 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4011 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4012 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4013 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4014 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4015 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4016 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4017 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4018 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4019 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4020 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4021 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4022 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4023 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4024
4025 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4026 {
4027     static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4028     BOOL ret;
4029     BYTE *buf = NULL;
4030     DWORD size = 0, i;
4031
4032     for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4033     {
4034         ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4035          corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4036          (BYTE *)&buf, &size);
4037         ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4038          "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4039     }
4040     /* at a minimum, a CRL must contain an issuer: */
4041     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4042      v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4043      (BYTE *)&buf, &size);
4044     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4045     if (buf)
4046     {
4047         CRL_INFO *info = (CRL_INFO *)buf;
4048
4049         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4050         ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4051          info->cCRLEntry);
4052         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4053          "Wrong issuer size %d\n", info->Issuer.cbData);
4054         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4055          "Unexpected issuer\n");
4056         LocalFree(buf);
4057     }
4058     /* check decoding with an empty CRL entry */
4059     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4060      v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4061      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4062     todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4063      "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4064     /* with a real CRL entry */
4065     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4066      v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4067      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4068     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4069     if (buf)
4070     {
4071         CRL_INFO *info = (CRL_INFO *)buf;
4072         CRL_ENTRY *entry;
4073
4074         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4075         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4076          info->cCRLEntry);
4077         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4078         entry = info->rgCRLEntry;
4079         ok(entry->SerialNumber.cbData == 1,
4080          "Expected serial number size 1, got %d\n",
4081          entry->SerialNumber.cbData);
4082         ok(*entry->SerialNumber.pbData == *serialNum,
4083          "Expected serial number %d, got %d\n", *serialNum,
4084          *entry->SerialNumber.pbData);
4085         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4086          "Wrong issuer size %d\n", info->Issuer.cbData);
4087         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4088          "Unexpected issuer\n");
4089     }
4090     /* a real CRL from verisign that has extensions */
4091     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4092      verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4093      NULL, (BYTE *)&buf, &size);
4094     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4095     if (buf)
4096     {
4097         CRL_INFO *info = (CRL_INFO *)buf;
4098         CRL_ENTRY *entry;
4099
4100         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4101         ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4102          info->cCRLEntry);
4103         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4104         entry = info->rgCRLEntry;
4105         ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4106          info->cExtension);
4107         LocalFree(buf);
4108     }
4109     /* another real CRL from verisign that has lots of entries */
4110     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4111      verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4112      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4113     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4114     if (buf)
4115     {
4116         CRL_INFO *info = (CRL_INFO *)buf;
4117
4118         ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4119         ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4120          info->cCRLEntry);
4121         ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4122          info->cExtension);
4123         LocalFree(buf);
4124     }
4125     /* and finally, with an extension */
4126     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4127      v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4128      NULL, (BYTE *)&buf, &size);
4129     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4130     if (buf)
4131     {
4132         CRL_INFO *info = (CRL_INFO *)buf;
4133         CRL_ENTRY *entry;
4134
4135         ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4136         ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4137          info->cCRLEntry);
4138         ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4139         entry = info->rgCRLEntry;
4140         ok(entry->SerialNumber.cbData == 1,
4141          "Expected serial number size 1, got %d\n",
4142          entry->SerialNumber.cbData);
4143         ok(*entry->SerialNumber.pbData == *serialNum,
4144          "Expected serial number %d, got %d\n", *serialNum,
4145          *entry->SerialNumber.pbData);
4146         ok(info->Issuer.cbData == sizeof(encodedCommonName),
4147          "Wrong issuer size %d\n", info->Issuer.cbData);
4148         ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4149          "Unexpected issuer\n");
4150         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4151          info->cExtension);
4152     }
4153     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4154      v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4155      NULL, (BYTE *)&buf, &size);
4156     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4157     if (buf)
4158     {
4159         CRL_INFO *info = (CRL_INFO *)buf;
4160
4161         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4162          info->cExtension);
4163         LocalFree(buf);
4164     }
4165     /* And again, with an issuing dist point */
4166     ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4167      v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4168      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4169     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4170     if (buf)
4171     {
4172         CRL_INFO *info = (CRL_INFO *)buf;
4173
4174         ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4175          info->cExtension);
4176         LocalFree(buf);
4177     }
4178 }
4179
4180 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4181  szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4182 static const BYTE encodedUsage[] = {
4183  0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4184  0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4185  0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4186
4187 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4188 {
4189     BOOL ret;
4190     BYTE *buf = NULL;
4191     DWORD size = 0;
4192     CERT_ENHKEY_USAGE usage;
4193
4194     /* Test with empty usage */
4195     usage.cUsageIdentifier = 0;
4196     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4197      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4198     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4199     if (buf)
4200     {
4201         ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4202         ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4203         LocalFree(buf);
4204     }
4205     /* Test with a few usages */
4206     usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4207     usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4208     ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4209      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4210     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4211     if (buf)
4212     {
4213         ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4214         ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4215         LocalFree(buf);
4216     }
4217 }
4218
4219 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4220 {
4221     BOOL ret;
4222     LPBYTE buf = NULL;
4223     DWORD size = 0;
4224
4225     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4226      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4227      (BYTE *)&buf, &size);
4228     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4229     if (buf)
4230     {
4231         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4232
4233         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4234          "Wrong size %d\n", size);
4235         ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4236          usage->cUsageIdentifier);
4237         LocalFree(buf);
4238     }
4239     ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4240      encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4241      (BYTE *)&buf, &size);
4242     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4243     if (buf)
4244     {
4245         CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4246         DWORD i;
4247
4248         ok(size >= sizeof(CERT_ENHKEY_USAGE),
4249          "Wrong size %d\n", size);
4250         ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4251          "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4252         for (i = 0; i < usage->cUsageIdentifier; i++)
4253             ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4254              "Expected OID %s, got %s\n", keyUsages[i],
4255              usage->rgpszUsageIdentifier[i]);
4256         LocalFree(buf);
4257     }
4258 }
4259
4260 static const BYTE authorityKeyIdWithId[] = { 0x30,0x03,0x80,0x01,0x01 };
4261 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4262  0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4263  0x20,0x4c,0x61,0x6e,0x67,0x00 };
4264 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4265
4266 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4267 {
4268     CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4269     BOOL ret;
4270     BYTE *buf = NULL;
4271     DWORD size = 0;
4272
4273     /* Test with empty id */
4274     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4275      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4276     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4277     if (buf)
4278     {
4279         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4280         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4281         LocalFree(buf);
4282     }
4283     /* With just a key id */
4284     info.KeyId.cbData = sizeof(serialNum);
4285     info.KeyId.pbData = (BYTE *)serialNum;
4286     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4287      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4288     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4289     if (buf)
4290     {
4291         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4292         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4293         LocalFree(buf);
4294     }
4295     /* With just an issuer */
4296     info.KeyId.cbData = 0;
4297     info.CertIssuer.cbData = sizeof(encodedCommonName);
4298     info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4299     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4300      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4301     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4302     if (buf)
4303     {
4304         ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4305          size);
4306         ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4307         LocalFree(buf);
4308     }
4309     /* With just a serial number */
4310     info.CertIssuer.cbData = 0;
4311     info.CertSerialNumber.cbData = sizeof(serialNum);
4312     info.CertSerialNumber.pbData = (BYTE *)serialNum;
4313     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4314      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4315     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4316     if (buf)
4317     {
4318         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4319          size);
4320         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4321         LocalFree(buf);
4322     }
4323 }
4324
4325 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4326 {
4327     BOOL ret;
4328     LPBYTE buf = NULL;
4329     DWORD size = 0;
4330
4331     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4332      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4333      (BYTE *)&buf, &size);
4334     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4335     if (buf)
4336     {
4337         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4338
4339         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4340          size);
4341         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4342         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4343         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4344         LocalFree(buf);
4345     }
4346     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4347      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4348      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4349     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4350     if (buf)
4351     {
4352         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4353
4354         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4355          size);
4356         ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4357         ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4358          "Unexpected key id\n");
4359         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4360         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4361         LocalFree(buf);
4362     }
4363     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4364      authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4365      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4366     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4367     if (buf)
4368     {
4369         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4370
4371         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4372          size);
4373         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4374         ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4375          "Unexpected issuer len\n");
4376         ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4377          sizeof(encodedCommonName)), "Unexpected issuer\n");
4378         ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4379         LocalFree(buf);
4380     }
4381     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4382      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4383      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4384     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4385     if (buf)
4386     {
4387         CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4388
4389         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4390          size);
4391         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4392         ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4393         ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4394          "Unexpected serial number len\n");
4395         ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4396          "Unexpected serial number\n");
4397         LocalFree(buf);
4398     }
4399 }
4400
4401 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4402  0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4403  0x6f,0x72,0x67 };
4404
4405 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4406 {
4407     CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4408     CERT_ALT_NAME_ENTRY entry = { 0 };
4409     BOOL ret;
4410     BYTE *buf = NULL;
4411     DWORD size = 0;
4412
4413     /* Test with empty id */
4414     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4415      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4416     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4417     if (buf)
4418     {
4419         ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4420         ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4421         LocalFree(buf);
4422     }
4423     /* With just a key id */
4424     info.KeyId.cbData = sizeof(serialNum);
4425     info.KeyId.pbData = (BYTE *)serialNum;
4426     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4427      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4428     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4429     if (buf)
4430     {
4431         ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4432          size);
4433         ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4434         LocalFree(buf);
4435     }
4436     /* With a bogus issuer name */
4437     info.KeyId.cbData = 0;
4438     info.AuthorityCertIssuer.cAltEntry = 1;
4439     info.AuthorityCertIssuer.rgAltEntry = &entry;
4440     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4441      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4442     ok(!ret && GetLastError() == E_INVALIDARG,
4443      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4444     /* With an issuer name */
4445     entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4446     U(entry).pwszURL = (LPWSTR)url;
4447     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4448      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4449     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4450     if (buf)
4451     {
4452         ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4453          size);
4454         ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4455          "Unexpected value\n");
4456         LocalFree(buf);
4457     }
4458     /* With just a serial number */
4459     info.AuthorityCertIssuer.cAltEntry = 0;
4460     info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4461     info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4462     ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4463      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4464     ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4465     if (buf)
4466     {
4467         ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4468          size);
4469         ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4470         LocalFree(buf);
4471     }
4472 }
4473
4474 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4475 {
4476     BOOL ret;
4477     LPBYTE buf = NULL;
4478     DWORD size = 0;
4479
4480     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4481      emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4482      (BYTE *)&buf, &size);
4483     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4484     if (buf)
4485     {
4486         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4487
4488         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4489          size);
4490         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4491         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4492          "Expected no issuer name entries\n");
4493         ok(info->AuthorityCertSerialNumber.cbData == 0,
4494          "Expected no serial number\n");
4495         LocalFree(buf);
4496     }
4497     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4498      authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4499      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4500     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4501     if (buf)
4502     {
4503         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4504
4505         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4506          size);
4507         ok(info->KeyId.cbData == sizeof(serialNum), "Unexpected key id len\n");
4508         ok(!memcmp(info->KeyId.pbData, serialNum, sizeof(serialNum)),
4509          "Unexpected key id\n");
4510         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4511          "Expected no issuer name entries\n");
4512         ok(info->AuthorityCertSerialNumber.cbData == 0,
4513          "Expected no serial number\n");
4514         LocalFree(buf);
4515     }
4516     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4517      authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4518      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4519     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4520     if (buf)
4521     {
4522         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4523
4524         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4525          size);
4526         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4527         ok(info->AuthorityCertIssuer.cAltEntry == 1,
4528          "Expected 1 issuer entry, got %d\n",
4529          info->AuthorityCertIssuer.cAltEntry);
4530         ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4531          CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4532          info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4533         ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4534          url), "Unexpected URL\n");
4535         ok(info->AuthorityCertSerialNumber.cbData == 0,
4536          "Expected no serial number\n");
4537         LocalFree(buf);
4538     }
4539     ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4540      authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4541      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4542     ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4543     if (buf)
4544     {
4545         CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4546
4547         ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4548          size);
4549         ok(info->KeyId.cbData == 0, "Expected no key id\n");
4550         ok(info->AuthorityCertIssuer.cAltEntry == 0,
4551          "Expected no issuer name entries\n");
4552         ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4553          "Unexpected serial number len\n");
4554         ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4555          sizeof(serialNum)), "Unexpected serial number\n");
4556         LocalFree(buf);
4557     }
4558 }
4559
4560 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
4561 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
4562  0x03,0,0,0,0,0,0 };
4563 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
4564  0xa0,0x01,0x01 };
4565 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
4566  0x03,0x02,0x01,0x01 };
4567 static BYTE bogusDER[] = { 1 };
4568
4569 static void test_encodePKCSContentInfo(DWORD dwEncoding)
4570 {
4571     BOOL ret;
4572     BYTE *buf = NULL;
4573     DWORD size = 0;
4574     CRYPT_CONTENT_INFO info = { 0 };
4575     char oid1[] = "1.2.3";
4576
4577     SetLastError(0xdeadbeef);
4578     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
4579      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4580     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4581      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4582     SetLastError(0xdeadbeef);
4583     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4584      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4585     ok(!ret && GetLastError() == E_INVALIDARG,
4586      "Expected E_INVALIDARG, got %x\n", GetLastError());
4587     info.pszObjId = oid1;
4588     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4589      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4590     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4591     if (buf)
4592     {
4593         ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
4594         ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
4595         LocalFree(buf);
4596     }
4597     info.Content.pbData = bogusDER;
4598     info.Content.cbData = sizeof(bogusDER);
4599     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4600      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4601     ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
4602     if (buf)
4603     {
4604         ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
4605         ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
4606         LocalFree(buf);
4607     }
4608     info.Content.pbData = (BYTE *)ints[0].encoded;
4609     info.Content.cbData = ints[0].encoded[1] + 2;
4610     ret = CryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
4611      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4612     if (buf)
4613     {
4614         ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
4615         ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
4616         LocalFree(buf);
4617     }
4618 }
4619
4620 static void test_decodePKCSContentInfo(DWORD dwEncoding)
4621 {
4622     BOOL ret;
4623     LPBYTE buf = NULL;
4624     DWORD size = 0;
4625     CRYPT_CONTENT_INFO *info;
4626
4627     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4628      emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
4629      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4630     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4631     if (buf)
4632     {
4633         info = (CRYPT_CONTENT_INFO *)buf;
4634
4635         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4636          info->pszObjId);
4637         ok(info->Content.cbData == 0, "Expected no data, got %d\n",
4638          info->Content.cbData);
4639         LocalFree(buf);
4640     }
4641     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4642      emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
4643      0, NULL, NULL, &size);
4644     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4645     SetLastError(0xdeadbeef);
4646     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4647      bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
4648      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4649     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
4650      * I doubt an app depends on that.
4651      */
4652     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
4653      GetLastError() == CRYPT_E_ASN1_CORRUPT),
4654      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
4655      GetLastError());
4656     ret = CryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
4657      intPKCSContentInfo, sizeof(intPKCSContentInfo),
4658      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4659     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4660     if (buf)
4661     {
4662         info = (CRYPT_CONTENT_INFO *)buf;
4663
4664         ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4665          info->pszObjId);
4666         ok(info->Content.cbData == ints[0].encoded[1] + 2,
4667          "Unexpected size %d\n", info->Content.cbData);
4668         ok(!memcmp(info->Content.pbData, ints[0].encoded,
4669          info->Content.cbData), "Unexpected value\n");
4670     }
4671 }
4672
4673 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
4674  0x00 };
4675 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
4676  0x01 };
4677 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
4678  0x02,0x01,0x01 };
4679
4680 static void test_encodePKCSAttribute(DWORD dwEncoding)
4681 {
4682     CRYPT_ATTRIBUTE attr = { 0 };
4683     BOOL ret;
4684     LPBYTE buf = NULL;
4685     DWORD size = 0;
4686     CRYPT_ATTR_BLOB blob;
4687     char oid[] = "1.2.3";
4688
4689     SetLastError(0xdeadbeef);
4690     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
4691      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4692     ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
4693      "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
4694     SetLastError(0xdeadbeef);
4695     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4696      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4697     ok(!ret && GetLastError() == E_INVALIDARG,
4698      "Expected E_INVALIDARG, got %x\n", GetLastError());
4699     attr.pszObjId = oid;
4700     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4701      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4702     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4703     if (buf)
4704     {
4705         ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
4706         ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
4707         LocalFree(buf);
4708     }
4709     blob.cbData = sizeof(bogusDER);
4710     blob.pbData = bogusDER;
4711     attr.cValue = 1;
4712     attr.rgValue = &blob;
4713     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4714      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4715     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4716     if (buf)
4717     {
4718         ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
4719         ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
4720         LocalFree(buf);
4721     }
4722     blob.pbData = (BYTE *)ints[0].encoded;
4723     blob.cbData = ints[0].encoded[1] + 2;
4724     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
4725      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4726     if (buf)
4727     {
4728         ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
4729         ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
4730         LocalFree(buf);
4731     }
4732 }
4733
4734 static void test_decodePKCSAttribute(DWORD dwEncoding)
4735 {
4736     BOOL ret;
4737     LPBYTE buf = NULL;
4738     DWORD size = 0;
4739     CRYPT_ATTRIBUTE *attr;
4740
4741     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4742      emptyPKCSAttr, sizeof(emptyPKCSAttr),
4743      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4744     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4745     if (buf)
4746     {
4747         attr = (CRYPT_ATTRIBUTE *)buf;
4748
4749         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4750          attr->pszObjId);
4751         ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
4752         LocalFree(buf);
4753     }
4754     SetLastError(0xdeadbeef);
4755     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4756      bogusPKCSAttr, sizeof(bogusPKCSAttr),
4757      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4758     /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
4759      * I doubt an app depends on that.
4760      */
4761     ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
4762      GetLastError() == CRYPT_E_ASN1_CORRUPT),
4763      "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
4764      GetLastError());
4765     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
4766      intPKCSAttr, sizeof(intPKCSAttr),
4767      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4768     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4769     if (buf)
4770     {
4771         attr = (CRYPT_ATTRIBUTE *)buf;
4772
4773         ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
4774          attr->pszObjId);
4775         ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
4776         ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
4777          "Unexpected size %d\n", attr->rgValue[0].cbData);
4778         ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
4779          attr->rgValue[0].cbData), "Unexpected value\n");
4780     }
4781 }
4782
4783 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
4784 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
4785  0x2a,0x03,0x31,0x00 };
4786 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
4787  0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
4788
4789 static void test_encodePKCSAttributes(DWORD dwEncoding)
4790 {
4791     CRYPT_ATTRIBUTES attributes = { 0 };
4792     CRYPT_ATTRIBUTE attr[2] = { { 0 } };
4793     CRYPT_ATTR_BLOB blob;
4794     BOOL ret;
4795     LPBYTE buf = NULL;
4796     DWORD size = 0;
4797     char oid1[] = "1.2.3", oid2[] = "1.5.6";
4798
4799     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4800      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4801     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4802     if (buf)
4803     {
4804         ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
4805         ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
4806         LocalFree(buf);
4807     }
4808     attributes.cAttr = 1;
4809     attributes.rgAttr = attr;
4810     SetLastError(0xdeadbeef);
4811     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4812      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4813     ok(!ret && GetLastError() == E_INVALIDARG,
4814      "Expected E_INVALIDARG, got %x\n", GetLastError());
4815     attr[0].pszObjId = oid1;
4816     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4817      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4818     if (buf)
4819     {
4820         ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
4821         ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
4822         LocalFree(buf);
4823     }
4824     attr[1].pszObjId = oid2;
4825     attr[1].cValue = 1;
4826     attr[1].rgValue = &blob;
4827     blob.pbData = (BYTE *)ints[0].encoded;
4828     blob.cbData = ints[0].encoded[1] + 2;
4829     attributes.cAttr = 2;
4830     ret = CryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
4831      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4832     ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4833     if (buf)
4834     {
4835         ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
4836         ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
4837         LocalFree(buf);
4838     }
4839 }
4840
4841 static void test_decodePKCSAttributes(DWORD dwEncoding)
4842 {
4843     BOOL ret;
4844     LPBYTE buf = NULL;
4845     DWORD size = 0;
4846     CRYPT_ATTRIBUTES *attributes;
4847
4848     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
4849      emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
4850      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4851     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4852     if (buf)
4853     {
4854         attributes = (CRYPT_ATTRIBUTES *)buf;
4855         ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
4856          attributes->cAttr);
4857         LocalFree(buf);
4858     }
4859     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
4860      singlePKCSAttributes, sizeof(singlePKCSAttributes),
4861      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4862     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4863     if (buf)
4864     {
4865         attributes = (CRYPT_ATTRIBUTES *)buf;
4866         ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
4867          attributes->cAttr);
4868         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
4869          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
4870         ok(attributes->rgAttr[0].cValue == 0,
4871          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
4872         LocalFree(buf);
4873     }
4874     ret = CryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
4875      doublePKCSAttributes, sizeof(doublePKCSAttributes),
4876      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4877     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4878     if (buf)
4879     {
4880         attributes = (CRYPT_ATTRIBUTES *)buf;
4881         ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
4882          attributes->cAttr);
4883         ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
4884          "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
4885         ok(attributes->rgAttr[0].cValue == 0,
4886          "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
4887         ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
4888          "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
4889         ok(attributes->rgAttr[1].cValue == 1,
4890          "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
4891         ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
4892          "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
4893         ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
4894          attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
4895         LocalFree(buf);
4896     }
4897 }
4898
4899 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
4900  0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
4901  0x67 };
4902 static const BYTE minimalPKCSSigner[] = {
4903  0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4904  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4905  0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
4906 static const BYTE PKCSSignerWithSerial[] = {
4907  0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4908  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4909  0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
4910  0x00 };
4911 static const BYTE PKCSSignerWithHashAlgo[] = {
4912  0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4913  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4914  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
4915  0x00,0x04,0x00 };
4916 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
4917  0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4918  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4919  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
4920  0x06,0x05,0x00,0x04,0x00 };
4921 static const BYTE PKCSSignerWithHash[] = {
4922  0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
4923  0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
4924  0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
4925  0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
4926  0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
4927
4928 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
4929 {
4930     static char oid1[] = "1.2.3", oid2[] = "1.5.6";
4931     BOOL ret;
4932     LPBYTE buf = NULL;
4933     DWORD size = 0;
4934     CMSG_SIGNER_INFO info = { 0 };
4935
4936     SetLastError(0xdeadbeef);
4937     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
4938      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4939     ok(!ret && GetLastError() == E_INVALIDARG,
4940      "Expected E_INVALIDARG, got %08x\n", GetLastError());
4941     /* To be encoded, a signer must have an issuer at least, and the encoding
4942      * must include PKCS_7_ASN_ENCODING.  (That isn't enough to be decoded,
4943      * see decoding tests.)
4944      */
4945     info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
4946     info.Issuer.pbData = encodedCommonNameNoNull;
4947     SetLastError(0xdeadbeef);
4948     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
4949      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4950     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
4951         ok(!ret && GetLastError() == E_INVALIDARG,
4952          "Expected E_INVALIDARG, got %08x\n", GetLastError());
4953     else
4954     {
4955         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4956         if (buf)
4957         {
4958             ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
4959             if (size == sizeof(minimalPKCSSigner))
4960                 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
4961             else
4962                 ok(0, "Unexpected value\n");
4963             LocalFree(buf);
4964         }
4965     }
4966     info.SerialNumber.cbData = sizeof(serialNum);
4967     info.SerialNumber.pbData = (BYTE *)serialNum;
4968     SetLastError(0xdeadbeef);
4969     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
4970      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4971     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
4972         ok(!ret && GetLastError() == E_INVALIDARG,
4973          "Expected E_INVALIDARG, got %08x\n", GetLastError());
4974     else
4975     {
4976         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4977         if (buf)
4978         {
4979             ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
4980              size);
4981             if (size == sizeof(PKCSSignerWithSerial))
4982                 ok(!memcmp(buf, PKCSSignerWithSerial, size),
4983                  "Unexpected value\n");
4984             else
4985                 ok(0, "Unexpected value\n");
4986             LocalFree(buf);
4987         }
4988     }
4989     info.HashAlgorithm.pszObjId = oid1;
4990     SetLastError(0xdeadbeef);
4991     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
4992      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4993     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
4994         ok(!ret && GetLastError() == E_INVALIDARG,
4995          "Expected E_INVALIDARG, got %08x\n", GetLastError());
4996     else
4997     {
4998         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
4999         if (buf)
5000         {
5001             ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
5002              size);
5003             if (size == sizeof(PKCSSignerWithHashAlgo))
5004                 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
5005                  "Unexpected value\n");
5006             else
5007                 ok(0, "Unexpected value\n");
5008             LocalFree(buf);
5009         }
5010     }
5011     info.HashEncryptionAlgorithm.pszObjId = oid2;
5012     SetLastError(0xdeadbeef);
5013     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5014      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5015     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5016         ok(!ret && GetLastError() == E_INVALIDARG,
5017          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5018     else
5019     {
5020         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5021         if (buf)
5022         {
5023             ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
5024              "Unexpected size %d\n", size);
5025             if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
5026                 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
5027                  "Unexpected value\n");
5028             else
5029                 ok(0, "Unexpected value\n");
5030             LocalFree(buf);
5031         }
5032     }
5033     info.EncryptedHash.cbData = sizeof(hash);
5034     info.EncryptedHash.pbData = (BYTE *)hash;
5035     SetLastError(0xdeadbeef);
5036     ret = CryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
5037      CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5038     if (!(dwEncoding & PKCS_7_ASN_ENCODING))
5039         ok(!ret && GetLastError() == E_INVALIDARG,
5040          "Expected E_INVALIDARG, got %08x\n", GetLastError());
5041     else
5042     {
5043         ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5044         if (buf)
5045         {
5046             ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
5047              size);
5048             if (size == sizeof(PKCSSignerWithHash))
5049                 ok(!memcmp(buf, PKCSSignerWithHash, size),
5050                  "Unexpected value\n");
5051             else
5052                 ok(0, "Unexpected value\n");
5053             LocalFree(buf);
5054         }
5055     }
5056 }
5057
5058 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
5059 {
5060     BOOL ret;
5061     LPBYTE buf = NULL;
5062     DWORD size = 0;
5063     CMSG_SIGNER_INFO *info;
5064
5065     /* A PKCS signer can't be decoded without a serial number. */
5066     SetLastError(0xdeadbeef);
5067     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5068      minimalPKCSSigner, sizeof(minimalPKCSSigner),
5069      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5070     ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
5071      "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
5072     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5073      PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
5074      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5075     ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5076     if (buf)
5077     {
5078         info = (CMSG_SIGNER_INFO *)buf;
5079         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5080          info->dwVersion);
5081         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5082          "Unexpected size %d\n", info->Issuer.cbData);
5083         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5084          info->Issuer.cbData), "Unexpected value\n");
5085         ok(info->SerialNumber.cbData == sizeof(serialNum),
5086          "Unexpected size %d\n", info->SerialNumber.cbData);
5087         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5088          "Unexpected value\n");
5089         LocalFree(buf);
5090     }
5091     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5092      PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
5093      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5094     if (buf)
5095     {
5096         info = (CMSG_SIGNER_INFO *)buf;
5097         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5098          info->dwVersion);
5099         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5100          "Unexpected size %d\n", info->Issuer.cbData);
5101         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5102          info->Issuer.cbData), "Unexpected value\n");
5103         ok(info->SerialNumber.cbData == sizeof(serialNum),
5104          "Unexpected size %d\n", info->SerialNumber.cbData);
5105         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5106          "Unexpected value\n");
5107         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5108          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5109         LocalFree(buf);
5110     }
5111     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5112      PKCSSignerWithHashAndEncryptionAlgo,
5113      sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
5114      NULL, (BYTE *)&buf, &size);
5115     if (buf)
5116     {
5117         info = (CMSG_SIGNER_INFO *)buf;
5118         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5119          info->dwVersion);
5120         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5121          "Unexpected size %d\n", info->Issuer.cbData);
5122         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5123          info->Issuer.cbData), "Unexpected value\n");
5124         ok(info->SerialNumber.cbData == sizeof(serialNum),
5125          "Unexpected size %d\n", info->SerialNumber.cbData);
5126         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5127          "Unexpected value\n");
5128         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5129          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5130         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5131          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5132         LocalFree(buf);
5133     }
5134     ret = CryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
5135      PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
5136      CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5137     if (buf)
5138     {
5139         info = (CMSG_SIGNER_INFO *)buf;
5140         ok(info->dwVersion == 0, "Expected version 0, got %d\n",
5141          info->dwVersion);
5142         ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
5143          "Unexpected size %d\n", info->Issuer.cbData);
5144         ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
5145          info->Issuer.cbData), "Unexpected value\n");
5146         ok(info->SerialNumber.cbData == sizeof(serialNum),
5147          "Unexpected size %d\n", info->SerialNumber.cbData);
5148         ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
5149          "Unexpected value\n");
5150         ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
5151          "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
5152         ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
5153          "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
5154         ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
5155          info->EncryptedHash.cbData);
5156         ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
5157          "Unexpected value\n");
5158         LocalFree(buf);
5159     }
5160 }
5161
5162 /* Free *pInfo with HeapFree */
5163 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
5164 {
5165     BOOL ret;
5166     DWORD size = 0;
5167     HCRYPTKEY key;
5168
5169     /* This crashes
5170     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
5171      */
5172     ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
5173     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5174      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5175     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
5176      &size);
5177     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5178      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5179     ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
5180      NULL, &size);
5181     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5182      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5183     ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5184      0, NULL, NULL, &size);
5185     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5186      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5187     /* Test with no key */
5188     ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
5189      0, NULL, NULL, &size);
5190     ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
5191      GetLastError());
5192     ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
5193     ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
5194     if (ret)
5195     {
5196         ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
5197          NULL, 0, NULL, NULL, &size);
5198         ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
5199         *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
5200         if (*pInfo)
5201         {
5202             ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
5203              X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
5204             ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
5205              GetLastError());
5206             if (ret)
5207             {
5208                 /* By default (we passed NULL as the OID) the OID is
5209                  * szOID_RSA_RSA.
5210                  */
5211                 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
5212                  "Expected %s, got %s\n", szOID_RSA_RSA,
5213                  (*pInfo)->Algorithm.pszObjId);
5214             }
5215         }
5216     }
5217 }
5218
5219 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
5220  0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
5221  0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
5222  0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5223  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5224  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5225  0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
5226  0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
5227  0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
5228  0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
5229  0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
5230  0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
5231  0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
5232  0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
5233  0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
5234  0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
5235  0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
5236  0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
5237  0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
5238  0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
5239  0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
5240  0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
5241  0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
5242  0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
5243  0x49, 0xe5, 0xf9, 0x65, 0xf3 };
5244
5245 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
5246 {
5247     BOOL ret;
5248     HCRYPTKEY key;
5249     PCCERT_CONTEXT context;
5250
5251     /* These crash
5252     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
5253     ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
5254     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
5255     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5256      NULL);
5257      */
5258     ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
5259     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5260      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5261     ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
5262     ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
5263      "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
5264     ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
5265      &key);
5266     ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
5267      "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
5268     ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
5269      &key);
5270     ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5271     CryptDestroyKey(key);
5272
5273     /* Test importing a public key from a certificate context */
5274     context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
5275      sizeof(expiredCert));
5276     ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
5277      GetLastError());
5278     if (context)
5279     {
5280         ok(!strcmp(szOID_RSA_RSA,
5281          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
5282          "Expected %s, got %s\n", szOID_RSA_RSA,
5283          context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
5284         ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
5285          &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
5286         ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
5287         CryptDestroyKey(key);
5288         CertFreeCertificateContext(context);
5289     }
5290 }
5291
5292 static const char cspName[] = "WineCryptTemp";
5293
5294 static void testPortPublicKeyInfo(void)
5295 {
5296     HCRYPTPROV csp;
5297     BOOL ret;
5298     PCERT_PUBLIC_KEY_INFO info = NULL;
5299
5300     /* Just in case a previous run failed, delete this thing */
5301     CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5302      CRYPT_DELETEKEYSET);
5303     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5304      CRYPT_NEWKEYSET);
5305
5306     testExportPublicKey(csp, &info);
5307     testImportPublicKey(csp, info);
5308
5309     HeapFree(GetProcessHeap(), 0, info);
5310     CryptReleaseContext(csp, 0);
5311     ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
5312      CRYPT_DELETEKEYSET);
5313 }
5314
5315 START_TEST(encode)
5316 {
5317     static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
5318      X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
5319     DWORD i;
5320
5321     for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
5322     {
5323         test_encodeInt(encodings[i]);
5324         test_decodeInt(encodings[i]);
5325         test_encodeEnumerated(encodings[i]);
5326         test_decodeEnumerated(encodings[i]);
5327         test_encodeFiletime(encodings[i]);
5328         test_decodeFiletime(encodings[i]);
5329         test_encodeName(encodings[i]);
5330         test_decodeName(encodings[i]);
5331         test_encodeUnicodeName(encodings[i]);
5332         test_decodeUnicodeName(encodings[i]);
5333         test_encodeNameValue(encodings[i]);
5334         test_decodeNameValue(encodings[i]);
5335         test_encodeUnicodeNameValue(encodings[i]);
5336         test_decodeUnicodeNameValue(encodings[i]);
5337         test_encodeAltName(encodings[i]);
5338         test_decodeAltName(encodings[i]);
5339         test_encodeOctets(encodings[i]);
5340         test_decodeOctets(encodings[i]);
5341         test_encodeBits(encodings[i]);
5342         test_decodeBits(encodings[i]);
5343         test_encodeBasicConstraints(encodings[i]);
5344         test_decodeBasicConstraints(encodings[i]);
5345         test_encodeRsaPublicKey(encodings[i]);
5346         test_decodeRsaPublicKey(encodings[i]);
5347         test_encodeSequenceOfAny(encodings[i]);
5348         test_decodeSequenceOfAny(encodings[i]);
5349         test_encodeExtensions(encodings[i]);
5350         test_decodeExtensions(encodings[i]);
5351         test_encodePublicKeyInfo(encodings[i]);
5352         test_decodePublicKeyInfo(encodings[i]);
5353         test_encodeCertToBeSigned(encodings[i]);
5354         test_decodeCertToBeSigned(encodings[i]);
5355         test_encodeCert(encodings[i]);
5356         test_decodeCert(encodings[i]);
5357         test_encodeCRLDistPoints(encodings[i]);
5358         test_decodeCRLDistPoints(encodings[i]);
5359         test_encodeCRLIssuingDistPoint(encodings[i]);
5360         test_decodeCRLIssuingDistPoint(encodings[i]);
5361         test_encodeCRLToBeSigned(encodings[i]);
5362         test_decodeCRLToBeSigned(encodings[i]);
5363         test_encodeEnhancedKeyUsage(encodings[i]);
5364         test_decodeEnhancedKeyUsage(encodings[i]);
5365         test_encodeAuthorityKeyId(encodings[i]);
5366         test_decodeAuthorityKeyId(encodings[i]);
5367         test_encodeAuthorityKeyId2(encodings[i]);
5368         test_decodeAuthorityKeyId2(encodings[i]);
5369         test_encodePKCSContentInfo(encodings[i]);
5370         test_decodePKCSContentInfo(encodings[i]);
5371         test_encodePKCSAttribute(encodings[i]);
5372         test_decodePKCSAttribute(encodings[i]);
5373         test_encodePKCSAttributes(encodings[i]);
5374         test_decodePKCSAttributes(encodings[i]);
5375         test_encodePKCSSignerInfo(encodings[i]);
5376         test_decodePKCSSignerInfo(encodings[i]);
5377     }
5378     testPortPublicKeyInfo();
5379 }