crypt32: Implement encoding CTLs.
[wine/hacks.git] / dlls / crypt32 / tests / encode.c
blob42209f00078cd1ef1d7e3611e269f12567ed2f34
1 /*
2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
4 * Copyright 2005 Juan Lang
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.
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.
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
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 #include <winerror.h>
25 #include <wincrypt.h>
27 #include "wine/test.h"
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
33 struct encodedInt
35 int val;
36 const BYTE *encoded;
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
47 static const struct encodedInt ints[] = {
48 { 1, bin1 },
49 { 127, bin2 },
50 { 128, bin3 },
51 { 256, bin4 },
52 { -128, bin5 },
53 { -129, bin6 },
54 { 0xbaddf00d, bin7 },
57 struct encodedBigInt
59 const BYTE *val;
60 const BYTE *encoded;
61 const BYTE *decoded;
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
72 static const struct encodedBigInt bigInts[] = {
73 { bin8, bin9, bin10 },
74 { bin11, bin12, bin13 },
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84 { bin14, bin15, NULL },
85 { bin16, bin17, NULL },
88 static void test_encodeInt(DWORD dwEncoding)
90 DWORD bufSize = 0;
91 int i;
92 BOOL ret;
93 CRYPT_INTEGER_BLOB blob;
94 BYTE *buf = NULL;
96 /* CryptEncodeObjectEx with NULL bufSize crashes..
97 ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98 NULL);
100 /* check bogus encoding */
101 ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102 &bufSize);
103 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105 /* check with NULL integer buffer. Windows XP incorrectly returns an
106 * NTSTATUS.
108 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
109 &bufSize);
110 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
111 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
112 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
114 /* encode as normal integer */
115 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
116 NULL, NULL, &bufSize);
117 ok(ret, "Expected success, got %d\n", GetLastError());
118 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
119 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
120 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
121 if (buf)
123 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
124 buf[0]);
125 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
126 buf[1], ints[i].encoded[1]);
127 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
128 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
129 LocalFree(buf);
131 /* encode as multibyte integer */
132 blob.cbData = sizeof(ints[i].val);
133 blob.pbData = (BYTE *)&ints[i].val;
134 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
135 0, NULL, NULL, &bufSize);
136 ok(ret, "Expected success, got %d\n", GetLastError());
137 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
139 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
140 if (buf)
142 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
143 buf[0]);
144 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
145 buf[1], ints[i].encoded[1]);
146 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
147 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
148 LocalFree(buf);
151 /* encode a couple bigger ints, just to show it's little-endian and leading
152 * sign bytes are dropped
154 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
156 blob.cbData = strlen((const char*)bigInts[i].val);
157 blob.pbData = (BYTE *)bigInts[i].val;
158 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
159 0, NULL, NULL, &bufSize);
160 ok(ret, "Expected success, got %d\n", GetLastError());
161 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
163 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
164 if (buf)
166 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
167 buf[0]);
168 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
169 buf[1], bigInts[i].encoded[1]);
170 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
171 bigInts[i].encoded[1] + 1),
172 "Encoded value didn't match expected\n");
173 LocalFree(buf);
176 /* and, encode some uints */
177 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
179 blob.cbData = strlen((const char*)bigUInts[i].val);
180 blob.pbData = (BYTE*)bigUInts[i].val;
181 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
182 0, NULL, NULL, &bufSize);
183 ok(ret, "Expected success, got %d\n", GetLastError());
184 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
186 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
187 if (buf)
189 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
190 buf[0]);
191 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
192 buf[1], bigUInts[i].encoded[1]);
193 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
194 bigUInts[i].encoded[1] + 1),
195 "Encoded value didn't match expected\n");
196 LocalFree(buf);
201 static void test_decodeInt(DWORD dwEncoding)
203 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
204 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
205 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
206 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
207 static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
208 BYTE *buf = NULL;
209 DWORD bufSize = 0;
210 int i;
211 BOOL ret;
213 /* CryptDecodeObjectEx with NULL bufSize crashes..
214 ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
215 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
217 /* check bogus encoding */
218 ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
219 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
220 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
221 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
222 /* check with NULL integer buffer */
223 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
224 &bufSize);
225 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
226 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
227 /* check with a valid, but too large, integer */
228 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
229 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
230 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
231 "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
232 /* check with a DER-encoded string */
233 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
234 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
235 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
236 "Expected CRYPT_E_ASN1_BADTAG, got %d\n", GetLastError());
237 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
239 /* When the output buffer is NULL, this always succeeds */
240 SetLastError(0xdeadbeef);
241 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242 ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
243 &bufSize);
244 ok(ret && GetLastError() == NOERROR,
245 "Expected success and NOERROR, got %d\n", GetLastError());
246 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
247 ints[i].encoded, ints[i].encoded[1] + 2,
248 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
249 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
250 ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
251 ok(buf != NULL, "Expected allocated buffer\n");
252 if (buf)
254 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
255 ints[i].val, *(int *)buf);
256 LocalFree(buf);
259 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
261 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
262 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
263 &bufSize);
264 ok(ret && GetLastError() == NOERROR,
265 "Expected success and NOERROR, got %d\n", GetLastError());
266 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
267 bigInts[i].encoded, bigInts[i].encoded[1] + 2,
268 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
269 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
270 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
271 ok(buf != NULL, "Expected allocated buffer\n");
272 if (buf)
274 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
276 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
277 "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
278 blob->cbData);
279 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
280 "Unexpected value\n");
281 LocalFree(buf);
284 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
286 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
287 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
288 &bufSize);
289 ok(ret && GetLastError() == NOERROR,
290 "Expected success and NOERROR, got %d\n", GetLastError());
291 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
292 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
293 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
294 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
295 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
296 ok(buf != NULL, "Expected allocated buffer\n");
297 if (buf)
299 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
301 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
302 "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
303 blob->cbData);
304 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
305 "Unexpected value\n");
306 LocalFree(buf);
309 /* Decode the value 1 with long-form length */
310 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
311 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
312 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
313 if (buf)
315 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
316 LocalFree(buf);
318 /* check with extra bytes at the end */
319 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
320 sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
321 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
322 if (buf)
324 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
325 LocalFree(buf);
327 /* Try to decode some bogus large items */
328 /* The buffer size is smaller than the encoded length, so this should fail
329 * with CRYPT_E_ASN1_EOD if it's being decoded.
330 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
331 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
332 * So this test unfortunately isn't useful.
333 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
334 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
335 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
336 "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
338 /* This will try to decode the buffer and overflow it, check that it's
339 * caught.
341 if (0)
343 /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
344 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
345 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
346 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
347 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
351 static const BYTE bin18[] = {0x0a,0x01,0x01};
352 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
354 /* These are always encoded unsigned, and aren't constrained to be any
355 * particular value
357 static const struct encodedInt enums[] = {
358 { 1, bin18 },
359 { -128, bin19 },
362 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
363 * X509_ENUMERATED.
365 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
366 szOID_CRL_REASON_CODE };
368 static void test_encodeEnumerated(DWORD dwEncoding)
370 DWORD i, j;
372 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
374 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
376 BOOL ret;
377 BYTE *buf = NULL;
378 DWORD bufSize = 0;
380 ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
381 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
382 &bufSize);
383 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
384 if (buf)
386 ok(buf[0] == 0xa,
387 "Got unexpected type %d for enumerated (expected 0xa)\n",
388 buf[0]);
389 ok(buf[1] == enums[j].encoded[1],
390 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
391 ok(!memcmp(buf + 1, enums[j].encoded + 1,
392 enums[j].encoded[1] + 1),
393 "Encoded value of 0x%08x didn't match expected\n",
394 enums[j].val);
395 LocalFree(buf);
401 static void test_decodeEnumerated(DWORD dwEncoding)
403 DWORD i, j;
405 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
407 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
409 BOOL ret;
410 DWORD bufSize = sizeof(int);
411 int val;
413 ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
414 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
415 (BYTE *)&val, &bufSize);
416 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
417 ok(bufSize == sizeof(int),
418 "Got unexpected size %d for enumerated\n", bufSize);
419 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
420 val, enums[j].val);
425 struct encodedFiletime
427 SYSTEMTIME sysTime;
428 const BYTE *encodedTime;
431 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
432 const struct encodedFiletime *time)
434 FILETIME ft = { 0 };
435 BYTE *buf = NULL;
436 DWORD bufSize = 0;
437 BOOL ret;
439 ret = SystemTimeToFileTime(&time->sysTime, &ft);
440 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
441 ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
442 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
443 /* years other than 1950-2050 are not allowed for encodings other than
444 * X509_CHOICE_OF_TIME.
446 if (structType == X509_CHOICE_OF_TIME ||
447 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
449 ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
450 GetLastError());
451 ok(buf != NULL, "Expected an allocated buffer\n");
452 if (buf)
454 ok(buf[0] == time->encodedTime[0],
455 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
456 buf[0]);
457 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
458 time->encodedTime[1], bufSize);
459 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
460 "Got unexpected value for time encoding\n");
461 LocalFree(buf);
464 else
465 ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
466 "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
469 static const char *printSystemTime(const SYSTEMTIME *st)
471 static char buf[25];
473 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
474 st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
475 return buf;
478 static const char *printFileTime(const FILETIME *ft)
480 static char buf[25];
481 SYSTEMTIME st;
483 FileTimeToSystemTime(ft, &st);
484 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
485 st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
486 return buf;
489 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
491 SYSTEMTIME st;
493 FileTimeToSystemTime(got, &st);
494 ok(expected->wYear == st.wYear &&
495 expected->wMonth == st.wMonth &&
496 expected->wDay == st.wDay &&
497 expected->wHour == st.wHour &&
498 expected->wMinute == st.wMinute &&
499 expected->wSecond == st.wSecond &&
500 abs(expected->wMilliseconds - st.wMilliseconds) <= 1,
501 "Got unexpected value for time decoding:\nexpected %s, got %s\n",
502 printSystemTime(expected), printFileTime(got));
505 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
506 const struct encodedFiletime *time)
508 FILETIME ft = { 0 };
509 DWORD size = sizeof(ft);
510 BOOL ret;
512 ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
513 time->encodedTime[1] + 2, 0, NULL, &ft, &size);
514 /* years other than 1950-2050 are not allowed for encodings other than
515 * X509_CHOICE_OF_TIME.
517 if (structType == X509_CHOICE_OF_TIME ||
518 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
520 ok(ret, "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
521 GetLastError());
522 compareTime(&time->sysTime, &ft);
524 else
525 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
526 "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError());
529 static const BYTE bin20[] = {
530 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
531 static const BYTE bin21[] = {
532 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
533 static const BYTE bin22[] = {
534 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
536 static const struct encodedFiletime times[] = {
537 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
538 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
539 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
542 static void test_encodeFiletime(DWORD dwEncoding)
544 DWORD i;
546 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
548 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
549 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
550 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
554 static const BYTE bin23[] = {
555 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
556 static const BYTE bin24[] = {
557 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
558 static const BYTE bin25[] = {
559 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
560 static const BYTE bin26[] = {
561 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
562 static const BYTE bin27[] = {
563 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
564 static const BYTE bin28[] = {
565 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
566 static const BYTE bin29[] = {
567 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
568 static const BYTE bin30[] = {
569 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
570 static const BYTE bin31[] = {
571 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
572 static const BYTE bin32[] = {
573 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
574 static const BYTE bin33[] = {
575 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
576 static const BYTE bin34[] = {
577 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
578 static const BYTE bin35[] = {
579 0x17,0x08, '4','5','0','6','0','6','1','6'};
580 static const BYTE bin36[] = {
581 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
582 static const BYTE bin37[] = {
583 0x18,0x04, '2','1','4','5'};
584 static const BYTE bin38[] = {
585 0x18,0x08, '2','1','4','5','0','6','0','6'};
587 static void test_decodeFiletime(DWORD dwEncoding)
589 static const struct encodedFiletime otherTimes[] = {
590 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
591 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
592 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
593 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
594 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
595 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
596 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
597 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
598 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
599 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
600 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
601 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
603 /* An oddball case that succeeds in Windows, but doesn't seem correct
604 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
606 static const unsigned char *bogusTimes[] = {
607 /* oddly, this succeeds on Windows, with year 2765
608 "\x18" "\x0f" "21r50606161000Z",
610 bin35,
611 bin36,
612 bin37,
613 bin38,
615 DWORD i, size;
616 FILETIME ft1 = { 0 }, ft2 = { 0 };
617 BOOL ret;
619 /* Check bogus length with non-NULL buffer */
620 ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
621 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
622 size = 1;
623 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
624 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
625 ok(!ret && GetLastError() == ERROR_MORE_DATA,
626 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
627 /* Normal tests */
628 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
630 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
631 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
632 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
634 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
636 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
637 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
638 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
640 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
642 size = sizeof(ft1);
643 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
644 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
645 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
646 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
650 static const char commonName[] = "Juan Lang";
651 static const char surName[] = "Lang";
653 static const BYTE emptySequence[] = { 0x30, 0 };
654 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
655 static const BYTE twoRDNs[] = {
656 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
657 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
658 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
659 static const BYTE encodedTwoRDNs[] = {
660 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
661 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
662 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
663 0x6e,0x67,0x00,
666 static const BYTE us[] = { 0x55, 0x53 };
667 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
668 0x74, 0x61 };
669 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
670 0x6f, 0x6c, 0x69, 0x73 };
671 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
672 0x76, 0x65, 0x72, 0x73 };
673 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
674 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
675 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
676 0x73, 0x74 };
677 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
678 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
680 #define RDNA(arr) oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
681 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING, { sizeof(arr), (LPBYTE)arr }
683 static CHAR oid_us[] = "2.5.4.6",
684 oid_minnesota[] = "2.5.4.8",
685 oid_minneapolis[] = "2.5.4.7",
686 oid_codeweavers[] = "2.5.4.10",
687 oid_wine[] = "2.5.4.11",
688 oid_localhostAttr[] = "2.5.4.3",
689 oid_aric[] = "1.2.840.113549.1.9.1";
690 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
691 { RDNA(minnesota) },
692 { RDNA(minneapolis) },
693 { RDNA(codeweavers) },
694 { RDNA(wine) },
695 { RDNA(localhostAttr) },
696 { RDNIA5(aric) } };
697 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
698 { RDNA(localhostAttr) },
699 { RDNA(minnesota) },
700 { RDNA(minneapolis) },
701 { RDNA(codeweavers) },
702 { RDNA(wine) },
703 { RDNIA5(aric) } };
705 #undef RDNIA5
706 #undef RDNA
708 static const BYTE encodedRDNAttrs[] = {
709 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
710 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
711 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
712 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
713 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
714 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
715 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
716 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
717 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
718 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
721 static void test_encodeName(DWORD dwEncoding)
723 CERT_RDN_ATTR attrs[2];
724 CERT_RDN rdn;
725 CERT_NAME_INFO info;
726 static CHAR oid_common_name[] = szOID_COMMON_NAME,
727 oid_sur_name[] = szOID_SUR_NAME;
728 BYTE *buf = NULL;
729 DWORD size = 0;
730 BOOL ret;
732 /* Test with NULL pvStructInfo */
733 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
734 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
735 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
736 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
737 /* Test with empty CERT_NAME_INFO */
738 info.cRDN = 0;
739 info.rgRDN = NULL;
740 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
741 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
742 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
743 if (buf)
745 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
746 "Got unexpected encoding for empty name\n");
747 LocalFree(buf);
749 /* Test with bogus CERT_RDN */
750 info.cRDN = 1;
751 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
752 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
753 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
754 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
755 /* Test with empty CERT_RDN */
756 rdn.cRDNAttr = 0;
757 rdn.rgRDNAttr = NULL;
758 info.cRDN = 1;
759 info.rgRDN = &rdn;
760 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
761 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
762 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
763 if (buf)
765 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
766 "Got unexpected encoding for empty RDN array\n");
767 LocalFree(buf);
769 /* Test with bogus attr array */
770 rdn.cRDNAttr = 1;
771 rdn.rgRDNAttr = NULL;
772 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
773 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
774 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
775 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
776 /* oddly, a bogus OID is accepted by Windows XP; not testing.
777 attrs[0].pszObjId = "bogus";
778 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
779 attrs[0].Value.cbData = sizeof(commonName);
780 attrs[0].Value.pbData = (BYTE *)commonName;
781 rdn.cRDNAttr = 1;
782 rdn.rgRDNAttr = attrs;
783 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
784 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
785 ok(!ret, "Expected failure, got success\n");
787 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
788 * the encoded attributes to be swapped.
790 attrs[0].pszObjId = oid_common_name;
791 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
792 attrs[0].Value.cbData = sizeof(commonName);
793 attrs[0].Value.pbData = (BYTE *)commonName;
794 attrs[1].pszObjId = oid_sur_name;
795 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
796 attrs[1].Value.cbData = sizeof(surName);
797 attrs[1].Value.pbData = (BYTE *)surName;
798 rdn.cRDNAttr = 2;
799 rdn.rgRDNAttr = attrs;
800 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
801 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
802 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
803 if (buf)
805 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
806 "Got unexpected encoding for two RDN array\n");
807 LocalFree(buf);
809 /* A name can be "encoded" with previously encoded RDN attrs. */
810 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
811 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
812 attrs[0].Value.cbData = sizeof(twoRDNs);
813 rdn.cRDNAttr = 1;
814 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
815 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
816 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
817 if (buf)
819 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
820 ok(!memcmp(buf, encodedTwoRDNs, size),
821 "Unexpected value for re-endoded two RDN array\n");
822 LocalFree(buf);
824 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
825 rdn.cRDNAttr = 1;
826 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
827 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
828 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
829 ok(!ret && GetLastError() == E_INVALIDARG,
830 "Expected E_INVALIDARG, got %08x\n", GetLastError());
831 /* Test a more complex name */
832 rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
833 rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
834 info.cRDN = 1;
835 info.rgRDN = &rdn;
836 buf = NULL;
837 size = 0;
838 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
839 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
840 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
841 if (ret)
843 ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
844 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
845 LocalFree(buf);
849 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
850 static WCHAR surNameW[] = { 'L','a','n','g',0 };
852 static const BYTE twoRDNsNoNull[] = {
853 0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
854 0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
855 0x20,0x4c,0x61,0x6e,0x67 };
856 static const BYTE anyType[] = {
857 0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
858 0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
859 0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
860 0x61,0x4c,0x67,0x6e };
862 static void test_encodeUnicodeName(DWORD dwEncoding)
864 CERT_RDN_ATTR attrs[2];
865 CERT_RDN rdn;
866 CERT_NAME_INFO info;
867 static CHAR oid_common_name[] = szOID_COMMON_NAME,
868 oid_sur_name[] = szOID_SUR_NAME;
869 BYTE *buf = NULL;
870 DWORD size = 0;
871 BOOL ret;
873 /* Test with NULL pvStructInfo */
874 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
875 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
876 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
877 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
878 /* Test with empty CERT_NAME_INFO */
879 info.cRDN = 0;
880 info.rgRDN = NULL;
881 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
882 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
883 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
884 if (buf)
886 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
887 "Got unexpected encoding for empty name\n");
888 LocalFree(buf);
890 /* Check with one CERT_RDN_ATTR, that has an invalid character for the
891 * encoding (the NULL).
893 attrs[0].pszObjId = oid_common_name;
894 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
895 attrs[0].Value.cbData = sizeof(commonNameW);
896 attrs[0].Value.pbData = (BYTE *)commonNameW;
897 rdn.cRDNAttr = 1;
898 rdn.rgRDNAttr = attrs;
899 info.cRDN = 1;
900 info.rgRDN = &rdn;
901 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
902 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
903 ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
904 "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
905 ok(size == 9, "Unexpected error index %08x\n", size);
906 /* Check with two NULL-terminated CERT_RDN_ATTRs. Note DER encoding
907 * forces the order of the encoded attributes to be swapped.
909 attrs[0].pszObjId = oid_common_name;
910 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
911 attrs[0].Value.cbData = 0;
912 attrs[0].Value.pbData = (BYTE *)commonNameW;
913 attrs[1].pszObjId = oid_sur_name;
914 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
915 attrs[1].Value.cbData = 0;
916 attrs[1].Value.pbData = (BYTE *)surNameW;
917 rdn.cRDNAttr = 2;
918 rdn.rgRDNAttr = attrs;
919 info.cRDN = 1;
920 info.rgRDN = &rdn;
921 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
922 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
923 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
924 if (buf)
926 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
927 "Got unexpected encoding for two RDN array\n");
928 LocalFree(buf);
930 /* A name can be "encoded" with previously encoded RDN attrs. */
931 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
932 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
933 attrs[0].Value.cbData = sizeof(twoRDNs);
934 rdn.cRDNAttr = 1;
935 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
937 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
938 if (buf)
940 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
941 ok(!memcmp(buf, encodedTwoRDNs, size),
942 "Unexpected value for re-endoded two RDN array\n");
943 LocalFree(buf);
945 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
946 rdn.cRDNAttr = 1;
947 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
948 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
949 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
950 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
951 if (buf)
953 ok(size == sizeof(anyType), "Unexpected size %d\n", size);
954 ok(!memcmp(buf, anyType, size), "Unexpected value\n");
955 LocalFree(buf);
959 static void compareNameValues(const CERT_NAME_VALUE *expected,
960 const CERT_NAME_VALUE *got)
962 ok(got->dwValueType == expected->dwValueType,
963 "Expected string type %d, got %d\n", expected->dwValueType,
964 got->dwValueType);
965 ok(got->Value.cbData == expected->Value.cbData,
966 "String type %d: unexpected data size, got %d, expected %d\n",
967 expected->dwValueType, got->Value.cbData, expected->Value.cbData);
968 if (got->Value.cbData && got->Value.pbData)
969 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
970 min(got->Value.cbData, expected->Value.cbData)),
971 "String type %d: unexpected value\n", expected->dwValueType);
974 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
975 const CERT_RDN_ATTR *got)
977 if (expected->pszObjId && strlen(expected->pszObjId))
979 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
980 expected->pszObjId);
981 if (got->pszObjId)
983 ok(!strcmp(got->pszObjId, expected->pszObjId),
984 "Got unexpected OID %s, expected %s\n", got->pszObjId,
985 expected->pszObjId);
988 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
989 (const CERT_NAME_VALUE *)&got->dwValueType);
992 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
994 ok(got->cRDNAttr == expected->cRDNAttr,
995 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
996 if (got->cRDNAttr)
998 DWORD i;
1000 for (i = 0; i < got->cRDNAttr; i++)
1001 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1005 static void compareNames(const CERT_NAME_INFO *expected,
1006 const CERT_NAME_INFO *got)
1008 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1009 expected->cRDN, got->cRDN);
1010 if (got->cRDN)
1012 DWORD i;
1014 for (i = 0; i < got->cRDN; i++)
1015 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1019 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1020 static const BYTE twoRDNsExtraBytes[] = {
1021 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1022 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1023 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1025 static void test_decodeName(DWORD dwEncoding)
1027 BYTE *buf = NULL;
1028 DWORD bufSize = 0;
1029 BOOL ret;
1030 CERT_RDN rdn;
1031 CERT_NAME_INFO info = { 1, &rdn };
1033 /* test empty name */
1034 bufSize = 0;
1035 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1036 emptySequence[1] + 2,
1037 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1038 (BYTE *)&buf, &bufSize);
1039 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1040 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
1041 * decoder works the same way, so only test the count.
1043 if (buf)
1045 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1046 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1047 "Expected 0 RDNs in empty info, got %d\n",
1048 ((CERT_NAME_INFO *)buf)->cRDN);
1049 LocalFree(buf);
1051 /* test empty name with indefinite-length encoding */
1052 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1053 sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1054 (BYTE *)&buf, &bufSize);
1055 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1056 if (ret)
1058 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1059 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1060 "Expected 0 RDNs in empty info, got %d\n",
1061 ((CERT_NAME_INFO *)buf)->cRDN);
1062 LocalFree(buf);
1064 /* test empty RDN */
1065 bufSize = 0;
1066 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1067 emptyRDNs[1] + 2,
1068 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1069 (BYTE *)&buf, &bufSize);
1070 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1071 if (buf)
1073 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1075 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1076 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1077 "Got unexpected value for empty RDN\n");
1078 LocalFree(buf);
1080 /* test two RDN attrs */
1081 bufSize = 0;
1082 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1083 twoRDNs[1] + 2,
1084 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1085 (BYTE *)&buf, &bufSize);
1086 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1087 if (buf)
1089 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1090 oid_common_name[] = szOID_COMMON_NAME;
1092 CERT_RDN_ATTR attrs[] = {
1093 { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1094 (BYTE *)surName } },
1095 { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1096 (BYTE *)commonName } },
1099 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1100 rdn.rgRDNAttr = attrs;
1101 compareNames(&info, (CERT_NAME_INFO *)buf);
1102 LocalFree(buf);
1104 /* test that two RDN attrs with extra bytes succeeds */
1105 bufSize = 0;
1106 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1107 sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1108 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1109 /* And, a slightly more complicated name */
1110 buf = NULL;
1111 bufSize = 0;
1112 ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1113 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1114 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1115 if (ret)
1117 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1118 rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
1119 compareNames(&info, (CERT_NAME_INFO *)buf);
1120 LocalFree(buf);
1124 static void test_decodeUnicodeName(DWORD dwEncoding)
1126 BYTE *buf = NULL;
1127 DWORD bufSize = 0;
1128 BOOL ret;
1129 CERT_RDN rdn;
1130 CERT_NAME_INFO info = { 1, &rdn };
1132 /* test empty name */
1133 bufSize = 0;
1134 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1135 emptySequence[1] + 2,
1136 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1137 (BYTE *)&buf, &bufSize);
1138 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1139 if (buf)
1141 ok(bufSize == sizeof(CERT_NAME_INFO),
1142 "Got wrong bufSize %d\n", bufSize);
1143 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1144 "Expected 0 RDNs in empty info, got %d\n",
1145 ((CERT_NAME_INFO *)buf)->cRDN);
1146 LocalFree(buf);
1148 /* test empty RDN */
1149 bufSize = 0;
1150 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1151 emptyRDNs[1] + 2,
1152 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1153 (BYTE *)&buf, &bufSize);
1154 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1155 if (buf)
1157 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1159 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1160 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1161 "Got unexpected value for empty RDN\n");
1162 LocalFree(buf);
1164 /* test two RDN attrs */
1165 bufSize = 0;
1166 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1167 sizeof(twoRDNsNoNull),
1168 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1169 (BYTE *)&buf, &bufSize);
1170 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1171 if (buf)
1173 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1174 oid_common_name[] = szOID_COMMON_NAME;
1176 CERT_RDN_ATTR attrs[] = {
1177 { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1178 { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1179 { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1180 { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1183 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1184 rdn.rgRDNAttr = attrs;
1185 compareNames(&info, (CERT_NAME_INFO *)buf);
1186 LocalFree(buf);
1190 struct EncodedNameValue
1192 CERT_NAME_VALUE value;
1193 const BYTE *encoded;
1194 DWORD encodedSize;
1197 static const char bogusIA5[] = "\x80";
1198 static const char bogusPrintable[] = "~";
1199 static const char bogusNumeric[] = "A";
1200 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1201 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1202 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1203 static BYTE octetCommonNameValue[] = {
1204 0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1205 static BYTE numericCommonNameValue[] = {
1206 0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1207 static BYTE printableCommonNameValue[] = {
1208 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1209 static BYTE t61CommonNameValue[] = {
1210 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1211 static BYTE videotexCommonNameValue[] = {
1212 0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1213 static BYTE ia5CommonNameValue[] = {
1214 0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1215 static BYTE graphicCommonNameValue[] = {
1216 0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1217 static BYTE visibleCommonNameValue[] = {
1218 0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1219 static BYTE generalCommonNameValue[] = {
1220 0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1221 static BYTE bmpCommonNameValue[] = {
1222 0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1223 0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1224 static BYTE utf8CommonNameValue[] = {
1225 0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1227 static struct EncodedNameValue nameValues[] = {
1228 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1229 octetCommonNameValue, sizeof(octetCommonNameValue) },
1230 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1231 numericCommonNameValue, sizeof(numericCommonNameValue) },
1232 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1233 printableCommonNameValue, sizeof(printableCommonNameValue) },
1234 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1235 t61CommonNameValue, sizeof(t61CommonNameValue) },
1236 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1237 videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1238 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1239 ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1240 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1241 graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1242 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1243 visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1244 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1245 generalCommonNameValue, sizeof(generalCommonNameValue) },
1246 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1247 bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1248 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1249 utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1250 /* The following tests succeed under Windows, but really should fail,
1251 * they contain characters that are illegal for the encoding. I'm
1252 * including them to justify my lazy encoding.
1254 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1255 sizeof(bin42) },
1256 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1257 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1258 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1259 bin44, sizeof(bin44) },
1262 static void test_encodeNameValue(DWORD dwEncoding)
1264 BYTE *buf = NULL;
1265 DWORD size = 0, i;
1266 BOOL ret;
1267 CERT_NAME_VALUE value = { 0, { 0, NULL } };
1269 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1270 value.Value.pbData = printableCommonNameValue;
1271 value.Value.cbData = sizeof(printableCommonNameValue);
1272 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1273 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1274 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1275 if (buf)
1277 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1278 size);
1279 ok(!memcmp(buf, printableCommonNameValue, size),
1280 "Unexpected encoding\n");
1281 LocalFree(buf);
1283 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1285 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1286 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1287 &size);
1288 ok(ret, "Type %d: CryptEncodeObjectEx failed: %08x\n",
1289 nameValues[i].value.dwValueType, GetLastError());
1290 if (buf)
1292 ok(size == nameValues[i].encodedSize,
1293 "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1294 ok(!memcmp(buf, nameValues[i].encoded, size),
1295 "Got unexpected encoding\n");
1296 LocalFree(buf);
1301 static void test_decodeNameValue(DWORD dwEncoding)
1303 int i;
1304 BYTE *buf = NULL;
1305 DWORD bufSize = 0;
1306 BOOL ret;
1308 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1310 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1311 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1312 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1313 (BYTE *)&buf, &bufSize);
1314 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1315 nameValues[i].value.dwValueType, GetLastError());
1316 if (buf)
1318 compareNameValues(&nameValues[i].value,
1319 (const CERT_NAME_VALUE *)buf);
1320 LocalFree(buf);
1325 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1326 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1327 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1328 'h','q','.','o','r','g',0 };
1329 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1330 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1331 0x6f, 0x72, 0x67 };
1332 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1333 0x575b, 0 };
1334 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1335 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1336 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1337 static const BYTE localhost[] = { 127, 0, 0, 1 };
1338 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1339 0x01 };
1340 static const unsigned char encodedCommonName[] = {
1341 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1342 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1343 static const BYTE encodedDirectoryName[] = {
1344 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1345 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1347 static void test_encodeAltName(DWORD dwEncoding)
1349 CERT_ALT_NAME_INFO info = { 0 };
1350 CERT_ALT_NAME_ENTRY entry = { 0 };
1351 BYTE *buf = NULL;
1352 DWORD size = 0;
1353 BOOL ret;
1354 char oid[] = "1.2.3";
1356 /* Test with empty info */
1357 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1358 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1359 if (buf)
1361 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1362 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1363 LocalFree(buf);
1365 /* Test with an empty entry */
1366 info.cAltEntry = 1;
1367 info.rgAltEntry = &entry;
1368 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1369 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1370 ok(!ret && GetLastError() == E_INVALIDARG,
1371 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1372 /* Test with an empty pointer */
1373 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1374 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1375 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1376 if (buf)
1378 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1379 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1380 LocalFree(buf);
1382 /* Test with a real URL */
1383 U(entry).pwszURL = (LPWSTR)url;
1384 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1385 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1386 if (buf)
1388 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1389 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1390 LocalFree(buf);
1392 /* Now with the URL containing an invalid IA5 char */
1393 U(entry).pwszURL = (LPWSTR)nihongoURL;
1394 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1395 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1396 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1397 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1398 /* The first invalid character is at index 7 */
1399 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1400 "Expected invalid char at index 7, got %d\n",
1401 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1402 /* Now with the URL missing a scheme */
1403 U(entry).pwszURL = (LPWSTR)dnsName;
1404 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1405 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1406 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1407 if (buf)
1409 /* This succeeds, but it shouldn't, so don't worry about conforming */
1410 LocalFree(buf);
1412 /* Now with a DNS name */
1413 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1414 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1415 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1416 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1417 if (buf)
1419 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1420 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1421 LocalFree(buf);
1423 /* Test with an IP address */
1424 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1425 U(entry).IPAddress.cbData = sizeof(localhost);
1426 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1427 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1428 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1429 if (buf)
1431 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1432 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1433 LocalFree(buf);
1435 /* Test with OID */
1436 entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1437 U(entry).pszRegisteredID = oid;
1438 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1439 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1440 if (buf)
1442 ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1443 ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1444 LocalFree(buf);
1446 /* Test with directory name */
1447 entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1448 U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1449 U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1450 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1451 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1452 if (buf)
1454 ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1455 ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1456 LocalFree(buf);
1460 static void test_decodeAltName(DWORD dwEncoding)
1462 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1463 0x00, 0x00, 0x01 };
1464 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1465 0x01 };
1466 BOOL ret;
1467 BYTE *buf = NULL;
1468 DWORD bufSize = 0;
1469 CERT_ALT_NAME_INFO *info;
1471 /* Test some bogus ones first */
1472 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1473 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1474 NULL, (BYTE *)&buf, &bufSize);
1475 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1476 "Expected CRYPT_E_ASN1_BADTAG, got %08x\n", GetLastError());
1477 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1478 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1479 &bufSize);
1480 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1481 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
1482 /* Now expected cases */
1483 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1484 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1485 &bufSize);
1486 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1487 if (buf)
1489 info = (CERT_ALT_NAME_INFO *)buf;
1491 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1492 info->cAltEntry);
1493 LocalFree(buf);
1495 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1496 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1497 &bufSize);
1498 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1499 if (buf)
1501 info = (CERT_ALT_NAME_INFO *)buf;
1503 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1504 info->cAltEntry);
1505 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1506 "Expected CERT_ALT_NAME_URL, got %d\n",
1507 info->rgAltEntry[0].dwAltNameChoice);
1508 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1509 "Expected empty URL\n");
1510 LocalFree(buf);
1512 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1513 emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1514 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1515 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1516 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1517 &bufSize);
1518 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1519 if (buf)
1521 info = (CERT_ALT_NAME_INFO *)buf;
1523 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1524 info->cAltEntry);
1525 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1526 "Expected CERT_ALT_NAME_URL, got %d\n",
1527 info->rgAltEntry[0].dwAltNameChoice);
1528 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1529 LocalFree(buf);
1531 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1532 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1533 &bufSize);
1534 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1535 if (buf)
1537 info = (CERT_ALT_NAME_INFO *)buf;
1539 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1540 info->cAltEntry);
1541 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1542 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1543 info->rgAltEntry[0].dwAltNameChoice);
1544 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1545 "Unexpected DNS name\n");
1546 LocalFree(buf);
1548 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1549 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1550 &bufSize);
1551 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1552 if (buf)
1554 info = (CERT_ALT_NAME_INFO *)buf;
1556 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1557 info->cAltEntry);
1558 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1559 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1560 info->rgAltEntry[0].dwAltNameChoice);
1561 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1562 "Unexpected IP address length %d\n",
1563 U(info->rgAltEntry[0]).IPAddress.cbData);
1564 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1565 sizeof(localhost)), "Unexpected IP address value\n");
1566 LocalFree(buf);
1568 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1569 sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1570 &bufSize);
1571 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1572 if (buf)
1574 info = (CERT_ALT_NAME_INFO *)buf;
1576 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1577 info->cAltEntry);
1578 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1579 "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1580 info->rgAltEntry[0].dwAltNameChoice);
1581 ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1582 "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1583 LocalFree(buf);
1585 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1586 encodedDirectoryName, sizeof(encodedDirectoryName),
1587 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1588 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1589 if (buf)
1591 info = (CERT_ALT_NAME_INFO *)buf;
1593 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1594 info->cAltEntry);
1595 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1596 "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1597 info->rgAltEntry[0].dwAltNameChoice);
1598 ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1599 sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1600 U(info->rgAltEntry[0]).DirectoryName.cbData);
1601 ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1602 encodedCommonName, sizeof(encodedCommonName)),
1603 "Unexpected directory name value\n");
1604 LocalFree(buf);
1608 struct UnicodeExpectedError
1610 DWORD valueType;
1611 LPCWSTR str;
1612 DWORD errorIndex;
1613 DWORD error;
1616 static const WCHAR oneW[] = { '1',0 };
1617 static const WCHAR aW[] = { 'a',0 };
1618 static const WCHAR quoteW[] = { '"', 0 };
1620 static struct UnicodeExpectedError unicodeErrors[] = {
1621 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1622 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1623 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1624 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1625 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1626 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1629 struct UnicodeExpectedResult
1631 DWORD valueType;
1632 LPCWSTR str;
1633 CRYPT_DATA_BLOB encoded;
1636 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1637 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1638 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1639 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1640 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1641 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1642 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1643 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1644 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1645 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1646 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1647 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1648 0x5b };
1649 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1650 0x6f,0x5b };
1651 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1652 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1653 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1654 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1656 static struct UnicodeExpectedResult unicodeResults[] = {
1657 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1658 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1659 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1660 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1661 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1662 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1663 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1664 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1665 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1666 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1667 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1668 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1669 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1672 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1673 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1674 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1677 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1679 BYTE *buf = NULL;
1680 DWORD size = 0, i;
1681 BOOL ret;
1682 CERT_NAME_VALUE value;
1684 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1685 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1686 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1687 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1688 /* Have to have a string of some sort */
1689 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1690 value.Value.pbData = NULL;
1691 value.Value.cbData = 0;
1692 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1693 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1694 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1695 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1696 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1697 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1698 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1699 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1700 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1701 value.dwValueType = CERT_RDN_ANY_TYPE;
1702 value.Value.pbData = (LPBYTE)oneW;
1703 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1704 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1705 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1706 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1707 value.Value.cbData = sizeof(oneW);
1708 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1709 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1710 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1711 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1712 /* An encoded string with specified length isn't good enough either */
1713 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1714 value.Value.pbData = oneUniversal;
1715 value.Value.cbData = sizeof(oneUniversal);
1716 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1717 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1718 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1719 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1720 /* More failure checking */
1721 value.Value.cbData = 0;
1722 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1724 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1725 value.dwValueType = unicodeErrors[i].valueType;
1726 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1727 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1728 ok(!ret && GetLastError() == unicodeErrors[i].error,
1729 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1730 unicodeErrors[i].error, GetLastError());
1731 ok(size == unicodeErrors[i].errorIndex,
1732 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1733 size);
1735 /* cbData can be zero if the string is NULL-terminated */
1736 value.Value.cbData = 0;
1737 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1739 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1740 value.dwValueType = unicodeResults[i].valueType;
1741 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1742 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1743 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1744 if (buf)
1746 ok(size == unicodeResults[i].encoded.cbData,
1747 "Value type %d: expected size %d, got %d\n",
1748 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1749 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1750 "Value type %d: unexpected value\n", value.dwValueType);
1751 LocalFree(buf);
1754 /* These "encode," but they do so by truncating each unicode character
1755 * rather than properly encoding it. Kept separate from the proper results,
1756 * because the encoded forms won't decode to their original strings.
1758 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1760 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1761 value.dwValueType = unicodeWeirdness[i].valueType;
1762 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1763 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1764 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1765 if (buf)
1767 ok(size == unicodeWeirdness[i].encoded.cbData,
1768 "Value type %d: expected size %d, got %d\n",
1769 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1770 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1771 "Value type %d: unexpected value\n", value.dwValueType);
1772 LocalFree(buf);
1777 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1779 if (n <= 0) return 0;
1780 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1781 return *str1 - *str2;
1784 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1786 DWORD i;
1788 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1790 BYTE *buf = NULL;
1791 BOOL ret;
1792 DWORD size = 0;
1794 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1795 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1796 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1797 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1798 if (ret && buf)
1800 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1802 ok(value->dwValueType == unicodeResults[i].valueType,
1803 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1804 value->dwValueType);
1805 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1806 value->Value.cbData / sizeof(WCHAR)),
1807 "Unexpected decoded value for index %d (value type %d)\n", i,
1808 unicodeResults[i].valueType);
1809 LocalFree(buf);
1814 struct encodedOctets
1816 const BYTE *val;
1817 const BYTE *encoded;
1820 static const unsigned char bin46[] = { 'h','i',0 };
1821 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1822 static const unsigned char bin48[] = {
1823 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1824 static const unsigned char bin49[] = {
1825 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1826 static const unsigned char bin50[] = { 0 };
1827 static const unsigned char bin51[] = { 0x04,0x00,0 };
1829 static const struct encodedOctets octets[] = {
1830 { bin46, bin47 },
1831 { bin48, bin49 },
1832 { bin50, bin51 },
1835 static void test_encodeOctets(DWORD dwEncoding)
1837 CRYPT_DATA_BLOB blob;
1838 DWORD i;
1840 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1842 BYTE *buf = NULL;
1843 BOOL ret;
1844 DWORD bufSize = 0;
1846 blob.cbData = strlen((const char*)octets[i].val);
1847 blob.pbData = (BYTE*)octets[i].val;
1848 ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1849 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1850 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1851 if (buf)
1853 ok(buf[0] == 4,
1854 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1855 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1856 buf[1], octets[i].encoded[1]);
1857 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1858 octets[i].encoded[1] + 1), "Got unexpected value\n");
1859 LocalFree(buf);
1864 static void test_decodeOctets(DWORD dwEncoding)
1866 DWORD i;
1868 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1870 BYTE *buf = NULL;
1871 BOOL ret;
1872 DWORD bufSize = 0;
1874 ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1875 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1876 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1877 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1878 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1879 "Expected size >= %d, got %d\n",
1880 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1881 ok(buf != NULL, "Expected allocated buffer\n");
1882 if (buf)
1884 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1886 if (blob->cbData)
1887 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1888 "Unexpected value\n");
1889 LocalFree(buf);
1894 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1896 struct encodedBits
1898 DWORD cUnusedBits;
1899 const BYTE *encoded;
1900 DWORD cbDecoded;
1901 const BYTE *decoded;
1904 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1905 static const unsigned char bin53[] = { 0xff,0xff };
1906 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1907 static const unsigned char bin55[] = { 0xff,0xfe };
1908 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1909 static const unsigned char bin57[] = { 0xfe };
1910 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1912 static const struct encodedBits bits[] = {
1913 /* normal test cases */
1914 { 0, bin52, 2, bin53 },
1915 { 1, bin54, 2, bin55 },
1916 /* strange test case, showing cUnusedBits >= 8 is allowed */
1917 { 9, bin56, 1, bin57 },
1918 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1919 { 17, bin58, 0, NULL },
1922 static void test_encodeBits(DWORD dwEncoding)
1924 DWORD i;
1926 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1928 CRYPT_BIT_BLOB blob;
1929 BOOL ret;
1930 BYTE *buf = NULL;
1931 DWORD bufSize = 0;
1933 blob.cbData = sizeof(bytesToEncode);
1934 blob.pbData = (BYTE *)bytesToEncode;
1935 blob.cUnusedBits = bits[i].cUnusedBits;
1936 ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1937 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1938 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1939 if (buf)
1941 ok(bufSize == bits[i].encoded[1] + 2,
1942 "Got unexpected size %d, expected %d\n", bufSize,
1943 bits[i].encoded[1] + 2);
1944 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1945 "Unexpected value\n");
1946 LocalFree(buf);
1951 static void test_decodeBits(DWORD dwEncoding)
1953 static const BYTE ber[] = "\x03\x02\x01\xff";
1954 static const BYTE berDecoded = 0xfe;
1955 DWORD i;
1956 BOOL ret;
1957 BYTE *buf = NULL;
1958 DWORD bufSize = 0;
1960 /* normal cases */
1961 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1963 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1964 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1965 &bufSize);
1966 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1967 if (buf)
1969 CRYPT_BIT_BLOB *blob;
1971 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1972 "Got unexpected size %d\n", bufSize);
1973 blob = (CRYPT_BIT_BLOB *)buf;
1974 ok(blob->cbData == bits[i].cbDecoded,
1975 "Got unexpected length %d, expected %d\n", blob->cbData,
1976 bits[i].cbDecoded);
1977 if (blob->cbData && bits[i].cbDecoded)
1978 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1979 "Unexpected value\n");
1980 LocalFree(buf);
1983 /* special case: check that something that's valid in BER but not in DER
1984 * decodes successfully
1986 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1987 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1988 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1989 if (buf)
1991 CRYPT_BIT_BLOB *blob;
1993 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1994 "Got unexpected size %d\n", bufSize);
1995 blob = (CRYPT_BIT_BLOB *)buf;
1996 ok(blob->cbData == sizeof(berDecoded),
1997 "Got unexpected length %d\n", blob->cbData);
1998 if (blob->cbData)
1999 ok(*blob->pbData == berDecoded, "Unexpected value\n");
2000 LocalFree(buf);
2004 struct Constraints2
2006 CERT_BASIC_CONSTRAINTS2_INFO info;
2007 const BYTE *encoded;
2010 static const unsigned char bin59[] = { 0x30,0x00 };
2011 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2012 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2013 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2014 static const struct Constraints2 constraints2[] = {
2015 /* empty constraints */
2016 { { FALSE, FALSE, 0}, bin59 },
2017 /* can be a CA */
2018 { { TRUE, FALSE, 0}, bin60 },
2019 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2020 * but that's not the case
2022 { { FALSE, TRUE, 0}, bin61 },
2023 /* can be a CA and has path length constraints set */
2024 { { TRUE, TRUE, 1}, bin62 },
2027 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2028 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2029 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2030 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2031 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2032 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2033 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2034 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2035 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2036 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2038 static void test_encodeBasicConstraints(DWORD dwEncoding)
2040 DWORD i, bufSize = 0;
2041 CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2042 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2043 (LPBYTE)encodedDomainName };
2044 BOOL ret;
2045 BYTE *buf = NULL;
2047 /* First test with the simpler info2 */
2048 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2050 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2051 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2052 &bufSize);
2053 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2054 if (buf)
2056 ok(bufSize == constraints2[i].encoded[1] + 2,
2057 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2058 bufSize);
2059 ok(!memcmp(buf, constraints2[i].encoded,
2060 constraints2[i].encoded[1] + 2), "Unexpected value\n");
2061 LocalFree(buf);
2064 /* Now test with more complex basic constraints */
2065 info.SubjectType.cbData = 0;
2066 info.fPathLenConstraint = FALSE;
2067 info.cSubtreesConstraint = 0;
2068 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2069 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2070 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2071 if (buf)
2073 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2074 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2075 "Unexpected value\n");
2076 LocalFree(buf);
2078 /* None of the certs I examined had any subtree constraint, but I test one
2079 * anyway just in case.
2081 info.cSubtreesConstraint = 1;
2082 info.rgSubtreesConstraint = &nameBlob;
2083 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2084 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2085 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2086 if (buf)
2088 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2089 ok(!memcmp(buf, constraintWithDomainName,
2090 sizeof(constraintWithDomainName)), "Unexpected value\n");
2091 LocalFree(buf);
2093 /* FIXME: test encoding with subject type. */
2096 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2098 static void test_decodeBasicConstraints(DWORD dwEncoding)
2100 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2101 0xff };
2102 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2103 DWORD i;
2104 BOOL ret;
2105 BYTE *buf = NULL;
2106 DWORD bufSize = 0;
2108 /* First test with simpler info2 */
2109 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2111 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2112 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2113 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2114 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2115 GetLastError());
2116 if (buf)
2118 CERT_BASIC_CONSTRAINTS2_INFO *info =
2119 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2121 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2122 "Unexpected value for item %d\n", i);
2123 LocalFree(buf);
2126 /* Check with the order of encoded elements inverted */
2127 buf = (PBYTE)1;
2128 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2129 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2130 &bufSize);
2131 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2132 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2133 ok(!buf, "Expected buf to be set to NULL\n");
2134 /* Check with a non-DER bool */
2135 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2136 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2137 (BYTE *)&buf, &bufSize);
2138 ok(ret, "pCryptDecodeObjectEx failed: %08x\n", GetLastError());
2139 if (buf)
2141 CERT_BASIC_CONSTRAINTS2_INFO *info =
2142 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2144 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2145 LocalFree(buf);
2147 /* Check with a non-basic constraints value */
2148 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2149 (LPBYTE)encodedCommonName, encodedCommonName[1] + 2,
2150 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2151 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2152 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2153 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2154 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2155 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2156 (BYTE *)&buf, &bufSize);
2157 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2158 if (buf)
2160 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2162 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2163 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2164 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2165 LocalFree(buf);
2167 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2168 constraintWithDomainName, sizeof(constraintWithDomainName),
2169 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2170 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2171 if (buf)
2173 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2175 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2176 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2177 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2178 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2180 ok(info->rgSubtreesConstraint[0].cbData ==
2181 sizeof(encodedDomainName), "Wrong size %d\n",
2182 info->rgSubtreesConstraint[0].cbData);
2183 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2184 sizeof(encodedDomainName)), "Unexpected value\n");
2186 LocalFree(buf);
2190 /* These are terrible public keys of course, I'm just testing encoding */
2191 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2192 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2193 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2194 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2195 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2196 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2197 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2198 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2200 struct EncodedRSAPubKey
2202 const BYTE *modulus;
2203 size_t modulusLen;
2204 const BYTE *encoded;
2205 size_t decodedModulusLen;
2208 struct EncodedRSAPubKey rsaPubKeys[] = {
2209 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2210 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2211 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2212 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2215 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2217 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2218 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2219 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2220 BOOL ret;
2221 BYTE *buf = NULL;
2222 DWORD bufSize = 0, i;
2224 /* Try with a bogus blob type */
2225 hdr->bType = 2;
2226 hdr->bVersion = CUR_BLOB_VERSION;
2227 hdr->reserved = 0;
2228 hdr->aiKeyAlg = CALG_RSA_KEYX;
2229 rsaPubKey->magic = 0x31415352;
2230 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2231 rsaPubKey->pubexp = 65537;
2232 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2233 sizeof(modulus1));
2235 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2236 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2237 &bufSize);
2238 ok(!ret && GetLastError() == E_INVALIDARG,
2239 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2240 /* Now with a bogus reserved field */
2241 hdr->bType = PUBLICKEYBLOB;
2242 hdr->reserved = 1;
2243 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2244 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2245 &bufSize);
2246 if (buf)
2248 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2249 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2250 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2251 LocalFree(buf);
2253 /* Now with a bogus blob version */
2254 hdr->reserved = 0;
2255 hdr->bVersion = 0;
2256 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2257 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2258 &bufSize);
2259 if (buf)
2261 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2262 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2263 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2264 LocalFree(buf);
2266 /* And with a bogus alg ID */
2267 hdr->bVersion = CUR_BLOB_VERSION;
2268 hdr->aiKeyAlg = CALG_DES;
2269 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2270 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2271 &bufSize);
2272 if (buf)
2274 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2275 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2276 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2277 LocalFree(buf);
2279 /* Check a couple of RSA-related OIDs */
2280 hdr->aiKeyAlg = CALG_RSA_KEYX;
2281 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2282 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2283 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2284 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2285 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2286 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2287 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2288 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2289 /* Finally, all valid */
2290 hdr->aiKeyAlg = CALG_RSA_KEYX;
2291 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2293 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2294 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2295 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2296 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2297 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2298 if (buf)
2300 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2301 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2302 bufSize);
2303 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2304 "Unexpected value\n");
2305 LocalFree(buf);
2310 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2312 DWORD i;
2313 LPBYTE buf = NULL;
2314 DWORD bufSize = 0;
2315 BOOL ret;
2317 /* Try with a bad length */
2318 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2319 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2320 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2321 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2322 "Expected CRYPT_E_ASN1_EOD, got %08x\n", CRYPT_E_ASN1_EOD);
2323 /* Try with a couple of RSA-related OIDs */
2324 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2325 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2326 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2327 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2328 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2329 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2330 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2331 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2332 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2333 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2334 /* Now try success cases */
2335 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2337 bufSize = 0;
2338 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2339 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2340 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2341 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2342 if (buf)
2344 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2345 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2347 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2348 rsaPubKeys[i].decodedModulusLen,
2349 "Wrong size %d\n", bufSize);
2350 ok(hdr->bType == PUBLICKEYBLOB,
2351 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2352 hdr->bType);
2353 ok(hdr->bVersion == CUR_BLOB_VERSION,
2354 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2355 CUR_BLOB_VERSION, hdr->bVersion);
2356 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2357 hdr->reserved);
2358 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2359 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2360 ok(rsaPubKey->magic == 0x31415352,
2361 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2362 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2363 "Wrong bit len %d\n", rsaPubKey->bitlen);
2364 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2365 rsaPubKey->pubexp);
2366 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2367 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2368 "Unexpected modulus\n");
2369 LocalFree(buf);
2374 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2375 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2376 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2378 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2379 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2380 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2381 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2383 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2385 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2386 CRYPT_SEQUENCE_OF_ANY seq;
2387 DWORD i;
2388 BOOL ret;
2389 BYTE *buf = NULL;
2390 DWORD bufSize = 0;
2392 /* Encode a homogeneous sequence */
2393 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2395 blobs[i].cbData = ints[i].encoded[1] + 2;
2396 blobs[i].pbData = (BYTE *)ints[i].encoded;
2398 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2399 seq.rgValue = blobs;
2401 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2402 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2403 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2404 if (buf)
2406 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2407 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2408 LocalFree(buf);
2410 /* Change the type of the first element in the sequence, and give it
2411 * another go
2413 blobs[0].cbData = times[0].encodedTime[1] + 2;
2414 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2415 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2416 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2417 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2418 if (buf)
2420 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2421 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2422 "Unexpected value\n");
2423 LocalFree(buf);
2427 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2429 BOOL ret;
2430 BYTE *buf = NULL;
2431 DWORD bufSize = 0;
2433 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2434 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2435 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2436 if (buf)
2438 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2439 DWORD i;
2441 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2442 "Wrong elements %d\n", seq->cValue);
2443 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2445 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2446 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2447 seq->rgValue[i].cbData);
2448 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2449 ints[i].encoded[1] + 2), "Unexpected value\n");
2451 LocalFree(buf);
2453 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2454 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2455 &bufSize);
2456 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2457 if (buf)
2459 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2461 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2462 "Wrong elements %d\n", seq->cValue);
2463 /* Just check the first element since it's all that changed */
2464 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2465 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2466 seq->rgValue[0].cbData);
2467 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2468 times[0].encodedTime[1] + 2), "Unexpected value\n");
2469 LocalFree(buf);
2473 struct encodedExtensions
2475 CERT_EXTENSIONS exts;
2476 const BYTE *encoded;
2479 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2480 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2481 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2482 static CERT_EXTENSION criticalExt =
2483 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2484 static CERT_EXTENSION nonCriticalExt =
2485 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2487 static const BYTE ext0[] = { 0x30,0x00 };
2488 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2489 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2490 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2491 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2493 static const struct encodedExtensions exts[] = {
2494 { { 0, NULL }, ext0 },
2495 { { 1, &criticalExt }, ext1 },
2496 { { 1, &nonCriticalExt }, ext2 },
2499 static void test_encodeExtensions(DWORD dwEncoding)
2501 DWORD i;
2503 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2505 BOOL ret;
2506 BYTE *buf = NULL;
2507 DWORD bufSize = 0;
2509 ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2510 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2511 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2512 if (buf)
2514 ok(bufSize == exts[i].encoded[1] + 2,
2515 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2516 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2517 "Unexpected value\n");
2518 LocalFree(buf);
2523 static void test_decodeExtensions(DWORD dwEncoding)
2525 DWORD i;
2527 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2529 BOOL ret;
2530 BYTE *buf = NULL;
2531 DWORD bufSize = 0;
2533 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2534 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2535 NULL, (BYTE *)&buf, &bufSize);
2536 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2537 if (buf)
2539 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2540 DWORD j;
2542 ok(ext->cExtension == exts[i].exts.cExtension,
2543 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2544 ext->cExtension);
2545 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2547 ok(!strcmp(ext->rgExtension[j].pszObjId,
2548 exts[i].exts.rgExtension[j].pszObjId),
2549 "Expected OID %s, got %s\n",
2550 exts[i].exts.rgExtension[j].pszObjId,
2551 ext->rgExtension[j].pszObjId);
2552 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2553 exts[i].exts.rgExtension[j].Value.pbData,
2554 exts[i].exts.rgExtension[j].Value.cbData),
2555 "Unexpected value\n");
2557 LocalFree(buf);
2562 /* MS encodes public key info with a NULL if the algorithm identifier's
2563 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2564 * it encodes them by omitting the algorithm parameters. This latter approach
2565 * seems more correct, so accept either form.
2567 struct encodedPublicKey
2569 CERT_PUBLIC_KEY_INFO info;
2570 const BYTE *encoded;
2571 const BYTE *encodedNoNull;
2572 CERT_PUBLIC_KEY_INFO decoded;
2575 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2576 0xe, 0xf };
2577 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2579 static const unsigned char bin64[] = {
2580 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2581 static const unsigned char bin65[] = {
2582 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2583 static const unsigned char bin66[] = {
2584 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2585 static const unsigned char bin67[] = {
2586 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2587 static const unsigned char bin68[] = {
2588 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2589 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2590 static const unsigned char bin69[] = {
2591 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2592 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2593 static const unsigned char bin70[] = {
2594 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2595 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2596 0x0f};
2597 static const unsigned char bin71[] = {
2598 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2599 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2600 0x0f};
2601 static unsigned char bin72[] = { 0x05,0x00};
2603 static CHAR oid_bogus[] = "1.2.3",
2604 oid_rsa[] = szOID_RSA;
2606 static const struct encodedPublicKey pubKeys[] = {
2607 /* with a bogus OID */
2608 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2609 bin64, bin65,
2610 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2611 /* some normal keys */
2612 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2613 bin66, bin67,
2614 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2615 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2616 bin68, bin69,
2617 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2618 /* with add'l parameters--note they must be DER-encoded */
2619 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2620 (BYTE *)aKey, 0 } },
2621 bin70, bin71,
2622 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2623 (BYTE *)aKey, 0 } } },
2626 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2628 DWORD i;
2630 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2632 BOOL ret;
2633 BYTE *buf = NULL;
2634 DWORD bufSize = 0;
2636 ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2637 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2638 &bufSize);
2639 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2640 if (buf)
2642 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2643 bufSize == pubKeys[i].encodedNoNull[1] + 2,
2644 "Expected %d or %d bytes, got %d\n", pubKeys[i].encoded[1] + 2,
2645 pubKeys[i].encodedNoNull[1] + 2, bufSize);
2646 if (bufSize == pubKeys[i].encoded[1] + 2)
2647 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2648 "Unexpected value\n");
2649 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2650 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2651 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2652 LocalFree(buf);
2657 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2658 const CERT_PUBLIC_KEY_INFO *got)
2660 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2661 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2662 got->Algorithm.pszObjId);
2663 ok(expected->Algorithm.Parameters.cbData ==
2664 got->Algorithm.Parameters.cbData,
2665 "Expected parameters of %d bytes, got %d\n",
2666 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2667 if (expected->Algorithm.Parameters.cbData)
2668 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2669 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2670 "Unexpected algorithm parameters\n");
2671 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2672 "Expected public key of %d bytes, got %d\n",
2673 expected->PublicKey.cbData, got->PublicKey.cbData);
2674 if (expected->PublicKey.cbData)
2675 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2676 got->PublicKey.cbData), "Unexpected public key value\n");
2679 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2681 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2682 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2683 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2684 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2685 DWORD i;
2686 BOOL ret;
2687 BYTE *buf = NULL;
2688 DWORD bufSize = 0;
2690 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2692 /* The NULL form decodes to the decoded member */
2693 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2694 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2695 NULL, (BYTE *)&buf, &bufSize);
2696 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2697 if (buf)
2699 comparePublicKeyInfo(&pubKeys[i].decoded,
2700 (CERT_PUBLIC_KEY_INFO *)buf);
2701 LocalFree(buf);
2703 /* The non-NULL form decodes to the original */
2704 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2705 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2706 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2707 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2708 if (buf)
2710 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2711 LocalFree(buf);
2714 /* Test with bogus (not valid DER) parameters */
2715 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2716 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2717 NULL, (BYTE *)&buf, &bufSize);
2718 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2719 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
2722 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2723 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2724 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2725 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2726 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2727 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2728 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2729 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2730 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2731 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2732 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2733 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2734 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2735 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2736 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2737 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2738 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2739 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2740 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2741 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2742 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2743 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2744 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2745 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2746 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2747 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2748 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2749 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2750 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2751 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2752 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2753 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2754 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2755 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2756 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2757 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2758 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2759 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2760 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2761 static const BYTE v1CertWithPubKey[] = {
2762 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2763 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2764 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2765 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2766 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2767 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2768 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2769 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2770 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2771 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2772 0x01,0x01 };
2773 static const BYTE v1CertWithPubKeyNoNull[] = {
2774 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2775 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2776 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2777 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2778 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2779 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2780 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2781 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2782 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2783 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2784 static const BYTE v1CertWithSubjectKeyId[] = {
2785 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2786 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2787 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2788 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2789 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2790 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2791 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2792 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2793 0x4c,0x61,0x6e,0x67,0x00 };
2795 static const BYTE serialNum[] = { 0x01 };
2797 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2799 BOOL ret;
2800 BYTE *buf = NULL;
2801 DWORD size = 0;
2802 CERT_INFO info = { 0 };
2803 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2804 static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2805 CERT_EXTENSION ext;
2807 /* Test with NULL pvStructInfo */
2808 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2809 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2810 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2811 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2812 /* Test with a V1 cert */
2813 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2814 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2815 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2816 if (buf)
2818 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2819 v1Cert[1] + 2, size);
2820 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2821 LocalFree(buf);
2823 /* Test v2 cert */
2824 info.dwVersion = CERT_V2;
2825 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2826 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2827 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2828 if (buf)
2830 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2831 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2832 LocalFree(buf);
2834 /* Test v3 cert */
2835 info.dwVersion = CERT_V3;
2836 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2837 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2838 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2839 if (buf)
2841 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2842 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2843 LocalFree(buf);
2845 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2846 * API doesn't prevent it)
2848 info.dwVersion = CERT_V1;
2849 info.cExtension = 1;
2850 info.rgExtension = &criticalExt;
2851 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2852 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2853 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2854 if (buf)
2856 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2857 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2858 LocalFree(buf);
2860 /* test v1 cert with a serial number */
2861 info.SerialNumber.cbData = sizeof(serialNum);
2862 info.SerialNumber.pbData = (BYTE *)serialNum;
2863 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2864 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2865 if (buf)
2867 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2868 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2869 LocalFree(buf);
2871 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2872 info.Issuer.cbData = sizeof(encodedCommonName);
2873 info.Issuer.pbData = (BYTE *)encodedCommonName;
2874 info.Subject.cbData = sizeof(encodedCommonName);
2875 info.Subject.pbData = (BYTE *)encodedCommonName;
2876 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2877 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2878 if (buf)
2880 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2881 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2882 LocalFree(buf);
2884 /* Add a public key */
2885 info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2886 info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2887 info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2888 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2889 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2890 if (buf)
2892 ok(size == sizeof(v1CertWithPubKey) ||
2893 size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2894 if (size == sizeof(v1CertWithPubKey))
2895 ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2896 else if (size == sizeof(v1CertWithPubKeyNoNull))
2897 ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2898 "Got unexpected value\n");
2899 LocalFree(buf);
2901 /* Remove the public key, and add a subject key identifier extension */
2902 info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2903 info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2904 info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2905 ext.pszObjId = oid_subject_key_identifier;
2906 ext.fCritical = FALSE;
2907 ext.Value.cbData = sizeof(octetCommonNameValue);
2908 ext.Value.pbData = (BYTE *)octetCommonNameValue;
2909 info.cExtension = 1;
2910 info.rgExtension = &ext;
2911 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2912 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2913 if (buf)
2915 ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2916 ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2917 LocalFree(buf);
2921 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2923 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2924 v1CertWithConstraints, v1CertWithSerial };
2925 BOOL ret;
2926 BYTE *buf = NULL;
2927 DWORD size = 0, i;
2929 /* Test with NULL pbEncoded */
2930 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2931 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2932 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2933 "Expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
2934 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2935 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2936 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2937 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2938 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2939 * minimum a cert must have a non-zero serial number, an issuer, and a
2940 * subject.
2942 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2944 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2945 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2946 (BYTE *)&buf, &size);
2947 ok(!ret, "Expected failure\n");
2949 /* Now check with serial number, subject and issuer specified */
2950 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2951 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2952 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2953 if (buf)
2955 CERT_INFO *info = (CERT_INFO *)buf;
2957 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2958 ok(info->SerialNumber.cbData == 1,
2959 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2960 ok(*info->SerialNumber.pbData == *serialNum,
2961 "Expected serial number %d, got %d\n", *serialNum,
2962 *info->SerialNumber.pbData);
2963 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2964 "Wrong size %d\n", info->Issuer.cbData);
2965 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2966 "Unexpected issuer\n");
2967 ok(info->Subject.cbData == sizeof(encodedCommonName),
2968 "Wrong size %d\n", info->Subject.cbData);
2969 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2970 info->Subject.cbData), "Unexpected subject\n");
2971 LocalFree(buf);
2973 /* Check again with pub key specified */
2974 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2975 v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
2976 (BYTE *)&buf, &size);
2977 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2978 if (buf)
2980 CERT_INFO *info = (CERT_INFO *)buf;
2982 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
2983 ok(info->SerialNumber.cbData == 1,
2984 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
2985 ok(*info->SerialNumber.pbData == *serialNum,
2986 "Expected serial number %d, got %d\n", *serialNum,
2987 *info->SerialNumber.pbData);
2988 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2989 "Wrong size %d\n", info->Issuer.cbData);
2990 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2991 "Unexpected issuer\n");
2992 ok(info->Subject.cbData == sizeof(encodedCommonName),
2993 "Wrong size %d\n", info->Subject.cbData);
2994 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2995 info->Subject.cbData), "Unexpected subject\n");
2996 ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
2997 szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
2998 info->SubjectPublicKeyInfo.Algorithm.pszObjId);
2999 ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3000 "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3001 ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3002 sizeof(aKey)), "Unexpected public key\n");
3003 LocalFree(buf);
3007 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3008 0xe, 0xf };
3010 static const BYTE signedBigCert[] = {
3011 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3012 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3013 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3014 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3015 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3016 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3017 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3018 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3019 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3020 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3021 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3022 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3024 static void test_encodeCert(DWORD dwEncoding)
3026 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
3027 * also that bigCert is a NULL-terminated string, so don't count its
3028 * last byte (otherwise the signed cert won't decode.)
3030 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3031 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3032 BOOL ret;
3033 BYTE *buf = NULL;
3034 DWORD bufSize = 0;
3036 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3037 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
3038 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3039 if (buf)
3041 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3042 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3043 LocalFree(buf);
3047 static void test_decodeCert(DWORD dwEncoding)
3049 BOOL ret;
3050 BYTE *buf = NULL;
3051 DWORD size = 0;
3053 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3054 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3055 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3056 if (buf)
3058 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3060 ok(info->ToBeSigned.cbData == sizeof(bigCert),
3061 "Wrong cert size %d\n", info->ToBeSigned.cbData);
3062 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3063 "Unexpected cert\n");
3064 ok(info->Signature.cbData == sizeof(hash),
3065 "Wrong signature size %d\n", info->Signature.cbData);
3066 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3067 "Unexpected signature\n");
3068 LocalFree(buf);
3070 /* A signed cert decodes as a CERT_INFO too */
3071 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3072 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3073 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3074 if (buf)
3076 CERT_INFO *info = (CERT_INFO *)buf;
3078 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3079 ok(info->SerialNumber.cbData == 1,
3080 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3081 ok(*info->SerialNumber.pbData == *serialNum,
3082 "Expected serial number %d, got %d\n", *serialNum,
3083 *info->SerialNumber.pbData);
3084 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3085 "Wrong size %d\n", info->Issuer.cbData);
3086 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3087 "Unexpected issuer\n");
3088 ok(info->Subject.cbData == sizeof(encodedCommonName),
3089 "Wrong size %d\n", info->Subject.cbData);
3090 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3091 info->Subject.cbData), "Unexpected subject\n");
3092 LocalFree(buf);
3096 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3097 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3098 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3099 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3100 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3101 0x00, 0x03 };
3102 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3103 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3104 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3105 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3106 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3107 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3108 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3109 0x2e, 0x6f, 0x72, 0x67 };
3110 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3111 CRL_REASON_AFFILIATION_CHANGED;
3113 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3115 CRL_DIST_POINTS_INFO info = { 0 };
3116 CRL_DIST_POINT point = { { 0 } };
3117 CERT_ALT_NAME_ENTRY entry = { 0 };
3118 BOOL ret;
3119 BYTE *buf = NULL;
3120 DWORD size = 0;
3122 /* Test with an empty info */
3123 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3124 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3125 ok(!ret && GetLastError() == E_INVALIDARG,
3126 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3127 /* Test with one empty dist point */
3128 info.cDistPoint = 1;
3129 info.rgDistPoint = &point;
3130 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3131 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3132 if (buf)
3134 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3135 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3136 LocalFree(buf);
3138 /* A dist point with an invalid name */
3139 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3140 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3141 U(entry).pwszURL = (LPWSTR)nihongoURL;
3142 U(point.DistPointName).FullName.cAltEntry = 1;
3143 U(point.DistPointName).FullName.rgAltEntry = &entry;
3144 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3145 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3146 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3147 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3148 /* The first invalid character is at index 7 */
3149 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3150 "Expected invalid char at index 7, got %d\n",
3151 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3152 /* A dist point with (just) a valid name */
3153 U(entry).pwszURL = (LPWSTR)url;
3154 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3155 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3156 if (buf)
3158 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3159 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3160 LocalFree(buf);
3162 /* A dist point with (just) reason flags */
3163 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3164 point.ReasonFlags.cbData = sizeof(crlReason);
3165 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3166 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3167 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3168 if (buf)
3170 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3171 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3172 LocalFree(buf);
3174 /* A dist point with just an issuer */
3175 point.ReasonFlags.cbData = 0;
3176 point.CRLIssuer.cAltEntry = 1;
3177 point.CRLIssuer.rgAltEntry = &entry;
3178 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3179 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3180 if (buf)
3182 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3183 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3184 LocalFree(buf);
3186 /* A dist point with both a name and an issuer */
3187 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3188 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3189 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3190 if (buf)
3192 ok(size == sizeof(distPointWithUrlAndIssuer),
3193 "Wrong size %d\n", size);
3194 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3195 LocalFree(buf);
3199 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3201 BOOL ret;
3202 BYTE *buf = NULL;
3203 DWORD size = 0;
3204 PCRL_DIST_POINTS_INFO info;
3205 PCRL_DIST_POINT point;
3206 PCERT_ALT_NAME_ENTRY entry;
3208 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3209 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3210 (BYTE *)&buf, &size);
3211 if (ret)
3213 info = (PCRL_DIST_POINTS_INFO)buf;
3214 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3215 "Wrong size %d\n", size);
3216 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3217 info->cDistPoint);
3218 point = info->rgDistPoint;
3219 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3220 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3221 point->DistPointName.dwDistPointNameChoice);
3222 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3223 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3224 LocalFree(buf);
3226 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3227 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3228 (BYTE *)&buf, &size);
3229 if (ret)
3231 info = (PCRL_DIST_POINTS_INFO)buf;
3232 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3233 "Wrong size %d\n", size);
3234 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3235 info->cDistPoint);
3236 point = info->rgDistPoint;
3237 ok(point->DistPointName.dwDistPointNameChoice ==
3238 CRL_DIST_POINT_FULL_NAME,
3239 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3240 point->DistPointName.dwDistPointNameChoice);
3241 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3242 "Expected 1 name entry, got %d\n",
3243 U(point->DistPointName).FullName.cAltEntry);
3244 entry = U(point->DistPointName).FullName.rgAltEntry;
3245 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3246 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3247 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3248 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3249 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3250 LocalFree(buf);
3252 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3253 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3254 NULL, (BYTE *)&buf, &size);
3255 if (ret)
3257 info = (PCRL_DIST_POINTS_INFO)buf;
3258 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3259 "Wrong size %d\n", size);
3260 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3261 info->cDistPoint);
3262 point = info->rgDistPoint;
3263 ok(point->DistPointName.dwDistPointNameChoice ==
3264 CRL_DIST_POINT_NO_NAME,
3265 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3266 point->DistPointName.dwDistPointNameChoice);
3267 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3268 "Expected reason length\n");
3269 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3270 "Unexpected reason\n");
3271 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3272 LocalFree(buf);
3274 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3275 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3276 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3277 if (ret)
3279 info = (PCRL_DIST_POINTS_INFO)buf;
3280 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3281 "Wrong size %d\n", size);
3282 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3283 info->cDistPoint);
3284 point = info->rgDistPoint;
3285 ok(point->DistPointName.dwDistPointNameChoice ==
3286 CRL_DIST_POINT_FULL_NAME,
3287 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3288 point->DistPointName.dwDistPointNameChoice);
3289 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3290 "Expected 1 name entry, got %d\n",
3291 U(point->DistPointName).FullName.cAltEntry);
3292 entry = U(point->DistPointName).FullName.rgAltEntry;
3293 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3294 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3295 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3296 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3297 ok(point->CRLIssuer.cAltEntry == 1,
3298 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3299 entry = point->CRLIssuer.rgAltEntry;
3300 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3301 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3302 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3303 LocalFree(buf);
3307 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3308 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3309 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3310 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3311 0x67 };
3313 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3315 BOOL ret;
3316 BYTE *buf = NULL;
3317 DWORD size = 0;
3318 CRL_ISSUING_DIST_POINT point = { { 0 } };
3319 CERT_ALT_NAME_ENTRY entry;
3321 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3322 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3323 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3325 skip("no X509_ISSUING_DIST_POINT encode support\n");
3326 return;
3328 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3329 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3330 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3331 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3332 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3333 if (buf)
3335 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3336 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3337 LocalFree(buf);
3339 /* nonsensical flags */
3340 point.fOnlyContainsUserCerts = TRUE;
3341 point.fOnlyContainsCACerts = TRUE;
3342 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3343 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3344 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3345 if (buf)
3347 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3348 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3349 LocalFree(buf);
3351 /* unimplemented name type */
3352 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3353 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3354 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3355 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3356 ok(!ret && GetLastError() == E_INVALIDARG,
3357 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3358 /* empty name */
3359 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3360 U(point.DistPointName).FullName.cAltEntry = 0;
3361 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3362 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3363 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3364 if (buf)
3366 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3367 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3368 LocalFree(buf);
3370 /* name with URL entry */
3371 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3372 U(entry).pwszURL = (LPWSTR)url;
3373 U(point.DistPointName).FullName.cAltEntry = 1;
3374 U(point.DistPointName).FullName.rgAltEntry = &entry;
3375 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3376 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3377 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3378 if (buf)
3380 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3381 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3382 LocalFree(buf);
3386 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3387 const CERT_ALT_NAME_ENTRY *got)
3389 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3390 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3391 got->dwAltNameChoice);
3392 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3394 switch (got->dwAltNameChoice)
3396 case CERT_ALT_NAME_RFC822_NAME:
3397 case CERT_ALT_NAME_DNS_NAME:
3398 case CERT_ALT_NAME_EDI_PARTY_NAME:
3399 case CERT_ALT_NAME_URL:
3400 case CERT_ALT_NAME_REGISTERED_ID:
3401 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3402 (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3403 (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3404 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3405 "Unexpected name\n");
3406 break;
3407 case CERT_ALT_NAME_X400_ADDRESS:
3408 case CERT_ALT_NAME_DIRECTORY_NAME:
3409 case CERT_ALT_NAME_IP_ADDRESS:
3410 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3411 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3412 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3413 U(*got).IPAddress.cbData), "Unexpected value\n");
3414 break;
3419 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3420 const CERT_ALT_NAME_INFO *got)
3422 DWORD i;
3424 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3425 expected->cAltEntry, got->cAltEntry);
3426 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3427 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3430 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3431 const CRL_DIST_POINT_NAME *got)
3433 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3434 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3435 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3436 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3439 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3440 const CRL_ISSUING_DIST_POINT *got)
3442 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3443 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3444 "Unexpected fOnlyContainsUserCerts\n");
3445 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3446 "Unexpected fOnlyContainsCACerts\n");
3447 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3448 "Unexpected reason flags\n");
3449 ok(got->fIndirectCRL == expected->fIndirectCRL,
3450 "Unexpected fIndirectCRL\n");
3453 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3455 BOOL ret;
3456 BYTE *buf = NULL;
3457 DWORD size = 0;
3458 CRL_ISSUING_DIST_POINT point = { { 0 } };
3460 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3461 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3462 (BYTE *)&buf, &size);
3463 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3465 skip("no X509_ISSUING_DIST_POINT decode support\n");
3466 return;
3468 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3469 if (ret)
3471 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3472 LocalFree(buf);
3474 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3475 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3476 (BYTE *)&buf, &size);
3477 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3478 if (ret)
3480 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3481 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3482 LocalFree(buf);
3484 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3485 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3486 (BYTE *)&buf, &size);
3487 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3488 if (ret)
3490 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3491 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3492 U(point.DistPointName).FullName.cAltEntry = 0;
3493 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3494 LocalFree(buf);
3496 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3497 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3498 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3499 if (ret)
3501 CERT_ALT_NAME_ENTRY entry;
3503 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3504 U(entry).pwszURL = (LPWSTR)url;
3505 U(point.DistPointName).FullName.cAltEntry = 1;
3506 U(point.DistPointName).FullName.rgAltEntry = &entry;
3507 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3508 LocalFree(buf);
3512 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3513 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3514 0x30, 0x5a };
3515 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3516 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3517 0x30, 0x30, 0x30, 0x30, 0x5a };
3518 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3519 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3520 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3521 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3522 0x5a };
3523 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3524 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3525 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3526 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3527 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3528 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3529 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3530 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3531 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3532 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3533 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3534 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3535 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3536 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3537 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3538 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3539 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3540 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3541 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3542 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3543 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3544 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3545 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3546 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3547 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3548 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3549 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3550 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3551 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3552 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3553 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3554 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3555 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3556 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3557 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3558 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3559 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3560 0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3561 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3562 0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3564 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3566 BOOL ret;
3567 BYTE *buf = NULL;
3568 static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3569 DWORD size = 0;
3570 CRL_INFO info = { 0 };
3571 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3572 CERT_EXTENSION ext;
3574 /* Test with a V1 CRL */
3575 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3576 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3577 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3578 if (buf)
3580 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3581 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3582 LocalFree(buf);
3584 /* Test v2 CRL */
3585 info.dwVersion = CRL_V2;
3586 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3587 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3588 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3589 if (buf)
3591 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3592 v2CRL[1] + 2, size);
3593 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3594 LocalFree(buf);
3596 /* v1 CRL with a name */
3597 info.dwVersion = CRL_V1;
3598 info.Issuer.cbData = sizeof(encodedCommonName);
3599 info.Issuer.pbData = (BYTE *)encodedCommonName;
3600 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3601 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3602 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3603 if (buf)
3605 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3606 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3607 LocalFree(buf);
3609 /* v1 CRL with a name and a NULL entry pointer */
3610 info.cCRLEntry = 1;
3611 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3612 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3613 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3614 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3615 /* now set an empty entry */
3616 info.rgCRLEntry = &entry;
3617 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3618 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3619 if (buf)
3621 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3622 "Wrong size %d\n", size);
3623 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3624 "Got unexpected value\n");
3625 LocalFree(buf);
3627 /* an entry with a serial number */
3628 entry.SerialNumber.cbData = sizeof(serialNum);
3629 entry.SerialNumber.pbData = (BYTE *)serialNum;
3630 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3631 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3632 if (buf)
3634 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3635 "Wrong size %d\n", size);
3636 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3637 "Got unexpected value\n");
3638 LocalFree(buf);
3640 /* an entry with an extension */
3641 entry.cExtension = 1;
3642 entry.rgExtension = &criticalExt;
3643 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3644 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3645 ok(ret, "pCryptEncodeObjectEx failed: %08x\n", GetLastError());
3646 if (buf)
3648 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3649 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3650 LocalFree(buf);
3652 /* a CRL with an extension */
3653 entry.cExtension = 0;
3654 info.cExtension = 1;
3655 info.rgExtension = &criticalExt;
3656 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3657 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3658 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3659 if (buf)
3661 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3662 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3663 LocalFree(buf);
3665 /* a v2 CRL with an extension, this time non-critical */
3666 info.dwVersion = CRL_V2;
3667 info.rgExtension = &nonCriticalExt;
3668 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3669 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3670 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3671 if (buf)
3673 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3674 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3675 LocalFree(buf);
3677 /* a v2 CRL with an issuing dist point extension */
3678 ext.pszObjId = oid_issuing_dist_point;
3679 ext.fCritical = TRUE;
3680 ext.Value.cbData = sizeof(urlIDP);
3681 ext.Value.pbData = (LPBYTE)urlIDP;
3682 entry.rgExtension = &ext;
3683 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3684 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
3685 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3686 if (buf)
3688 ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3689 ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3690 LocalFree(buf);
3694 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3695 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3696 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3697 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3698 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3699 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3700 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3701 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3702 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3703 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3704 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3705 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3706 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3707 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3708 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3709 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3710 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3711 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3712 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3713 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3714 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3715 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3716 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3717 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3718 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3719 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3720 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3721 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3722 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3723 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3724 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3725 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3726 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3727 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3728 0xcd };
3729 static const BYTE verisignCRLWithLotsOfEntries[] = {
3730 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3731 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3732 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3733 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3734 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3735 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3736 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3737 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3738 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3739 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3740 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3741 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3742 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3743 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3744 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3745 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3746 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3747 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3748 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3749 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3750 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3751 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3752 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3753 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3754 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3755 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3756 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3757 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3758 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3759 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3760 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3761 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3762 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3763 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3764 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3765 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3766 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3767 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3768 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3769 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3770 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3771 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3772 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3773 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3774 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3775 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3776 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3777 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3778 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3779 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3780 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3781 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3782 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3783 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3784 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3785 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3786 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3787 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3788 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3789 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3790 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3791 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3792 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3793 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3794 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3795 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3796 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3797 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3798 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3799 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3800 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3801 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3802 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3803 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3804 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3805 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3806 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3807 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3808 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3809 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3810 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3811 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3812 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3813 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3814 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3815 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3816 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3817 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3818 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3819 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3820 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3821 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3822 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3823 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3824 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3825 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3826 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3827 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3828 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3829 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3830 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3831 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3832 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3833 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3834 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3835 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3836 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3837 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3838 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3839 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3840 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3841 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3842 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3843 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3844 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3845 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3846 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3847 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3848 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3849 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3850 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3851 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3852 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3853 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3854 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3855 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3856 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3857 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3858 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3859 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3860 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3861 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3862 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3863 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3864 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3865 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3866 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3867 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3868 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3869 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3870 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3871 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3872 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3873 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3874 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3875 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3876 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3877 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3878 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3879 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3880 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3881 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3882 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3883 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3884 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3885 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3886 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3887 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3888 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3889 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3890 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3891 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3892 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3893 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3894 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3895 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3896 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3897 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3898 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3899 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3900 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3901 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3902 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3903 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3904 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3905 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3906 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3907 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3908 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3909 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3910 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3911 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3912 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3913 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3914 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3915 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3916 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3917 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3918 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3919 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3920 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3921 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3922 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
3923 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
3924 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
3925 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
3926 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
3927 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
3928 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
3929 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
3930 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
3931 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
3932 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
3933 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
3934 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
3935 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
3936 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
3937 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
3938 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
3939 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
3940 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
3941 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
3942 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
3943 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
3944 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
3945 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
3946 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
3947 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
3948 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
3949 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
3950 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
3951 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
3952 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
3953 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
3954 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
3955 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
3956 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
3957 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
3958 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
3959 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
3960 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
3961 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
3962 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
3963 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
3964 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
3965 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
3966 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
3967 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
3968 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
3969 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
3970 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
3971 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
3972 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
3973 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
3974 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
3975 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
3976 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
3977 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
3978 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
3979 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
3980 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
3981 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
3982 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
3983 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
3984 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
3985 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
3986 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
3987 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
3988 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
3989 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
3990 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
3991 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
3992 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
3993 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
3994 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
3995 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
3996 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
3997 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
3998 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
3999 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4000 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4001 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4002 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4003 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4004 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4005 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4006 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4007 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4008 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4009 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4010 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4011 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4012 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4013 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4014 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4015 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4016 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4017 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4018 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4019 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4020 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4021 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4022 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4023 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4024 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4025 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4026 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4027 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4028 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4029 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4030 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4031 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4032 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4033 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4034 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4035 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4036 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4037 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4038 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4039 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4040 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4041 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4042 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4043 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4044 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4045 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4046 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4047 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4048 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4049 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4050 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4051 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4052 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4053 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4054 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4055 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4056 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4057 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4058 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4059 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4060 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4061 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4062 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4063 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4064 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4065 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4066 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4067 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4068 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4069 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4070 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4071 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4072 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4073 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4074 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4075 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4076 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4077 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4078 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4079 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4080 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4081 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4082 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4083 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4084 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4085 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4086 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4087 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4088 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4089 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4090 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4091 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4092 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4093 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4094 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4095 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4096 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4097 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4098 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4099 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4100 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4101 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4102 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4103 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4104 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4105 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4106 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4107 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4108 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4109 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4110 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4111 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4112 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4113 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4114 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4115 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4116 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4117 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4118 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4119 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4120 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4121 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4122 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4123 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4124 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4125 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4126 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4127 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4128 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4129 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4130 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4131 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4132 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4133 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4134 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4135 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4136 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4137 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4138 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4139 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4140 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4141 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4142 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4143 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4144 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4145 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4146 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4147 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4148 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4149 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4150 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4151 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4152 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4153 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4154 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4155 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4156 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4157 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4158 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4159 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4160 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4161 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4162 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4163 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4164 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4165 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4166 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4167 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4168 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4169 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4170 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4171 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4172 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4173 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4174 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4175 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4176 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4177 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4178 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4179 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4180 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4181 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4182 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4183 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4184 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4185 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4186 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4187 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4188 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4189 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4190 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4191 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4192 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4193 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4194 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4195 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4196 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4197 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4198 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4199 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4200 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4201 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4202 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4203 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4204 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4205 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4206 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4207 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4208 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4209 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4210 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4211 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4212 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4213 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4214 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4215 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4216 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4217 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4218 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4219 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4220 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4221 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4222 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4223 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4224 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4225 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4226 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4227 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4228 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4229 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4230 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4231 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4232 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4233 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4234 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4235 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4236 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4237 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4239 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4241 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4242 BOOL ret;
4243 BYTE *buf = NULL;
4244 DWORD size = 0, i;
4246 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4248 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4249 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4250 (BYTE *)&buf, &size);
4251 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
4252 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4254 /* at a minimum, a CRL must contain an issuer: */
4255 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4256 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4257 (BYTE *)&buf, &size);
4258 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4259 if (buf)
4261 CRL_INFO *info = (CRL_INFO *)buf;
4263 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4264 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4265 info->cCRLEntry);
4266 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4267 "Wrong issuer size %d\n", info->Issuer.cbData);
4268 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4269 "Unexpected issuer\n");
4270 LocalFree(buf);
4272 /* check decoding with an empty CRL entry */
4273 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4274 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4275 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4276 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
4277 "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError());
4278 /* with a real CRL entry */
4279 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4280 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4281 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4282 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4283 if (buf)
4285 CRL_INFO *info = (CRL_INFO *)buf;
4286 CRL_ENTRY *entry;
4288 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4289 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4290 info->cCRLEntry);
4291 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4292 entry = info->rgCRLEntry;
4293 ok(entry->SerialNumber.cbData == 1,
4294 "Expected serial number size 1, got %d\n",
4295 entry->SerialNumber.cbData);
4296 ok(*entry->SerialNumber.pbData == *serialNum,
4297 "Expected serial number %d, got %d\n", *serialNum,
4298 *entry->SerialNumber.pbData);
4299 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4300 "Wrong issuer size %d\n", info->Issuer.cbData);
4301 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4302 "Unexpected issuer\n");
4303 LocalFree(buf);
4305 /* a real CRL from verisign that has extensions */
4306 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4307 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4308 NULL, (BYTE *)&buf, &size);
4309 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4310 if (buf)
4312 CRL_INFO *info = (CRL_INFO *)buf;
4313 CRL_ENTRY *entry;
4315 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4316 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4317 info->cCRLEntry);
4318 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4319 entry = info->rgCRLEntry;
4320 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4321 info->cExtension);
4322 LocalFree(buf);
4324 /* another real CRL from verisign that has lots of entries */
4325 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4326 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4327 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4328 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4329 if (buf)
4331 CRL_INFO *info = (CRL_INFO *)buf;
4333 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4334 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4335 info->cCRLEntry);
4336 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4337 info->cExtension);
4338 LocalFree(buf);
4340 /* and finally, with an extension */
4341 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4342 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4343 NULL, (BYTE *)&buf, &size);
4344 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4345 if (buf)
4347 CRL_INFO *info = (CRL_INFO *)buf;
4348 CRL_ENTRY *entry;
4350 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4351 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4352 info->cCRLEntry);
4353 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4354 entry = info->rgCRLEntry;
4355 ok(entry->SerialNumber.cbData == 1,
4356 "Expected serial number size 1, got %d\n",
4357 entry->SerialNumber.cbData);
4358 ok(*entry->SerialNumber.pbData == *serialNum,
4359 "Expected serial number %d, got %d\n", *serialNum,
4360 *entry->SerialNumber.pbData);
4361 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4362 "Wrong issuer size %d\n", info->Issuer.cbData);
4363 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4364 "Unexpected issuer\n");
4365 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4366 info->cExtension);
4367 LocalFree(buf);
4369 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4370 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4371 NULL, (BYTE *)&buf, &size);
4372 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4373 if (buf)
4375 CRL_INFO *info = (CRL_INFO *)buf;
4377 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4378 info->cExtension);
4379 LocalFree(buf);
4381 /* And again, with an issuing dist point */
4382 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4383 v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4384 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4385 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4386 if (buf)
4388 CRL_INFO *info = (CRL_INFO *)buf;
4390 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4391 info->cExtension);
4392 LocalFree(buf);
4396 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4397 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4398 static const BYTE encodedUsage[] = {
4399 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4400 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4401 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4403 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4405 BOOL ret;
4406 BYTE *buf = NULL;
4407 DWORD size = 0;
4408 CERT_ENHKEY_USAGE usage;
4410 /* Test with empty usage */
4411 usage.cUsageIdentifier = 0;
4412 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4413 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4414 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4415 if (buf)
4417 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4418 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4419 LocalFree(buf);
4421 /* Test with a few usages */
4422 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4423 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4424 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4425 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4426 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4427 if (buf)
4429 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4430 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4431 LocalFree(buf);
4435 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4437 BOOL ret;
4438 LPBYTE buf = NULL;
4439 DWORD size = 0;
4441 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4442 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4443 (BYTE *)&buf, &size);
4444 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4445 if (buf)
4447 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4449 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4450 "Wrong size %d\n", size);
4451 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4452 usage->cUsageIdentifier);
4453 LocalFree(buf);
4455 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4456 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4457 (BYTE *)&buf, &size);
4458 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4459 if (buf)
4461 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4462 DWORD i;
4464 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4465 "Wrong size %d\n", size);
4466 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4467 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4468 for (i = 0; i < usage->cUsageIdentifier; i++)
4469 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4470 "Expected OID %s, got %s\n", keyUsages[i],
4471 usage->rgpszUsageIdentifier[i]);
4472 LocalFree(buf);
4476 static BYTE keyId[] = { 1,2,3,4 };
4477 static const BYTE authorityKeyIdWithId[] = {
4478 0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4479 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4480 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4481 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4482 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4484 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4486 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4487 BOOL ret;
4488 BYTE *buf = NULL;
4489 DWORD size = 0;
4491 /* Test with empty id */
4492 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4493 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4494 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4495 if (buf)
4497 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4498 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4499 LocalFree(buf);
4501 /* With just a key id */
4502 info.KeyId.cbData = sizeof(keyId);
4503 info.KeyId.pbData = keyId;
4504 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4505 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4506 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4507 if (buf)
4509 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4510 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4511 LocalFree(buf);
4513 /* With just an issuer */
4514 info.KeyId.cbData = 0;
4515 info.CertIssuer.cbData = sizeof(encodedCommonName);
4516 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4517 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4518 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4519 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4520 if (buf)
4522 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4523 size);
4524 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4525 LocalFree(buf);
4527 /* With just a serial number */
4528 info.CertIssuer.cbData = 0;
4529 info.CertSerialNumber.cbData = sizeof(serialNum);
4530 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4531 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4532 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4533 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4534 if (buf)
4536 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4537 size);
4538 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4539 LocalFree(buf);
4543 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4545 BOOL ret;
4546 LPBYTE buf = NULL;
4547 DWORD size = 0;
4549 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4550 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4551 (BYTE *)&buf, &size);
4552 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4553 if (buf)
4555 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4557 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4558 size);
4559 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4560 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4561 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4562 LocalFree(buf);
4564 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4565 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4566 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4567 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4568 if (buf)
4570 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4572 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4573 size);
4574 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4575 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4576 "Unexpected key id\n");
4577 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4578 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4579 LocalFree(buf);
4581 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4582 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4583 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4584 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4585 if (buf)
4587 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4589 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4590 size);
4591 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4592 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4593 "Unexpected issuer len\n");
4594 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4595 sizeof(encodedCommonName)), "Unexpected issuer\n");
4596 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4597 LocalFree(buf);
4599 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4600 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4601 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4602 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4603 if (buf)
4605 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4607 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4608 size);
4609 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4610 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4611 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4612 "Unexpected serial number len\n");
4613 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4614 "Unexpected serial number\n");
4615 LocalFree(buf);
4619 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4620 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4621 0x6f,0x72,0x67 };
4623 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4625 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4626 CERT_ALT_NAME_ENTRY entry = { 0 };
4627 BOOL ret;
4628 BYTE *buf = NULL;
4629 DWORD size = 0;
4631 /* Test with empty id */
4632 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4633 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4634 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4635 if (buf)
4637 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4638 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4639 LocalFree(buf);
4641 /* With just a key id */
4642 info.KeyId.cbData = sizeof(keyId);
4643 info.KeyId.pbData = keyId;
4644 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4645 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4646 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4647 if (buf)
4649 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4650 size);
4651 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4652 LocalFree(buf);
4654 /* With a bogus issuer name */
4655 info.KeyId.cbData = 0;
4656 info.AuthorityCertIssuer.cAltEntry = 1;
4657 info.AuthorityCertIssuer.rgAltEntry = &entry;
4658 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4659 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4660 ok(!ret && GetLastError() == E_INVALIDARG,
4661 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4662 /* With an issuer name */
4663 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4664 U(entry).pwszURL = (LPWSTR)url;
4665 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4666 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4667 ok(ret, "pCryptEncodeObjectEx failed: %08x\n", GetLastError());
4668 if (buf)
4670 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4671 size);
4672 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4673 "Unexpected value\n");
4674 LocalFree(buf);
4676 /* With just a serial number */
4677 info.AuthorityCertIssuer.cAltEntry = 0;
4678 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4679 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4680 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4681 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4682 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4683 if (buf)
4685 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4686 size);
4687 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4688 LocalFree(buf);
4692 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4694 BOOL ret;
4695 LPBYTE buf = NULL;
4696 DWORD size = 0;
4698 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4699 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4700 (BYTE *)&buf, &size);
4701 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4702 if (buf)
4704 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4706 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4707 size);
4708 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4709 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4710 "Expected no issuer name entries\n");
4711 ok(info->AuthorityCertSerialNumber.cbData == 0,
4712 "Expected no serial number\n");
4713 LocalFree(buf);
4715 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4716 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4717 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4718 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4719 if (buf)
4721 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4723 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4724 size);
4725 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4726 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4727 "Unexpected key id\n");
4728 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4729 "Expected no issuer name entries\n");
4730 ok(info->AuthorityCertSerialNumber.cbData == 0,
4731 "Expected no serial number\n");
4732 LocalFree(buf);
4734 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4735 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4736 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4737 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4738 if (buf)
4740 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4742 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4743 size);
4744 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4745 ok(info->AuthorityCertIssuer.cAltEntry == 1,
4746 "Expected 1 issuer entry, got %d\n",
4747 info->AuthorityCertIssuer.cAltEntry);
4748 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4749 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4750 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4751 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4752 url), "Unexpected URL\n");
4753 ok(info->AuthorityCertSerialNumber.cbData == 0,
4754 "Expected no serial number\n");
4755 LocalFree(buf);
4757 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4758 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4759 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4760 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4761 if (buf)
4763 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4765 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4766 size);
4767 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4768 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4769 "Expected no issuer name entries\n");
4770 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4771 "Unexpected serial number len\n");
4772 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4773 sizeof(serialNum)), "Unexpected serial number\n");
4774 LocalFree(buf);
4778 static const BYTE authorityInfoAccessWithUrl[] = {
4779 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4780 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4781 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4782 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4783 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4784 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4786 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4788 static char oid1[] = "1.2.3";
4789 static char oid2[] = "1.5.6";
4790 BOOL ret;
4791 BYTE *buf = NULL;
4792 DWORD size = 0;
4793 CERT_ACCESS_DESCRIPTION accessDescription[2];
4794 CERT_AUTHORITY_INFO_ACCESS aia;
4796 memset(accessDescription, 0, sizeof(accessDescription));
4797 aia.cAccDescr = 0;
4798 aia.rgAccDescr = NULL;
4799 /* Having no access descriptions is allowed */
4800 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4801 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4802 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4803 if (buf)
4805 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4806 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4807 LocalFree(buf);
4808 buf = NULL;
4810 /* It can't have an empty access method */
4811 aia.cAccDescr = 1;
4812 aia.rgAccDescr = accessDescription;
4813 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4814 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4815 ok(!ret && GetLastError() == E_INVALIDARG,
4816 "expected E_INVALIDARG, got %08x\n", GetLastError());
4817 /* It can't have an empty location */
4818 accessDescription[0].pszAccessMethod = oid1;
4819 SetLastError(0xdeadbeef);
4820 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4821 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4822 ok(!ret && GetLastError() == E_INVALIDARG,
4823 "expected E_INVALIDARG, got %08x\n", GetLastError());
4824 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4825 accessDescription[0].AccessLocation.pwszURL = (LPWSTR)url;
4826 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4827 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4828 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4829 if (buf)
4831 ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4832 size);
4833 ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4834 "unexpected value\n");
4835 LocalFree(buf);
4836 buf = NULL;
4838 accessDescription[1].pszAccessMethod = oid2;
4839 accessDescription[1].AccessLocation.dwAltNameChoice =
4840 CERT_ALT_NAME_IP_ADDRESS;
4841 accessDescription[1].AccessLocation.IPAddress.cbData =
4842 sizeof(encodedIPAddr);
4843 accessDescription[1].AccessLocation.IPAddress.pbData =
4844 (LPBYTE)encodedIPAddr;
4845 aia.cAccDescr = 2;
4846 ret = CryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4847 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4848 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4849 if (buf)
4851 ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4852 "unexpected size %d\n", size);
4853 ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4854 "unexpected value\n");
4855 LocalFree(buf);
4856 buf = NULL;
4860 static void compareAuthorityInfoAccess(LPCSTR header,
4861 const CERT_AUTHORITY_INFO_ACCESS *expected,
4862 const CERT_AUTHORITY_INFO_ACCESS *got)
4864 DWORD i;
4866 ok(expected->cAccDescr == got->cAccDescr,
4867 "%s: expected %d access descriptions, got %d\n", header,
4868 expected->cAccDescr, got->cAccDescr);
4869 for (i = 0; i < expected->cAccDescr; i++)
4871 ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4872 got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4873 header, i, expected->rgAccDescr[i].pszAccessMethod,
4874 got->rgAccDescr[i].pszAccessMethod);
4875 compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4876 &got->rgAccDescr[i].AccessLocation);
4880 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4882 static char oid1[] = "1.2.3";
4883 static char oid2[] = "1.5.6";
4884 BOOL ret;
4885 LPBYTE buf = NULL;
4886 DWORD size = 0;
4888 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4889 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4890 (BYTE *)&buf, &size);
4891 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4892 if (buf)
4894 CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4896 compareAuthorityInfoAccess("empty AIA", &aia,
4897 (CERT_AUTHORITY_INFO_ACCESS *)buf);
4898 LocalFree(buf);
4899 buf = NULL;
4901 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4902 authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4903 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
4904 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4905 if (buf)
4907 CERT_ACCESS_DESCRIPTION accessDescription;
4908 CERT_AUTHORITY_INFO_ACCESS aia;
4910 accessDescription.pszAccessMethod = oid1;
4911 accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4912 accessDescription.AccessLocation.pwszURL = (LPWSTR)url;
4913 aia.cAccDescr = 1;
4914 aia.rgAccDescr = &accessDescription;
4915 compareAuthorityInfoAccess("AIA with URL", &aia,
4916 (CERT_AUTHORITY_INFO_ACCESS *)buf);
4917 LocalFree(buf);
4918 buf = NULL;
4920 ret = CryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4921 authorityInfoAccessWithUrlAndIPAddr,
4922 sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
4923 NULL, (BYTE *)&buf, &size);
4924 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4925 if (buf)
4927 CERT_ACCESS_DESCRIPTION accessDescription[2];
4928 CERT_AUTHORITY_INFO_ACCESS aia;
4930 accessDescription[0].pszAccessMethod = oid1;
4931 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4932 accessDescription[0].AccessLocation.pwszURL = (LPWSTR)url;
4933 accessDescription[1].pszAccessMethod = oid2;
4934 accessDescription[1].AccessLocation.dwAltNameChoice =
4935 CERT_ALT_NAME_IP_ADDRESS;
4936 accessDescription[1].AccessLocation.IPAddress.cbData =
4937 sizeof(encodedIPAddr);
4938 accessDescription[1].AccessLocation.IPAddress.pbData =
4939 (LPBYTE)encodedIPAddr;
4940 aia.cAccDescr = 2;
4941 aia.rgAccDescr = accessDescription;
4942 compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
4943 (CERT_AUTHORITY_INFO_ACCESS *)buf);
4944 LocalFree(buf);
4945 buf = NULL;
4949 static const BYTE emptyCTL[] = {
4950 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4951 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4952 static const BYTE emptyCTLWithVersion1[] = {
4953 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
4954 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4955 static const BYTE ctlWithUsageIdentifier[] = {
4956 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
4957 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4958 static const BYTE ctlWithListIdentifier[] = {
4959 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
4960 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4961 static const BYTE ctlWithSequenceNumber[] = {
4962 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
4963 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4964 static const BYTE ctlWithThisUpdate[] = {
4965 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
4966 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4967 static const BYTE ctlWithThisAndNextUpdate[] = {
4968 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
4969 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
4970 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
4971 static const BYTE ctlWithAlgId[] = {
4972 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4973 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
4974 static const BYTE ctlWithBogusEntry[] = {
4975 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4976 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
4977 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
4978 static const BYTE ctlWithOneEntry[] = {
4979 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4980 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
4981 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
4982 static const BYTE ctlWithTwoEntries[] = {
4983 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
4984 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
4985 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
4986 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
4987 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4989 static void test_encodeCTL(DWORD dwEncoding)
4991 static char oid1[] = "1.2.3";
4992 static char oid2[] = "1.5.6";
4993 char *pOid1 = oid1;
4994 BOOL ret;
4995 BYTE *buf = NULL;
4996 DWORD size = 0;
4997 CTL_INFO info;
4998 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
4999 CTL_ENTRY ctlEntry[2];
5000 CRYPT_ATTRIBUTE attr1, attr2;
5001 CRYPT_ATTR_BLOB value1, value2;
5003 memset(&info, 0, sizeof(info));
5004 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5005 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5006 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5007 if (buf)
5009 ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5010 ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5011 LocalFree(buf);
5012 buf = NULL;
5014 info.dwVersion = 1;
5015 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5016 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5017 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5018 if (buf)
5020 ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5021 ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5022 LocalFree(buf);
5023 buf = NULL;
5025 info.dwVersion = 0;
5026 info.SubjectUsage.cUsageIdentifier = 1;
5027 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5028 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5029 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5030 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5031 if (buf)
5033 ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5034 size);
5035 ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5036 LocalFree(buf);
5037 buf = NULL;
5039 info.SubjectUsage.cUsageIdentifier = 0;
5040 info.ListIdentifier.cbData = sizeof(serialNum);
5041 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5042 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5043 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5044 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5045 if (buf)
5047 ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5048 ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5049 LocalFree(buf);
5050 buf = NULL;
5052 info.ListIdentifier.cbData = 0;
5053 info.SequenceNumber.cbData = sizeof(serialNum);
5054 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5055 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5056 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5057 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5058 if (buf)
5060 ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5061 size);
5062 ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5063 LocalFree(buf);
5064 buf = NULL;
5066 info.SequenceNumber.cbData = 0;
5067 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5068 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5069 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5070 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5071 if (buf)
5073 ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5074 ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5075 LocalFree(buf);
5076 buf = NULL;
5078 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5079 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5080 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5081 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5082 if (buf)
5084 ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5085 size);
5086 ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5087 LocalFree(buf);
5088 buf = NULL;
5090 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5091 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5092 info.SubjectAlgorithm.pszObjId = oid2;
5093 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5094 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5095 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5096 if (buf)
5098 ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5099 ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5100 LocalFree(buf);
5101 buf = NULL;
5103 /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5104 * (see tests below) but it'll encode fine.
5106 info.SubjectAlgorithm.pszObjId = NULL;
5107 value1.cbData = sizeof(serialNum);
5108 value1.pbData = (LPBYTE)serialNum;
5109 attr1.pszObjId = oid1;
5110 attr1.cValue = 1;
5111 attr1.rgValue = &value1;
5112 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5113 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5114 ctlEntry[0].cAttribute = 1;
5115 ctlEntry[0].rgAttribute = &attr1;
5116 info.cCTLEntry = 1;
5117 info.rgCTLEntry = ctlEntry;
5118 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5119 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5120 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5121 if (buf)
5123 ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5124 ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5125 LocalFree(buf);
5126 buf = NULL;
5128 value1.cbData = sizeof(emptySequence);
5129 value1.pbData = (LPBYTE)emptySequence;
5130 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5131 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5132 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5133 if (buf)
5135 ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5136 ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5137 LocalFree(buf);
5138 buf = NULL;
5140 value2.cbData = sizeof(encodedIPAddr);
5141 value2.pbData = (LPBYTE)encodedIPAddr;
5142 attr2.pszObjId = oid2;
5143 attr2.cValue = 1;
5144 attr2.rgValue = &value2;
5145 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5146 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5147 ctlEntry[1].cAttribute = 1;
5148 ctlEntry[1].rgAttribute = &attr2;
5149 info.cCTLEntry = 2;
5150 ret = CryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5151 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5152 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5153 if (buf)
5155 ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5156 ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5157 LocalFree(buf);
5158 buf = NULL;
5162 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5163 const CTL_INFO *got)
5165 DWORD i, j, k;
5167 ok(expected->dwVersion == got->dwVersion,
5168 "%s: expected version %d, got %d\n", header, expected->dwVersion,
5169 got->dwVersion);
5170 ok(expected->SubjectUsage.cUsageIdentifier ==
5171 got->SubjectUsage.cUsageIdentifier,
5172 "%s: expected %d usage identifiers, got %d\n", header,
5173 expected->SubjectUsage.cUsageIdentifier,
5174 got->SubjectUsage.cUsageIdentifier);
5175 for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5176 ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5177 got->SubjectUsage.rgpszUsageIdentifier[i]),
5178 "%s[%d]: expected %s, got %s\n", header, i,
5179 expected->SubjectUsage.rgpszUsageIdentifier[i],
5180 got->SubjectUsage.rgpszUsageIdentifier[i]);
5181 ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5182 "%s: expected list identifier of %d bytes, got %d\n", header,
5183 expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5184 if (expected->ListIdentifier.cbData)
5185 ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5186 expected->ListIdentifier.cbData),
5187 "%s: unexpected list identifier value\n", header);
5188 ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5189 "%s: expected sequence number of %d bytes, got %d\n", header,
5190 expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5191 if (expected->SequenceNumber.cbData)
5192 ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5193 expected->SequenceNumber.cbData),
5194 "%s: unexpected sequence number value\n", header);
5195 ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5196 "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5197 expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5198 got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5199 ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5200 "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5201 expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5202 got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5203 if (expected->SubjectAlgorithm.pszObjId &&
5204 *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5205 ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5206 expected->SubjectAlgorithm.pszObjId);
5207 if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5208 ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5209 got->SubjectAlgorithm.pszObjId),
5210 "%s: expected subject algorithm %s, got %s\n", header,
5211 expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5212 ok(expected->SubjectAlgorithm.Parameters.cbData ==
5213 got->SubjectAlgorithm.Parameters.cbData,
5214 "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5215 expected->SubjectAlgorithm.Parameters.cbData,
5216 got->SubjectAlgorithm.Parameters.cbData);
5217 if (expected->SubjectAlgorithm.Parameters.cbData)
5218 ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5219 got->SubjectAlgorithm.Parameters.pbData,
5220 expected->SubjectAlgorithm.Parameters.cbData),
5221 "%s: unexpected subject algorithm parameter value\n", header);
5222 ok(expected->cCTLEntry == got->cCTLEntry,
5223 "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5224 got->cCTLEntry);
5225 for (i = 0; i < expected->cCTLEntry; i++)
5227 ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5228 got->rgCTLEntry[i].SubjectIdentifier.cbData,
5229 "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5230 header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5231 got->rgCTLEntry[i].SubjectIdentifier.cbData);
5232 if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5233 ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5234 got->rgCTLEntry[i].SubjectIdentifier.pbData,
5235 expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5236 "%s[%d]: unexpected subject identifier value\n",
5237 header, i);
5238 for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5240 ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5241 got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5242 "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5243 expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5244 got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5245 for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5247 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5248 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5249 "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5250 header, i, j, k,
5251 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5252 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5253 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5254 ok(!memcmp(
5255 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5256 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5257 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5258 "%s[%d][%d][%d]: unexpected value\n",
5259 header, i, j, k);
5263 ok(expected->cExtension == got->cExtension,
5264 "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5265 got->cExtension);
5266 for (i = 0; i < expected->cExtension; i++)
5268 ok(!strcmp(expected->rgExtension[i].pszObjId,
5269 got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5270 header, i, expected->rgExtension[i].pszObjId,
5271 got->rgExtension[i].pszObjId);
5272 ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5273 "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5274 expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5275 ok(expected->rgExtension[i].Value.cbData ==
5276 got->rgExtension[i].Value.cbData,
5277 "%s[%d]: expected extension value to have %d bytes, got %d\n",
5278 header, i, expected->rgExtension[i].Value.cbData,
5279 got->rgExtension[i].Value.cbData);
5280 if (expected->rgExtension[i].Value.cbData)
5281 ok(!memcmp(expected->rgExtension[i].Value.pbData,
5282 got->rgExtension[i].Value.pbData,
5283 expected->rgExtension[i].Value.cbData),
5284 "%s[%d]: unexpected extension value\n", header, i);
5288 static void test_decodeCTL(DWORD dwEncoding)
5290 static char oid1[] = "1.2.3";
5291 static char oid2[] = "1.5.6";
5292 static BYTE nullData[] = { 5,0 };
5293 char *pOid1 = oid1;
5294 BOOL ret;
5295 BYTE *buf = NULL;
5296 DWORD size = 0;
5297 CTL_INFO info;
5298 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5299 CTL_ENTRY ctlEntry[2];
5300 CRYPT_ATTRIBUTE attr1, attr2;
5301 CRYPT_ATTR_BLOB value1, value2;
5303 memset(&info, 0, sizeof(info));
5304 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5305 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5306 todo_wine
5307 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5308 if (buf)
5310 compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5311 LocalFree(buf);
5312 buf = NULL;
5314 info.dwVersion = 1;
5315 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5316 sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
5317 &size);
5318 todo_wine
5319 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5320 if (buf)
5322 compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5323 LocalFree(buf);
5324 buf = NULL;
5326 info.dwVersion = 0;
5327 info.SubjectUsage.cUsageIdentifier = 1;
5328 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5329 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5330 sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5331 (BYTE *)&buf, &size);
5332 todo_wine
5333 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5334 if (buf)
5336 compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5337 LocalFree(buf);
5338 buf = NULL;
5340 info.SubjectUsage.cUsageIdentifier = 0;
5341 info.ListIdentifier.cbData = sizeof(serialNum);
5342 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5343 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5344 sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5345 (BYTE *)&buf, &size);
5346 todo_wine
5347 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5348 if (buf)
5350 compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5351 LocalFree(buf);
5352 buf = NULL;
5354 info.ListIdentifier.cbData = 0;
5355 info.SequenceNumber.cbData = sizeof(serialNum);
5356 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5357 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5358 sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL,
5359 (BYTE *)&buf, &size);
5360 todo_wine
5361 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5362 if (buf)
5364 compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5365 LocalFree(buf);
5366 buf = NULL;
5368 info.SequenceNumber.cbData = 0;
5369 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5370 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5371 sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5372 (BYTE *)&buf, &size);
5373 todo_wine
5374 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5375 if (buf)
5377 compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5378 LocalFree(buf);
5379 buf = NULL;
5381 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5382 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5383 sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5384 (BYTE *)&buf, &size);
5385 todo_wine
5386 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5387 if (buf)
5389 compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5390 LocalFree(buf);
5391 buf = NULL;
5393 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5394 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5395 info.SubjectAlgorithm.pszObjId = oid2;
5396 info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5397 info.SubjectAlgorithm.Parameters.pbData = nullData;
5398 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5399 sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL,
5400 (BYTE *)&buf, &size);
5401 todo_wine
5402 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5403 if (buf)
5405 compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5406 LocalFree(buf);
5407 buf = NULL;
5409 SetLastError(0xdeadbeef);
5410 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5411 sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5412 (BYTE *)&buf, &size);
5413 todo_wine
5414 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
5415 "expected CRYPT_E_ASN1_EOD, got %08x\n", GetLastError());
5416 info.SubjectAlgorithm.Parameters.cbData = 0;
5417 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5418 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5419 info.SubjectAlgorithm.pszObjId = oid2;
5420 info.SubjectAlgorithm.pszObjId = NULL;
5421 value1.cbData = sizeof(emptySequence);
5422 value1.pbData = (LPBYTE)emptySequence;
5423 attr1.pszObjId = oid1;
5424 attr1.cValue = 1;
5425 attr1.rgValue = &value1;
5426 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5427 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5428 ctlEntry[0].cAttribute = 1;
5429 ctlEntry[0].rgAttribute = &attr1;
5430 info.cCTLEntry = 1;
5431 info.rgCTLEntry = ctlEntry;
5432 SetLastError(0xdeadbeef);
5433 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5434 sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL,
5435 (BYTE *)&buf, &size);
5436 todo_wine
5437 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5438 if (buf)
5440 compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5441 LocalFree(buf);
5442 buf = NULL;
5444 value2.cbData = sizeof(encodedIPAddr);
5445 value2.pbData = (LPBYTE)encodedIPAddr;
5446 attr2.pszObjId = oid2;
5447 attr2.cValue = 1;
5448 attr2.rgValue = &value2;
5449 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5450 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5451 ctlEntry[1].cAttribute = 1;
5452 ctlEntry[1].rgAttribute = &attr2;
5453 info.cCTLEntry = 2;
5454 ret = CryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5455 sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL,
5456 (BYTE *)&buf, &size);
5457 todo_wine
5458 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5459 if (buf)
5461 compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5462 LocalFree(buf);
5463 buf = NULL;
5467 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5468 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5469 0x03,0,0,0,0,0,0 };
5470 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5471 0xa0,0x01,0x01 };
5472 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5473 0x03,0x02,0x01,0x01 };
5474 static BYTE bogusDER[] = { 1 };
5476 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5478 BOOL ret;
5479 BYTE *buf = NULL;
5480 DWORD size = 0;
5481 CRYPT_CONTENT_INFO info = { 0 };
5482 char oid1[] = "1.2.3";
5484 SetLastError(0xdeadbeef);
5485 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5486 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5487 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5488 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5489 SetLastError(0xdeadbeef);
5490 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5491 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5492 ok(!ret && GetLastError() == E_INVALIDARG,
5493 "Expected E_INVALIDARG, got %x\n", GetLastError());
5494 info.pszObjId = oid1;
5495 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5496 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5497 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5498 if (buf)
5500 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5501 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5502 LocalFree(buf);
5504 info.Content.pbData = bogusDER;
5505 info.Content.cbData = sizeof(bogusDER);
5506 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5507 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5508 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5509 if (buf)
5511 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5512 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5513 LocalFree(buf);
5515 info.Content.pbData = (BYTE *)ints[0].encoded;
5516 info.Content.cbData = ints[0].encoded[1] + 2;
5517 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5518 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5519 if (buf)
5521 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5522 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5523 LocalFree(buf);
5527 static const BYTE indefiniteSignedPKCSContent[] = {
5528 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5529 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5530 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5531 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5532 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5533 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5534 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5535 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5536 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5537 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5538 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5539 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5540 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5541 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5542 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5543 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5544 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5545 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5546 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5547 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5548 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5549 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5550 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5551 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5552 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5553 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5554 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5555 0x00,0x00,0x00,0x00,0x00,0x00 };
5557 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5559 BOOL ret;
5560 LPBYTE buf = NULL;
5561 DWORD size = 0;
5562 CRYPT_CONTENT_INFO *info;
5564 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5565 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5566 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5567 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5568 if (buf)
5570 info = (CRYPT_CONTENT_INFO *)buf;
5572 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5573 info->pszObjId);
5574 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5575 info->Content.cbData);
5576 LocalFree(buf);
5578 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5579 emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5580 0, NULL, NULL, &size);
5581 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5582 SetLastError(0xdeadbeef);
5583 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5584 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5585 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5586 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5587 * I doubt an app depends on that.
5589 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5590 GetLastError() == CRYPT_E_ASN1_CORRUPT),
5591 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5592 GetLastError());
5593 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5594 intPKCSContentInfo, sizeof(intPKCSContentInfo),
5595 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5596 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5597 if (buf)
5599 info = (CRYPT_CONTENT_INFO *)buf;
5601 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5602 info->pszObjId);
5603 ok(info->Content.cbData == ints[0].encoded[1] + 2,
5604 "Unexpected size %d\n", info->Content.cbData);
5605 ok(!memcmp(info->Content.pbData, ints[0].encoded,
5606 info->Content.cbData), "Unexpected value\n");
5607 LocalFree(buf);
5609 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5610 indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5611 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5612 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5613 if (buf)
5615 info = (CRYPT_CONTENT_INFO *)buf;
5617 ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5618 "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5619 ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5620 info->Content.cbData);
5621 LocalFree(buf);
5625 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5626 0x00 };
5627 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5628 0x01 };
5629 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5630 0x02,0x01,0x01 };
5632 static void test_encodePKCSAttribute(DWORD dwEncoding)
5634 CRYPT_ATTRIBUTE attr = { 0 };
5635 BOOL ret;
5636 LPBYTE buf = NULL;
5637 DWORD size = 0;
5638 CRYPT_ATTR_BLOB blob;
5639 char oid[] = "1.2.3";
5641 SetLastError(0xdeadbeef);
5642 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5643 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5644 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5645 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5646 SetLastError(0xdeadbeef);
5647 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5648 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5649 ok(!ret && GetLastError() == E_INVALIDARG,
5650 "Expected E_INVALIDARG, got %x\n", GetLastError());
5651 attr.pszObjId = oid;
5652 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5653 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5654 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5655 if (buf)
5657 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5658 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5659 LocalFree(buf);
5661 blob.cbData = sizeof(bogusDER);
5662 blob.pbData = bogusDER;
5663 attr.cValue = 1;
5664 attr.rgValue = &blob;
5665 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5666 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5667 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5668 if (buf)
5670 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5671 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5672 LocalFree(buf);
5674 blob.pbData = (BYTE *)ints[0].encoded;
5675 blob.cbData = ints[0].encoded[1] + 2;
5676 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5677 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5678 if (buf)
5680 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5681 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5682 LocalFree(buf);
5686 static void test_decodePKCSAttribute(DWORD dwEncoding)
5688 BOOL ret;
5689 LPBYTE buf = NULL;
5690 DWORD size = 0;
5691 CRYPT_ATTRIBUTE *attr;
5693 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5694 emptyPKCSAttr, sizeof(emptyPKCSAttr),
5695 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5696 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5697 if (buf)
5699 attr = (CRYPT_ATTRIBUTE *)buf;
5701 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5702 attr->pszObjId);
5703 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5704 LocalFree(buf);
5706 SetLastError(0xdeadbeef);
5707 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5708 bogusPKCSAttr, sizeof(bogusPKCSAttr),
5709 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5710 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5711 * I doubt an app depends on that.
5713 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5714 GetLastError() == CRYPT_E_ASN1_CORRUPT),
5715 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5716 GetLastError());
5717 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5718 intPKCSAttr, sizeof(intPKCSAttr),
5719 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5720 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5721 if (buf)
5723 attr = (CRYPT_ATTRIBUTE *)buf;
5725 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5726 attr->pszObjId);
5727 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5728 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5729 "Unexpected size %d\n", attr->rgValue[0].cbData);
5730 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5731 attr->rgValue[0].cbData), "Unexpected value\n");
5732 LocalFree(buf);
5736 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5737 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5738 0x2a,0x03,0x31,0x00 };
5739 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5740 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5742 static void test_encodePKCSAttributes(DWORD dwEncoding)
5744 CRYPT_ATTRIBUTES attributes = { 0 };
5745 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5746 CRYPT_ATTR_BLOB blob;
5747 BOOL ret;
5748 LPBYTE buf = NULL;
5749 DWORD size = 0;
5750 char oid1[] = "1.2.3", oid2[] = "1.5.6";
5752 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5753 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5754 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5755 if (buf)
5757 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5758 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5759 LocalFree(buf);
5761 attributes.cAttr = 1;
5762 attributes.rgAttr = attr;
5763 SetLastError(0xdeadbeef);
5764 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5765 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5766 ok(!ret && GetLastError() == E_INVALIDARG,
5767 "Expected E_INVALIDARG, got %x\n", GetLastError());
5768 attr[0].pszObjId = oid1;
5769 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5770 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5771 if (buf)
5773 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5774 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5775 LocalFree(buf);
5777 attr[1].pszObjId = oid2;
5778 attr[1].cValue = 1;
5779 attr[1].rgValue = &blob;
5780 blob.pbData = (BYTE *)ints[0].encoded;
5781 blob.cbData = ints[0].encoded[1] + 2;
5782 attributes.cAttr = 2;
5783 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5784 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5785 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5786 if (buf)
5788 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5789 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5790 LocalFree(buf);
5794 static void test_decodePKCSAttributes(DWORD dwEncoding)
5796 BOOL ret;
5797 LPBYTE buf = NULL;
5798 DWORD size = 0;
5799 CRYPT_ATTRIBUTES *attributes;
5801 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5802 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5803 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5804 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5805 if (buf)
5807 attributes = (CRYPT_ATTRIBUTES *)buf;
5808 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5809 attributes->cAttr);
5810 LocalFree(buf);
5812 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5813 singlePKCSAttributes, sizeof(singlePKCSAttributes),
5814 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5815 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5816 if (buf)
5818 attributes = (CRYPT_ATTRIBUTES *)buf;
5819 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5820 attributes->cAttr);
5821 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5822 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5823 ok(attributes->rgAttr[0].cValue == 0,
5824 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5825 LocalFree(buf);
5827 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5828 doublePKCSAttributes, sizeof(doublePKCSAttributes),
5829 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5830 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5831 if (buf)
5833 attributes = (CRYPT_ATTRIBUTES *)buf;
5834 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5835 attributes->cAttr);
5836 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5837 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5838 ok(attributes->rgAttr[0].cValue == 0,
5839 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5840 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5841 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5842 ok(attributes->rgAttr[1].cValue == 1,
5843 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5844 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5845 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5846 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5847 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5848 LocalFree(buf);
5852 static const BYTE singleCapability[] = {
5853 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5854 static const BYTE twoCapabilities[] = {
5855 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5856 static const BYTE singleCapabilitywithNULL[] = {
5857 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5859 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
5861 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5862 BOOL ret;
5863 LPBYTE buf = NULL;
5864 DWORD size = 0;
5865 CRYPT_SMIME_CAPABILITY capability[2];
5866 CRYPT_SMIME_CAPABILITIES capabilities;
5868 /* An empty capabilities is allowed */
5869 capabilities.cCapability = 0;
5870 ret = CryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5871 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5872 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5873 if (buf)
5875 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5876 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5877 LocalFree(buf);
5879 /* A non-empty capabilities with an empty capability (lacking an OID) is
5880 * not allowed
5882 capability[0].pszObjId = NULL;
5883 capability[0].Parameters.cbData = 0;
5884 capabilities.cCapability = 1;
5885 capabilities.rgCapability = capability;
5886 SetLastError(0xdeadbeef);
5887 ret = CryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5888 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5889 ok(!ret && GetLastError() == E_INVALIDARG,
5890 "expected E_INVALIDARG, got %08x\n", GetLastError());
5891 capability[0].pszObjId = oid1;
5892 ret = CryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5893 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5894 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5895 if (buf)
5897 ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
5898 ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
5899 LocalFree(buf);
5901 capability[1].pszObjId = oid2;
5902 capability[1].Parameters.cbData = 0;
5903 capabilities.cCapability = 2;
5904 ret = CryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5905 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
5906 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5907 if (buf)
5909 ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
5910 ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
5911 LocalFree(buf);
5915 static void compareSMimeCapabilities(LPCSTR header,
5916 const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
5918 DWORD i;
5920 ok(got->cCapability == expected->cCapability,
5921 "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
5922 got->cCapability);
5923 for (i = 0; i < expected->cCapability; i++)
5925 ok(!strcmp(expected->rgCapability[i].pszObjId,
5926 got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5927 header, i, expected->rgCapability[i].pszObjId,
5928 got->rgCapability[i].pszObjId);
5929 ok(expected->rgCapability[i].Parameters.cbData ==
5930 got->rgCapability[i].Parameters.cbData,
5931 "%s[%d]: expected %d bytes, got %d\n", header, i,
5932 expected->rgCapability[i].Parameters.cbData,
5933 got->rgCapability[i].Parameters.cbData);
5934 if (expected->rgCapability[i].Parameters.cbData)
5935 ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
5936 got->rgCapability[i].Parameters.pbData,
5937 expected->rgCapability[i].Parameters.cbData),
5938 "%s[%d]: unexpected value\n", header, i);
5942 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
5944 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5945 BOOL ret;
5946 DWORD size = 0;
5947 CRYPT_SMIME_CAPABILITY capability[2];
5948 CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
5950 SetLastError(0xdeadbeef);
5951 ret = CryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5952 emptySequence, sizeof(emptySequence),
5953 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
5954 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5955 if (ret)
5957 capabilities.cCapability = 0;
5958 compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
5959 LocalFree(ptr);
5961 SetLastError(0xdeadbeef);
5962 ret = CryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5963 singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
5964 (BYTE *)&ptr, &size);
5965 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5966 if (ret)
5968 capability[0].pszObjId = oid1;
5969 capability[0].Parameters.cbData = 0;
5970 capabilities.cCapability = 1;
5971 capabilities.rgCapability = capability;
5972 compareSMimeCapabilities("single capability", &capabilities, ptr);
5973 LocalFree(ptr);
5975 SetLastError(0xdeadbeef);
5976 ret = CryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5977 singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
5978 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&ptr, &size);
5979 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5980 if (ret)
5982 BYTE NULLparam[] = {0x05, 0x00};
5983 capability[0].pszObjId = oid1;
5984 capability[0].Parameters.cbData = 2;
5985 capability[0].Parameters.pbData = NULLparam;
5986 capabilities.cCapability = 1;
5987 capabilities.rgCapability = capability;
5988 compareSMimeCapabilities("single capability with NULL", &capabilities,
5989 ptr);
5990 LocalFree(ptr);
5992 SetLastError(0xdeadbeef);
5993 ret = CryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
5994 twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
5995 (BYTE *)&ptr, &size);
5996 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5997 if (ret)
5999 capability[0].Parameters.cbData = 0;
6000 capability[1].pszObjId = oid2;
6001 capability[1].Parameters.cbData = 0;
6002 capabilities.cCapability = 2;
6003 compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6004 LocalFree(ptr);
6008 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6009 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6010 0x67 };
6011 static const BYTE minimalPKCSSigner[] = {
6012 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6013 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6014 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6015 static const BYTE PKCSSignerWithSerial[] = {
6016 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6017 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6018 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6019 0x00 };
6020 static const BYTE PKCSSignerWithHashAlgo[] = {
6021 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6022 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6023 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6024 0x00,0x04,0x00 };
6025 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6026 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6027 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6028 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6029 0x06,0x05,0x00,0x04,0x00 };
6030 static const BYTE PKCSSignerWithHash[] = {
6031 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6032 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6033 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6034 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6035 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6036 static const BYTE PKCSSignerWithAuthAttr[] = {
6037 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6038 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6039 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6040 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6041 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6042 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6043 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6045 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6047 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6048 BOOL ret;
6049 LPBYTE buf = NULL;
6050 DWORD size = 0;
6051 CMSG_SIGNER_INFO info = { 0 };
6052 char oid_common_name[] = szOID_COMMON_NAME;
6053 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6054 (LPBYTE)encodedCommonName };
6055 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6057 SetLastError(0xdeadbeef);
6058 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6059 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6060 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6062 skip("no PKCS7_SIGNER_INFO encode support\n");
6063 return;
6065 ok(!ret && GetLastError() == E_INVALIDARG,
6066 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6067 /* To be encoded, a signer must have an issuer at least, and the encoding
6068 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
6069 * see decoding tests.)
6071 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6072 info.Issuer.pbData = encodedCommonNameNoNull;
6073 SetLastError(0xdeadbeef);
6074 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6075 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6076 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6077 ok(!ret && GetLastError() == E_INVALIDARG,
6078 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6079 else
6081 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6082 if (buf)
6084 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6085 if (size == sizeof(minimalPKCSSigner))
6086 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6087 else
6088 ok(0, "Unexpected value\n");
6089 LocalFree(buf);
6092 info.SerialNumber.cbData = sizeof(serialNum);
6093 info.SerialNumber.pbData = (BYTE *)serialNum;
6094 SetLastError(0xdeadbeef);
6095 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6096 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6097 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6098 ok(!ret && GetLastError() == E_INVALIDARG,
6099 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6100 else
6102 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6103 if (buf)
6105 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6106 size);
6107 if (size == sizeof(PKCSSignerWithSerial))
6108 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6109 "Unexpected value\n");
6110 else
6111 ok(0, "Unexpected value\n");
6112 LocalFree(buf);
6115 info.HashAlgorithm.pszObjId = oid1;
6116 SetLastError(0xdeadbeef);
6117 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6118 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6119 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6120 ok(!ret && GetLastError() == E_INVALIDARG,
6121 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6122 else
6124 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6125 if (buf)
6127 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6128 size);
6129 if (size == sizeof(PKCSSignerWithHashAlgo))
6130 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6131 "Unexpected value\n");
6132 else
6133 ok(0, "Unexpected value\n");
6134 LocalFree(buf);
6137 info.HashEncryptionAlgorithm.pszObjId = oid2;
6138 SetLastError(0xdeadbeef);
6139 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6140 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6141 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6142 ok(!ret && GetLastError() == E_INVALIDARG,
6143 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6144 else
6146 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6147 if (buf)
6149 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6150 "Unexpected size %d\n", size);
6151 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6152 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6153 "Unexpected value\n");
6154 else
6155 ok(0, "Unexpected value\n");
6156 LocalFree(buf);
6159 info.EncryptedHash.cbData = sizeof(hash);
6160 info.EncryptedHash.pbData = (BYTE *)hash;
6161 SetLastError(0xdeadbeef);
6162 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6163 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6164 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6165 ok(!ret && GetLastError() == E_INVALIDARG,
6166 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6167 else
6169 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6170 if (buf)
6172 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6173 size);
6174 if (size == sizeof(PKCSSignerWithHash))
6175 ok(!memcmp(buf, PKCSSignerWithHash, size),
6176 "Unexpected value\n");
6177 else
6178 ok(0, "Unexpected value\n");
6179 LocalFree(buf);
6182 info.AuthAttrs.cAttr = 1;
6183 info.AuthAttrs.rgAttr = &attr;
6184 SetLastError(0xdeadbeef);
6185 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6186 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6187 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6188 ok(!ret && GetLastError() == E_INVALIDARG,
6189 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6190 else
6192 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6193 if (buf)
6195 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6196 size);
6197 if (size == sizeof(PKCSSignerWithAuthAttr))
6198 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6199 "Unexpected value\n");
6200 else
6201 ok(0, "Unexpected value\n");
6202 LocalFree(buf);
6207 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6209 BOOL ret;
6210 LPBYTE buf = NULL;
6211 DWORD size = 0;
6212 CMSG_SIGNER_INFO *info;
6214 /* A PKCS signer can't be decoded without a serial number. */
6215 SetLastError(0xdeadbeef);
6216 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6217 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6218 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6219 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
6220 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6221 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6222 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6223 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6224 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6225 if (buf)
6227 info = (CMSG_SIGNER_INFO *)buf;
6228 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6229 info->dwVersion);
6230 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6231 "Unexpected size %d\n", info->Issuer.cbData);
6232 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6233 info->Issuer.cbData), "Unexpected value\n");
6234 ok(info->SerialNumber.cbData == sizeof(serialNum),
6235 "Unexpected size %d\n", info->SerialNumber.cbData);
6236 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6237 "Unexpected value\n");
6238 LocalFree(buf);
6240 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6241 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6242 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6243 if (buf)
6245 info = (CMSG_SIGNER_INFO *)buf;
6246 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6247 info->dwVersion);
6248 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6249 "Unexpected size %d\n", info->Issuer.cbData);
6250 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6251 info->Issuer.cbData), "Unexpected value\n");
6252 ok(info->SerialNumber.cbData == sizeof(serialNum),
6253 "Unexpected size %d\n", info->SerialNumber.cbData);
6254 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6255 "Unexpected value\n");
6256 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6257 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6258 LocalFree(buf);
6260 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6261 PKCSSignerWithHashAndEncryptionAlgo,
6262 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6263 NULL, (BYTE *)&buf, &size);
6264 if (buf)
6266 info = (CMSG_SIGNER_INFO *)buf;
6267 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6268 info->dwVersion);
6269 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6270 "Unexpected size %d\n", info->Issuer.cbData);
6271 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6272 info->Issuer.cbData), "Unexpected value\n");
6273 ok(info->SerialNumber.cbData == sizeof(serialNum),
6274 "Unexpected size %d\n", info->SerialNumber.cbData);
6275 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6276 "Unexpected value\n");
6277 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6278 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6279 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6280 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6281 LocalFree(buf);
6283 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6284 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6285 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6286 if (buf)
6288 info = (CMSG_SIGNER_INFO *)buf;
6289 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6290 info->dwVersion);
6291 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6292 "Unexpected size %d\n", info->Issuer.cbData);
6293 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6294 info->Issuer.cbData), "Unexpected value\n");
6295 ok(info->SerialNumber.cbData == sizeof(serialNum),
6296 "Unexpected size %d\n", info->SerialNumber.cbData);
6297 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6298 "Unexpected value\n");
6299 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6300 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6301 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6302 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6303 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6304 info->EncryptedHash.cbData);
6305 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6306 "Unexpected value\n");
6307 LocalFree(buf);
6309 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6310 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6311 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6312 if (buf)
6314 info = (CMSG_SIGNER_INFO *)buf;
6315 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6316 info->AuthAttrs.cAttr);
6317 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6318 "Expected %s, got %s\n", szOID_COMMON_NAME,
6319 info->AuthAttrs.rgAttr[0].pszObjId);
6320 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6321 info->AuthAttrs.rgAttr[0].cValue);
6322 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6323 sizeof(encodedCommonName), "Unexpected size %d\n",
6324 info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6325 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6326 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6327 LocalFree(buf);
6331 static const BYTE CMSSignerWithKeyId[] = {
6332 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6333 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6335 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6337 BOOL ret;
6338 LPBYTE buf = NULL;
6339 DWORD size = 0;
6340 CMSG_CMS_SIGNER_INFO info = { 0 };
6341 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6343 SetLastError(0xdeadbeef);
6344 ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6345 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6346 ok(!ret && GetLastError() == E_INVALIDARG,
6347 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6348 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6349 SetLastError(0xdeadbeef);
6350 ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6351 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6352 ok(!ret && GetLastError() == E_INVALIDARG,
6353 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6354 /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6355 * be a key id or a issuer serial number with at least the issuer set, and
6356 * the encoding must include PKCS_7_ASN_ENCODING.
6357 * (That isn't enough to be decoded, see decoding tests.)
6359 info.SignerId.IssuerSerialNumber.Issuer.cbData =
6360 sizeof(encodedCommonNameNoNull);
6361 info.SignerId.IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6362 SetLastError(0xdeadbeef);
6363 ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6364 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6365 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6366 ok(!ret && GetLastError() == E_INVALIDARG,
6367 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6368 else
6370 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6371 if (buf)
6373 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6374 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6375 LocalFree(buf);
6378 info.SignerId.IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6379 info.SignerId.IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6380 SetLastError(0xdeadbeef);
6381 ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6382 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6383 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6384 ok(!ret && GetLastError() == E_INVALIDARG,
6385 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6386 else
6388 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6389 if (buf)
6391 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6392 size);
6393 ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6394 LocalFree(buf);
6397 info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6398 info.SignerId.KeyId.cbData = sizeof(serialNum);
6399 info.SignerId.KeyId.pbData = (BYTE *)serialNum;
6400 SetLastError(0xdeadbeef);
6401 ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6402 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6403 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6404 ok(!ret && GetLastError() == E_INVALIDARG,
6405 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6406 else
6408 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6409 if (buf)
6411 ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6412 size);
6413 ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6414 LocalFree(buf);
6417 /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6418 * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6419 * (see RFC 3852, section 5.3.)
6421 info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6422 info.SignerId.HashId.cbData = sizeof(hash);
6423 info.SignerId.HashId.pbData = (BYTE *)hash;
6424 SetLastError(0xdeadbeef);
6425 ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6426 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6427 ok(!ret && GetLastError() == E_INVALIDARG,
6428 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6429 /* Now with a hash algo */
6430 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6431 info.SignerId.IssuerSerialNumber.Issuer.cbData =
6432 sizeof(encodedCommonNameNoNull);
6433 info.SignerId.IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6434 info.HashAlgorithm.pszObjId = oid1;
6435 SetLastError(0xdeadbeef);
6436 ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6437 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6438 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6439 ok(!ret && GetLastError() == E_INVALIDARG,
6440 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6441 else
6443 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6444 if (buf)
6446 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6447 size);
6448 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6449 "Unexpected value\n");
6450 LocalFree(buf);
6453 info.HashEncryptionAlgorithm.pszObjId = oid2;
6454 SetLastError(0xdeadbeef);
6455 ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6456 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6457 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6458 ok(!ret && GetLastError() == E_INVALIDARG,
6459 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6460 else
6462 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6463 if (buf)
6465 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6466 "Unexpected size %d\n", size);
6467 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6468 "Unexpected value\n");
6469 LocalFree(buf);
6472 info.EncryptedHash.cbData = sizeof(hash);
6473 info.EncryptedHash.pbData = (BYTE *)hash;
6474 SetLastError(0xdeadbeef);
6475 ret = CryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6476 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6477 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6478 ok(!ret && GetLastError() == E_INVALIDARG,
6479 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6480 else
6482 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6483 if (buf)
6485 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6486 size);
6487 ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6488 LocalFree(buf);
6493 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6495 BOOL ret;
6496 LPBYTE buf = NULL;
6497 DWORD size = 0;
6498 CMSG_CMS_SIGNER_INFO *info;
6499 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6501 /* A CMS signer can't be decoded without a serial number. */
6502 SetLastError(0xdeadbeef);
6503 ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6504 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6505 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6506 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
6507 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6508 ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6509 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6510 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6511 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6512 if (buf)
6514 info = (CMSG_CMS_SIGNER_INFO *)buf;
6515 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6516 info->dwVersion);
6517 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6518 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6519 info->SignerId.dwIdChoice);
6520 ok(info->SignerId.IssuerSerialNumber.Issuer.cbData ==
6521 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6522 info->SignerId.IssuerSerialNumber.Issuer.cbData);
6523 ok(!memcmp(info->SignerId.IssuerSerialNumber.Issuer.pbData,
6524 encodedCommonNameNoNull,
6525 info->SignerId.IssuerSerialNumber.Issuer.cbData),
6526 "Unexpected value\n");
6527 ok(info->SignerId.IssuerSerialNumber.SerialNumber.cbData ==
6528 sizeof(serialNum), "Unexpected size %d\n",
6529 info->SignerId.IssuerSerialNumber.SerialNumber.cbData);
6530 ok(!memcmp(info->SignerId.IssuerSerialNumber.SerialNumber.pbData,
6531 serialNum, sizeof(serialNum)), "Unexpected value\n");
6532 LocalFree(buf);
6534 ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6535 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6536 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6537 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6538 if (buf)
6540 info = (CMSG_CMS_SIGNER_INFO *)buf;
6541 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6542 info->dwVersion);
6543 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6544 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6545 info->SignerId.dwIdChoice);
6546 ok(info->SignerId.IssuerSerialNumber.Issuer.cbData ==
6547 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6548 info->SignerId.IssuerSerialNumber.Issuer.cbData);
6549 ok(!memcmp(info->SignerId.IssuerSerialNumber.Issuer.pbData,
6550 encodedCommonNameNoNull,
6551 info->SignerId.IssuerSerialNumber.Issuer.cbData),
6552 "Unexpected value\n");
6553 ok(info->SignerId.IssuerSerialNumber.SerialNumber.cbData ==
6554 sizeof(serialNum), "Unexpected size %d\n",
6555 info->SignerId.IssuerSerialNumber.SerialNumber.cbData);
6556 ok(!memcmp(info->SignerId.IssuerSerialNumber.SerialNumber.pbData,
6557 serialNum, sizeof(serialNum)), "Unexpected value\n");
6558 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6559 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6560 LocalFree(buf);
6562 ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6563 PKCSSignerWithHashAndEncryptionAlgo,
6564 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6565 NULL, (BYTE *)&buf, &size);
6566 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6567 if (buf)
6569 info = (CMSG_CMS_SIGNER_INFO *)buf;
6570 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6571 info->dwVersion);
6572 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6573 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6574 info->SignerId.dwIdChoice);
6575 ok(info->SignerId.IssuerSerialNumber.Issuer.cbData ==
6576 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6577 info->SignerId.IssuerSerialNumber.Issuer.cbData);
6578 ok(!memcmp(info->SignerId.IssuerSerialNumber.Issuer.pbData,
6579 encodedCommonNameNoNull,
6580 info->SignerId.IssuerSerialNumber.Issuer.cbData),
6581 "Unexpected value\n");
6582 ok(info->SignerId.IssuerSerialNumber.SerialNumber.cbData ==
6583 sizeof(serialNum), "Unexpected size %d\n",
6584 info->SignerId.IssuerSerialNumber.SerialNumber.cbData);
6585 ok(!memcmp(info->SignerId.IssuerSerialNumber.SerialNumber.pbData,
6586 serialNum, sizeof(serialNum)), "Unexpected value\n");
6587 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6588 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6589 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6590 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6591 LocalFree(buf);
6593 ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6594 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6595 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6596 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6597 if (buf)
6599 info = (CMSG_CMS_SIGNER_INFO *)buf;
6600 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6601 info->dwVersion);
6602 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6603 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6604 info->SignerId.dwIdChoice);
6605 ok(info->SignerId.IssuerSerialNumber.Issuer.cbData ==
6606 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6607 info->SignerId.IssuerSerialNumber.Issuer.cbData);
6608 ok(!memcmp(info->SignerId.IssuerSerialNumber.Issuer.pbData,
6609 encodedCommonNameNoNull,
6610 info->SignerId.IssuerSerialNumber.Issuer.cbData),
6611 "Unexpected value\n");
6612 ok(info->SignerId.IssuerSerialNumber.SerialNumber.cbData ==
6613 sizeof(serialNum), "Unexpected size %d\n",
6614 info->SignerId.IssuerSerialNumber.SerialNumber.cbData);
6615 ok(!memcmp(info->SignerId.IssuerSerialNumber.SerialNumber.pbData,
6616 serialNum, sizeof(serialNum)), "Unexpected value\n");
6617 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6618 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6619 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6620 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6621 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6622 info->EncryptedHash.cbData);
6623 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6624 "Unexpected value\n");
6625 LocalFree(buf);
6627 ret = CryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6628 CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6629 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6630 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6631 if (buf)
6633 info = (CMSG_CMS_SIGNER_INFO *)buf;
6634 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6635 info->dwVersion);
6636 ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6637 "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6638 info->SignerId.dwIdChoice);
6639 ok(info->SignerId.KeyId.cbData == sizeof(serialNum),
6640 "Unexpected size %d\n", info->SignerId.KeyId.cbData);
6641 ok(!memcmp(info->SignerId.KeyId.pbData, serialNum, sizeof(serialNum)),
6642 "Unexpected value\n");
6643 LocalFree(buf);
6647 static BYTE emptyDNSPermittedConstraints[] = {
6648 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6649 static BYTE emptyDNSExcludedConstraints[] = {
6650 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6651 static BYTE DNSExcludedConstraints[] = {
6652 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6653 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6654 static BYTE permittedAndExcludedConstraints[] = {
6655 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6656 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6657 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6658 static BYTE permittedAndExcludedWithMinConstraints[] = {
6659 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6660 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6661 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6662 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6663 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6664 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6665 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6667 static void test_encodeNameConstraints(DWORD dwEncoding)
6669 BOOL ret;
6670 CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6671 CERT_GENERAL_SUBTREE permitted = { { 0 } };
6672 CERT_GENERAL_SUBTREE excluded = { { 0 } };
6673 LPBYTE buf;
6674 DWORD size;
6676 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6677 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6678 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6680 skip("no X509_NAME_CONSTRAINTS encode support\n");
6681 return;
6683 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6684 if (ret)
6686 ok(size == sizeof(emptySequence), "Unexpected size\n");
6687 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6688 LocalFree(buf);
6690 constraints.cPermittedSubtree = 1;
6691 constraints.rgPermittedSubtree = &permitted;
6692 SetLastError(0xdeadbeef);
6693 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6694 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6695 ok(!ret && GetLastError() == E_INVALIDARG,
6696 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6697 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6698 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6699 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6700 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6701 if (ret)
6703 ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6704 ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6705 "Unexpected value\n");
6706 LocalFree(buf);
6708 constraints.cPermittedSubtree = 0;
6709 constraints.cExcludedSubtree = 1;
6710 constraints.rgExcludedSubtree = &excluded;
6711 excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6712 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6713 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6714 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6715 if (ret)
6717 ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6718 ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6719 "Unexpected value\n");
6720 LocalFree(buf);
6722 U(excluded.Base).pwszURL = (LPWSTR)url;
6723 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6724 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6725 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6726 if (ret)
6728 ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6729 ok(!memcmp(buf, DNSExcludedConstraints, size),
6730 "Unexpected value\n");
6731 LocalFree(buf);
6733 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6734 U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6735 U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6736 constraints.cPermittedSubtree = 1;
6737 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6738 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6739 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6740 if (ret)
6742 ok(size == sizeof(permittedAndExcludedConstraints),
6743 "Unexpected size\n");
6744 ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6745 "Unexpected value\n");
6746 LocalFree(buf);
6748 permitted.dwMinimum = 5;
6749 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6750 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6751 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6752 if (ret)
6754 ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6755 "Unexpected size\n");
6756 ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6757 "Unexpected value\n");
6758 LocalFree(buf);
6760 permitted.fMaximum = TRUE;
6761 permitted.dwMaximum = 3;
6762 SetLastError(0xdeadbeef);
6763 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6764 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
6765 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6766 if (ret)
6768 ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6769 "Unexpected size\n");
6770 ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6771 "Unexpected value\n");
6772 LocalFree(buf);
6776 struct EncodedNameConstraints
6778 CRYPT_DATA_BLOB encoded;
6779 CERT_NAME_CONSTRAINTS_INFO constraints;
6782 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6783 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6784 static CERT_GENERAL_SUBTREE DNSSubtree = {
6785 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6786 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6787 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6788 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6789 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6790 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6791 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6793 struct EncodedNameConstraints encodedNameConstraints[] = {
6794 { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6795 { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6796 { 1, &emptyDNSSubtree, 0, NULL } },
6797 { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6798 { 0, NULL, 1, &emptyDNSSubtree } },
6799 { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6800 { 0, NULL, 1, &DNSSubtree } },
6801 { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6802 { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6803 { { sizeof(permittedAndExcludedWithMinConstraints),
6804 permittedAndExcludedWithMinConstraints },
6805 { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6806 { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6807 permittedAndExcludedWithMinMaxConstraints },
6808 { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6811 static void test_decodeNameConstraints(DWORD dwEncoding)
6813 BOOL ret;
6814 DWORD i;
6815 CERT_NAME_CONSTRAINTS_INFO *constraints;
6817 U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6818 U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6819 U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6820 U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6821 U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6822 U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6823 U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6824 for (i = 0;
6825 i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6826 i++)
6828 DWORD size;
6830 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6831 encodedNameConstraints[i].encoded.pbData,
6832 encodedNameConstraints[i].encoded.cbData,
6833 CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
6834 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6836 skip("no X509_NAME_CONSTRAINTS decode support\n");
6837 return;
6839 ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
6840 if (ret)
6842 DWORD j;
6844 if (constraints->cPermittedSubtree !=
6845 encodedNameConstraints[i].constraints.cPermittedSubtree)
6846 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
6847 encodedNameConstraints[i].constraints.cPermittedSubtree,
6848 constraints->cPermittedSubtree);
6849 if (constraints->cPermittedSubtree ==
6850 encodedNameConstraints[i].constraints.cPermittedSubtree)
6852 for (j = 0; j < constraints->cPermittedSubtree; j++)
6854 compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
6855 &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
6858 if (constraints->cExcludedSubtree !=
6859 encodedNameConstraints[i].constraints.cExcludedSubtree)
6860 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
6861 encodedNameConstraints[i].constraints.cExcludedSubtree,
6862 constraints->cExcludedSubtree);
6863 if (constraints->cExcludedSubtree ==
6864 encodedNameConstraints[i].constraints.cExcludedSubtree)
6866 for (j = 0; j < constraints->cExcludedSubtree; j++)
6868 compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
6869 &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
6872 LocalFree(constraints);
6877 /* Free *pInfo with HeapFree */
6878 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
6880 BOOL ret;
6881 DWORD size = 0;
6882 HCRYPTKEY key;
6884 /* This crashes
6885 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
6887 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
6888 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6889 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6890 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
6891 &size);
6892 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6893 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6894 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
6895 NULL, &size);
6896 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6897 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6898 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
6899 0, NULL, NULL, &size);
6900 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6901 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6902 /* Test with no key */
6903 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
6904 0, NULL, NULL, &size);
6905 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
6906 GetLastError());
6907 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
6908 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
6909 if (ret)
6911 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
6912 NULL, 0, NULL, NULL, &size);
6913 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
6914 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
6915 if (*pInfo)
6917 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
6918 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
6919 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
6920 GetLastError());
6921 if (ret)
6923 /* By default (we passed NULL as the OID) the OID is
6924 * szOID_RSA_RSA.
6926 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
6927 "Expected %s, got %s\n", szOID_RSA_RSA,
6928 (*pInfo)->Algorithm.pszObjId);
6932 CryptDestroyKey(key);
6935 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
6936 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
6937 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
6938 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
6939 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
6940 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
6941 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
6942 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
6943 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
6944 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
6945 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
6946 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
6947 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
6948 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
6949 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
6950 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
6951 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
6952 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
6953 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
6954 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
6955 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
6956 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
6957 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
6958 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
6959 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
6961 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
6963 BOOL ret;
6964 HCRYPTKEY key;
6965 PCCERT_CONTEXT context;
6966 DWORD dwSize;
6967 ALG_ID ai;
6969 /* These crash
6970 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
6971 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
6972 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
6973 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
6974 NULL);
6976 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
6977 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
6978 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
6979 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
6980 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
6981 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
6982 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
6983 &key);
6984 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
6985 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
6987 /* Export key with standard algorithm (CALG_RSA_KEYX) */
6988 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
6989 &key);
6990 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
6992 dwSize = sizeof(ai);
6993 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
6994 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
6995 if(ret)
6997 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
6998 ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7001 CryptDestroyKey(key);
7003 /* Repeat with forced algorithm */
7004 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7005 &key);
7006 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7008 dwSize = sizeof(ai);
7009 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7010 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7011 if(ret)
7013 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7014 ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7017 CryptDestroyKey(key);
7019 /* Test importing a public key from a certificate context */
7020 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7021 sizeof(expiredCert));
7022 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7023 GetLastError());
7024 if (context)
7026 ok(!strcmp(szOID_RSA_RSA,
7027 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7028 "Expected %s, got %s\n", szOID_RSA_RSA,
7029 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7030 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7031 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7032 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7033 CryptDestroyKey(key);
7034 CertFreeCertificateContext(context);
7038 static const char cspName[] = "WineCryptTemp";
7040 static void testPortPublicKeyInfo(void)
7042 HCRYPTPROV csp;
7043 BOOL ret;
7044 PCERT_PUBLIC_KEY_INFO info = NULL;
7046 /* Just in case a previous run failed, delete this thing */
7047 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7048 CRYPT_DELETEKEYSET);
7049 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7050 CRYPT_NEWKEYSET);
7052 testExportPublicKey(csp, &info);
7053 testImportPublicKey(csp, info);
7055 HeapFree(GetProcessHeap(), 0, info);
7056 CryptReleaseContext(csp, 0);
7057 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7058 CRYPT_DELETEKEYSET);
7061 START_TEST(encode)
7063 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7064 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7065 HMODULE hCrypt32;
7066 DWORD i;
7068 hCrypt32 = GetModuleHandleA("crypt32.dll");
7069 pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7070 pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7071 if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7073 skip("CryptDecodeObjectEx() is not available\n");
7074 return;
7077 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7079 test_encodeInt(encodings[i]);
7080 test_decodeInt(encodings[i]);
7081 test_encodeEnumerated(encodings[i]);
7082 test_decodeEnumerated(encodings[i]);
7083 test_encodeFiletime(encodings[i]);
7084 test_decodeFiletime(encodings[i]);
7085 test_encodeName(encodings[i]);
7086 test_decodeName(encodings[i]);
7087 test_encodeUnicodeName(encodings[i]);
7088 test_decodeUnicodeName(encodings[i]);
7089 test_encodeNameValue(encodings[i]);
7090 test_decodeNameValue(encodings[i]);
7091 test_encodeUnicodeNameValue(encodings[i]);
7092 test_decodeUnicodeNameValue(encodings[i]);
7093 test_encodeAltName(encodings[i]);
7094 test_decodeAltName(encodings[i]);
7095 test_encodeOctets(encodings[i]);
7096 test_decodeOctets(encodings[i]);
7097 test_encodeBits(encodings[i]);
7098 test_decodeBits(encodings[i]);
7099 test_encodeBasicConstraints(encodings[i]);
7100 test_decodeBasicConstraints(encodings[i]);
7101 test_encodeRsaPublicKey(encodings[i]);
7102 test_decodeRsaPublicKey(encodings[i]);
7103 test_encodeSequenceOfAny(encodings[i]);
7104 test_decodeSequenceOfAny(encodings[i]);
7105 test_encodeExtensions(encodings[i]);
7106 test_decodeExtensions(encodings[i]);
7107 test_encodePublicKeyInfo(encodings[i]);
7108 test_decodePublicKeyInfo(encodings[i]);
7109 test_encodeCertToBeSigned(encodings[i]);
7110 test_decodeCertToBeSigned(encodings[i]);
7111 test_encodeCert(encodings[i]);
7112 test_decodeCert(encodings[i]);
7113 test_encodeCRLDistPoints(encodings[i]);
7114 test_decodeCRLDistPoints(encodings[i]);
7115 test_encodeCRLIssuingDistPoint(encodings[i]);
7116 test_decodeCRLIssuingDistPoint(encodings[i]);
7117 test_encodeCRLToBeSigned(encodings[i]);
7118 test_decodeCRLToBeSigned(encodings[i]);
7119 test_encodeEnhancedKeyUsage(encodings[i]);
7120 test_decodeEnhancedKeyUsage(encodings[i]);
7121 test_encodeAuthorityKeyId(encodings[i]);
7122 test_decodeAuthorityKeyId(encodings[i]);
7123 test_encodeAuthorityKeyId2(encodings[i]);
7124 test_decodeAuthorityKeyId2(encodings[i]);
7125 test_encodeAuthorityInfoAccess(encodings[i]);
7126 test_decodeAuthorityInfoAccess(encodings[i]);
7127 test_encodeCTL(encodings[i]);
7128 test_decodeCTL(encodings[i]);
7129 test_encodePKCSContentInfo(encodings[i]);
7130 test_decodePKCSContentInfo(encodings[i]);
7131 test_encodePKCSAttribute(encodings[i]);
7132 test_decodePKCSAttribute(encodings[i]);
7133 test_encodePKCSAttributes(encodings[i]);
7134 test_decodePKCSAttributes(encodings[i]);
7135 test_encodePKCSSMimeCapabilities(encodings[i]);
7136 test_decodePKCSSMimeCapabilities(encodings[i]);
7137 test_encodePKCSSignerInfo(encodings[i]);
7138 test_decodePKCSSignerInfo(encodings[i]);
7139 test_encodeCMSSignerInfo(encodings[i]);
7140 test_decodeCMSSignerInfo(encodings[i]);
7141 test_encodeNameConstraints(encodings[i]);
7142 test_decodeNameConstraints(encodings[i]);
7144 testPortPublicKeyInfo();