push 52d6b63ba2f2d4f9b02b6b922d27bff05a60596f
[wine/hacks.git] / dlls / crypt32 / tests / encode.c
blob1e93dfc284cb3387649840f7ba5e138860d1c289
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 if (0)
107 /* check with NULL integer buffer. Windows XP incorrectly returns an
108 * NTSTATUS (crashes on win9x).
110 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111 &bufSize);
112 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
115 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
117 /* encode as normal integer */
118 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119 NULL, NULL, &bufSize);
120 ok(ret, "Expected success, got %d\n", GetLastError());
121 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124 if (buf)
126 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127 buf[0]);
128 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129 buf[1], ints[i].encoded[1]);
130 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132 LocalFree(buf);
134 /* encode as multibyte integer */
135 blob.cbData = sizeof(ints[i].val);
136 blob.pbData = (BYTE *)&ints[i].val;
137 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138 0, NULL, NULL, &bufSize);
139 ok(ret, "Expected success, got %d\n", GetLastError());
140 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143 if (buf)
145 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146 buf[0]);
147 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148 buf[1], ints[i].encoded[1]);
149 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151 LocalFree(buf);
154 /* encode a couple bigger ints, just to show it's little-endian and leading
155 * sign bytes are dropped
157 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
159 blob.cbData = strlen((const char*)bigInts[i].val);
160 blob.pbData = (BYTE *)bigInts[i].val;
161 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162 0, NULL, NULL, &bufSize);
163 ok(ret, "Expected success, got %d\n", GetLastError());
164 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167 if (buf)
169 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170 buf[0]);
171 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172 buf[1], bigInts[i].encoded[1]);
173 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174 bigInts[i].encoded[1] + 1),
175 "Encoded value didn't match expected\n");
176 LocalFree(buf);
179 /* and, encode some uints */
180 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
182 blob.cbData = strlen((const char*)bigUInts[i].val);
183 blob.pbData = (BYTE*)bigUInts[i].val;
184 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185 0, NULL, NULL, &bufSize);
186 ok(ret, "Expected success, got %d\n", GetLastError());
187 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190 if (buf)
192 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193 buf[0]);
194 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195 buf[1], bigUInts[i].encoded[1]);
196 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197 bigUInts[i].encoded[1] + 1),
198 "Encoded value didn't match expected\n");
199 LocalFree(buf);
204 static void test_decodeInt(DWORD dwEncoding)
206 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210 static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211 BYTE *buf = NULL;
212 DWORD bufSize = 0;
213 int i;
214 BOOL ret;
216 /* CryptDecodeObjectEx with NULL bufSize crashes..
217 ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
220 /* check bogus encoding */
221 ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225 /* check with NULL integer buffer */
226 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227 &bufSize);
228 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229 GetLastError() == OSS_BAD_ARG /* Win9x */),
230 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231 /* check with a valid, but too large, integer */
232 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
234 ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) ||
235 broken(ret) /* Win9x */,
236 "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError());
237 /* check with a DER-encoded string */
238 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
239 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
240 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
241 GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
242 "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
243 GetLastError());
244 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
246 /* When the output buffer is NULL, this always succeeds */
247 SetLastError(0xdeadbeef);
248 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249 ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250 &bufSize);
251 ok(ret && GetLastError() == NOERROR,
252 "Expected success and NOERROR, got %d\n", GetLastError());
253 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254 ints[i].encoded, ints[i].encoded[1] + 2,
255 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
256 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
257 ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize);
258 ok(buf != NULL, "Expected allocated buffer\n");
259 if (buf)
261 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262 ints[i].val, *(int *)buf);
263 LocalFree(buf);
266 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
268 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270 &bufSize);
271 ok(ret && GetLastError() == NOERROR,
272 "Expected success and NOERROR, got %d\n", GetLastError());
273 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274 bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
276 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278 ok(buf != NULL, "Expected allocated buffer\n");
279 if (buf)
281 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
283 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284 "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285 blob->cbData);
286 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287 "Unexpected value\n");
288 LocalFree(buf);
291 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
293 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295 &bufSize);
296 ok(ret && GetLastError() == NOERROR,
297 "Expected success and NOERROR, got %d\n", GetLastError());
298 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
301 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303 ok(buf != NULL, "Expected allocated buffer\n");
304 if (buf)
306 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
308 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309 "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310 blob->cbData);
311 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312 "Unexpected value\n");
313 LocalFree(buf);
316 /* Decode the value 1 with long-form length */
317 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
319 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320 if (buf)
322 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323 LocalFree(buf);
325 /* check with extra bytes at the end */
326 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327 sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
328 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329 if (buf)
331 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332 LocalFree(buf);
334 /* Try to decode some bogus large items */
335 /* The buffer size is smaller than the encoded length, so this should fail
336 * with CRYPT_E_ASN1_EOD if it's being decoded.
337 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339 * So this test unfortunately isn't useful.
340 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
342 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343 "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
345 /* This will try to decode the buffer and overflow it, check that it's
346 * caught.
348 if (0)
350 /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
353 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
361 /* These are always encoded unsigned, and aren't constrained to be any
362 * particular value
364 static const struct encodedInt enums[] = {
365 { 1, bin18 },
366 { -128, bin19 },
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370 * X509_ENUMERATED.
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373 szOID_CRL_REASON_CODE };
375 static void test_encodeEnumerated(DWORD dwEncoding)
377 DWORD i, j;
379 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
381 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
383 BOOL ret;
384 BYTE *buf = NULL;
385 DWORD bufSize = 0;
387 ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
389 &bufSize);
390 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391 if (buf)
393 ok(buf[0] == 0xa,
394 "Got unexpected type %d for enumerated (expected 0xa)\n",
395 buf[0]);
396 ok(buf[1] == enums[j].encoded[1],
397 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399 enums[j].encoded[1] + 1),
400 "Encoded value of 0x%08x didn't match expected\n",
401 enums[j].val);
402 LocalFree(buf);
408 static void test_decodeEnumerated(DWORD dwEncoding)
410 DWORD i, j;
412 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
414 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
416 BOOL ret;
417 DWORD bufSize = sizeof(int);
418 int val;
420 ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422 &val, &bufSize);
423 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424 ok(bufSize == sizeof(int),
425 "Got unexpected size %d for enumerated\n", bufSize);
426 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427 val, enums[j].val);
432 struct encodedFiletime
434 SYSTEMTIME sysTime;
435 const BYTE *encodedTime;
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439 const struct encodedFiletime *time)
441 FILETIME ft = { 0 };
442 BYTE *buf = NULL;
443 DWORD bufSize = 0;
444 BOOL ret;
446 ret = SystemTimeToFileTime(&time->sysTime, &ft);
447 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448 ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
450 /* years other than 1950-2050 are not allowed for encodings other than
451 * X509_CHOICE_OF_TIME.
453 if (structType == X509_CHOICE_OF_TIME ||
454 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
456 ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457 GetLastError());
458 ok(buf != NULL, "Expected an allocated buffer\n");
459 if (buf)
461 ok(buf[0] == time->encodedTime[0],
462 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463 buf[0]);
464 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465 time->encodedTime[1], bufSize);
466 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467 "Got unexpected value for time encoding\n");
468 LocalFree(buf);
471 else
472 ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473 broken(GetLastError() == ERROR_SUCCESS),
474 "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
477 static const char *printSystemTime(const SYSTEMTIME *st)
479 static char buf[25];
481 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482 st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483 return buf;
486 static const char *printFileTime(const FILETIME *ft)
488 static char buf[25];
489 SYSTEMTIME st;
491 FileTimeToSystemTime(ft, &st);
492 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493 st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494 return buf;
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
499 SYSTEMTIME st;
501 FileTimeToSystemTime(got, &st);
502 ok((expected->wYear == st.wYear &&
503 expected->wMonth == st.wMonth &&
504 expected->wDay == st.wDay &&
505 expected->wHour == st.wHour &&
506 expected->wMinute == st.wMinute &&
507 expected->wSecond == st.wSecond &&
508 abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509 /* Some Windows systems only seem to be accurate in their time decoding to
510 * within about an hour.
512 broken(expected->wYear == st.wYear &&
513 expected->wMonth == st.wMonth &&
514 expected->wDay == st.wDay &&
515 abs(expected->wHour - st.wHour) <= 1),
516 "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517 printSystemTime(expected), printFileTime(got));
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521 const struct encodedFiletime *time)
523 FILETIME ft = { 0 };
524 DWORD size = sizeof(ft);
525 BOOL ret;
527 ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528 time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529 /* years other than 1950-2050 are not allowed for encodings other than
530 * X509_CHOICE_OF_TIME.
532 if (structType == X509_CHOICE_OF_TIME ||
533 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
535 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536 "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537 GetLastError());
538 if (ret)
539 compareTime(&time->sysTime, &ft);
541 else
542 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543 GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544 "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545 GetLastError());
548 static const BYTE bin20[] = {
549 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
555 static const struct encodedFiletime times[] = {
556 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
561 static void test_encodeFiletime(DWORD dwEncoding)
563 DWORD i;
565 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
567 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
573 static const BYTE bin23[] = {
574 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598 0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602 0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604 0x18,0x08, '2','1','4','5','0','6','0','6'};
606 static void test_decodeFiletime(DWORD dwEncoding)
608 static const struct encodedFiletime otherTimes[] = {
609 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
610 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
612 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
613 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
614 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
615 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
616 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
617 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
618 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
619 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
620 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
622 /* An oddball case that succeeds in Windows, but doesn't seem correct
623 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
625 static const unsigned char *bogusTimes[] = {
626 /* oddly, this succeeds on Windows, with year 2765
627 "\x18" "\x0f" "21r50606161000Z",
629 bin35,
630 bin36,
631 bin37,
632 bin38,
634 DWORD i, size;
635 FILETIME ft1 = { 0 }, ft2 = { 0 };
636 BOOL ret;
638 /* Check bogus length with non-NULL buffer */
639 ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641 size = 1;
642 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644 ok(!ret && GetLastError() == ERROR_MORE_DATA,
645 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646 /* Normal tests */
647 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
649 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
653 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
655 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
659 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
661 size = sizeof(ft1);
662 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664 ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665 GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666 broken(ret), /* Win9x and NT4 for bin38 */
667 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668 GetLastError());
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
675 static const BYTE emptySequence[] = { 0x30, 0 };
676 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
677 static const BYTE twoRDNs[] = {
678 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
679 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
680 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
681 static const BYTE encodedTwoRDNs[] = {
682 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
683 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
684 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
685 0x6e,0x67,0x00,
688 static const BYTE us[] = { 0x55, 0x53 };
689 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
690 0x74, 0x61 };
691 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
692 0x6f, 0x6c, 0x69, 0x73 };
693 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
694 0x76, 0x65, 0x72, 0x73 };
695 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
696 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
697 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
698 0x73, 0x74 };
699 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
700 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
702 #define RDNA(arr) oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
703 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING, { sizeof(arr), (LPBYTE)arr }
705 static CHAR oid_us[] = "2.5.4.6",
706 oid_minnesota[] = "2.5.4.8",
707 oid_minneapolis[] = "2.5.4.7",
708 oid_codeweavers[] = "2.5.4.10",
709 oid_wine[] = "2.5.4.11",
710 oid_localhostAttr[] = "2.5.4.3",
711 oid_aric[] = "1.2.840.113549.1.9.1";
712 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
713 { RDNA(minnesota) },
714 { RDNA(minneapolis) },
715 { RDNA(codeweavers) },
716 { RDNA(wine) },
717 { RDNA(localhostAttr) },
718 { RDNIA5(aric) } };
719 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
720 { RDNA(localhostAttr) },
721 { RDNA(minnesota) },
722 { RDNA(minneapolis) },
723 { RDNA(codeweavers) },
724 { RDNA(wine) },
725 { RDNIA5(aric) } };
727 #undef RDNIA5
728 #undef RDNA
730 static const BYTE encodedRDNAttrs[] = {
731 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
732 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
733 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
734 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
735 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
736 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
737 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
738 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
739 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
740 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
743 static void test_encodeName(DWORD dwEncoding)
745 CERT_RDN_ATTR attrs[2];
746 CERT_RDN rdn;
747 CERT_NAME_INFO info;
748 static CHAR oid_common_name[] = szOID_COMMON_NAME,
749 oid_sur_name[] = szOID_SUR_NAME;
750 BYTE *buf = NULL;
751 DWORD size = 0;
752 BOOL ret;
754 if (0)
756 /* Test with NULL pvStructInfo (crashes on win9x) */
757 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
758 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
759 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
760 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
762 /* Test with empty CERT_NAME_INFO */
763 info.cRDN = 0;
764 info.rgRDN = NULL;
765 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
767 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
768 if (buf)
770 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771 "Got unexpected encoding for empty name\n");
772 LocalFree(buf);
774 if (0)
776 /* Test with bogus CERT_RDN (crashes on win9x) */
777 info.cRDN = 1;
778 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
780 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
781 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
783 /* Test with empty CERT_RDN */
784 rdn.cRDNAttr = 0;
785 rdn.rgRDNAttr = NULL;
786 info.cRDN = 1;
787 info.rgRDN = &rdn;
788 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
789 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
790 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
791 if (buf)
793 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794 "Got unexpected encoding for empty RDN array\n");
795 LocalFree(buf);
797 if (0)
799 /* Test with bogus attr array (crashes on win9x) */
800 rdn.cRDNAttr = 1;
801 rdn.rgRDNAttr = NULL;
802 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
803 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
804 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
805 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
807 /* oddly, a bogus OID is accepted by Windows XP; not testing.
808 attrs[0].pszObjId = "bogus";
809 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
810 attrs[0].Value.cbData = sizeof(commonName);
811 attrs[0].Value.pbData = commonName;
812 rdn.cRDNAttr = 1;
813 rdn.rgRDNAttr = attrs;
814 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
815 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
816 ok(!ret, "Expected failure, got success\n");
818 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
819 * the encoded attributes to be swapped.
821 attrs[0].pszObjId = oid_common_name;
822 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
823 attrs[0].Value.cbData = sizeof(commonName);
824 attrs[0].Value.pbData = (BYTE *)commonName;
825 attrs[1].pszObjId = oid_sur_name;
826 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
827 attrs[1].Value.cbData = sizeof(surName);
828 attrs[1].Value.pbData = (BYTE *)surName;
829 rdn.cRDNAttr = 2;
830 rdn.rgRDNAttr = attrs;
831 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
832 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
833 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
834 if (buf)
836 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837 "Got unexpected encoding for two RDN array\n");
838 LocalFree(buf);
840 /* A name can be "encoded" with previously encoded RDN attrs. */
841 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
842 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
843 attrs[0].Value.cbData = sizeof(twoRDNs);
844 rdn.cRDNAttr = 1;
845 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
846 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
847 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
848 if (buf)
850 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851 ok(!memcmp(buf, encodedTwoRDNs, size),
852 "Unexpected value for re-endoded two RDN array\n");
853 LocalFree(buf);
855 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
856 rdn.cRDNAttr = 1;
857 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
858 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
859 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
860 ok(!ret && GetLastError() == E_INVALIDARG,
861 "Expected E_INVALIDARG, got %08x\n", GetLastError());
862 /* Test a more complex name */
863 rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
864 rdn.rgRDNAttr = rdnAttrs;
865 info.cRDN = 1;
866 info.rgRDN = &rdn;
867 buf = NULL;
868 size = 0;
869 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
870 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
871 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
872 if (ret)
874 ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
875 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
876 LocalFree(buf);
880 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
881 static WCHAR surNameW[] = { 'L','a','n','g',0 };
883 static const BYTE twoRDNsNoNull[] = {
884 0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
885 0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
886 0x20,0x4c,0x61,0x6e,0x67 };
887 static const BYTE anyType[] = {
888 0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
889 0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
890 0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
891 0x61,0x4c,0x67,0x6e };
893 static void test_encodeUnicodeName(DWORD dwEncoding)
895 CERT_RDN_ATTR attrs[2];
896 CERT_RDN rdn;
897 CERT_NAME_INFO info;
898 static CHAR oid_common_name[] = szOID_COMMON_NAME,
899 oid_sur_name[] = szOID_SUR_NAME;
900 BYTE *buf = NULL;
901 DWORD size = 0;
902 BOOL ret;
904 if (0)
906 /* Test with NULL pvStructInfo (crashes on win9x) */
907 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
908 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
909 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
910 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
912 /* Test with empty CERT_NAME_INFO */
913 info.cRDN = 0;
914 info.rgRDN = NULL;
915 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
916 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
917 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
918 if (buf)
920 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921 "Got unexpected encoding for empty name\n");
922 LocalFree(buf);
924 /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925 * encoding (the NULL).
927 attrs[0].pszObjId = oid_common_name;
928 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
929 attrs[0].Value.cbData = sizeof(commonNameW);
930 attrs[0].Value.pbData = (BYTE *)commonNameW;
931 rdn.cRDNAttr = 1;
932 rdn.rgRDNAttr = attrs;
933 info.cRDN = 1;
934 info.rgRDN = &rdn;
935 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
937 ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
938 "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
939 ok(size == 9, "Unexpected error index %08x\n", size);
940 /* Check with two NULL-terminated CERT_RDN_ATTRs. Note DER encoding
941 * forces the order of the encoded attributes to be swapped.
943 attrs[0].pszObjId = oid_common_name;
944 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
945 attrs[0].Value.cbData = 0;
946 attrs[0].Value.pbData = (BYTE *)commonNameW;
947 attrs[1].pszObjId = oid_sur_name;
948 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
949 attrs[1].Value.cbData = 0;
950 attrs[1].Value.pbData = (BYTE *)surNameW;
951 rdn.cRDNAttr = 2;
952 rdn.rgRDNAttr = attrs;
953 info.cRDN = 1;
954 info.rgRDN = &rdn;
955 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
956 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
957 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
958 if (buf)
960 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961 "Got unexpected encoding for two RDN array\n");
962 LocalFree(buf);
964 /* A name can be "encoded" with previously encoded RDN attrs. */
965 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
966 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
967 attrs[0].Value.cbData = sizeof(twoRDNs);
968 rdn.cRDNAttr = 1;
969 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
970 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
971 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
972 if (buf)
974 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975 ok(!memcmp(buf, encodedTwoRDNs, size),
976 "Unexpected value for re-endoded two RDN array\n");
977 LocalFree(buf);
979 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980 rdn.cRDNAttr = 1;
981 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
984 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985 if (buf)
987 ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988 ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989 LocalFree(buf);
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994 const CERT_NAME_VALUE *got)
996 if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
997 got->dwValueType == CERT_RDN_ENCODED_BLOB)
999 win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
1000 return;
1003 ok(got->dwValueType == expected->dwValueType,
1004 "Expected string type %d, got %d\n", expected->dwValueType,
1005 got->dwValueType);
1006 ok(got->Value.cbData == expected->Value.cbData,
1007 "String type %d: unexpected data size, got %d, expected %d\n",
1008 expected->dwValueType, got->Value.cbData, expected->Value.cbData);
1009 if (got->Value.cbData && got->Value.pbData)
1010 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1011 min(got->Value.cbData, expected->Value.cbData)),
1012 "String type %d: unexpected value\n", expected->dwValueType);
1015 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1016 const CERT_RDN_ATTR *got)
1018 if (expected->pszObjId && strlen(expected->pszObjId))
1020 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1021 expected->pszObjId);
1022 if (got->pszObjId)
1024 ok(!strcmp(got->pszObjId, expected->pszObjId),
1025 "Got unexpected OID %s, expected %s\n", got->pszObjId,
1026 expected->pszObjId);
1029 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1030 (const CERT_NAME_VALUE *)&got->dwValueType);
1033 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1035 ok(got->cRDNAttr == expected->cRDNAttr,
1036 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1037 if (got->cRDNAttr)
1039 DWORD i;
1041 for (i = 0; i < got->cRDNAttr; i++)
1042 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1046 static void compareNames(const CERT_NAME_INFO *expected,
1047 const CERT_NAME_INFO *got)
1049 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1050 expected->cRDN, got->cRDN);
1051 if (got->cRDN)
1053 DWORD i;
1055 for (i = 0; i < got->cRDN; i++)
1056 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1060 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 };
1061 static const BYTE twoRDNsExtraBytes[] = {
1062 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
1063 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1064 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0};
1066 static void test_decodeName(DWORD dwEncoding)
1068 BYTE *buf = NULL;
1069 DWORD bufSize = 0;
1070 BOOL ret;
1071 CERT_RDN rdn;
1072 CERT_NAME_INFO info = { 1, &rdn };
1074 /* test empty name */
1075 bufSize = 0;
1076 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
1077 emptySequence[1] + 2,
1078 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1079 &buf, &bufSize);
1080 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1081 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
1082 * decoder works the same way, so only test the count.
1084 if (buf)
1086 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1087 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1088 "Expected 0 RDNs in empty info, got %d\n",
1089 ((CERT_NAME_INFO *)buf)->cRDN);
1090 LocalFree(buf);
1092 /* test empty name with indefinite-length encoding */
1093 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence,
1094 sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
1095 &buf, &bufSize);
1096 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1097 if (ret)
1099 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize);
1100 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1101 "Expected 0 RDNs in empty info, got %d\n",
1102 ((CERT_NAME_INFO *)buf)->cRDN);
1103 LocalFree(buf);
1105 /* test empty RDN */
1106 bufSize = 0;
1107 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
1108 emptyRDNs[1] + 2,
1109 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1110 &buf, &bufSize);
1111 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1112 if (buf)
1114 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1116 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1117 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1118 "Got unexpected value for empty RDN\n");
1119 LocalFree(buf);
1121 /* test two RDN attrs */
1122 bufSize = 0;
1123 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
1124 twoRDNs[1] + 2,
1125 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1126 &buf, &bufSize);
1127 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1128 if (buf)
1130 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1131 oid_common_name[] = szOID_COMMON_NAME;
1133 CERT_RDN_ATTR attrs[] = {
1134 { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
1135 (BYTE *)surName } },
1136 { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
1137 (BYTE *)commonName } },
1140 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1141 rdn.rgRDNAttr = attrs;
1142 compareNames(&info, (CERT_NAME_INFO *)buf);
1143 LocalFree(buf);
1145 /* test that two RDN attrs with extra bytes succeeds */
1146 bufSize = 0;
1147 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes,
1148 sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize);
1149 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1150 /* And, a slightly more complicated name */
1151 buf = NULL;
1152 bufSize = 0;
1153 ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
1154 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1155 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1156 if (ret)
1158 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1159 rdn.rgRDNAttr = decodedRdnAttrs;
1160 compareNames(&info, (CERT_NAME_INFO *)buf);
1161 LocalFree(buf);
1165 static void test_decodeUnicodeName(DWORD dwEncoding)
1167 BYTE *buf = NULL;
1168 DWORD bufSize = 0;
1169 BOOL ret;
1170 CERT_RDN rdn;
1171 CERT_NAME_INFO info = { 1, &rdn };
1173 /* test empty name */
1174 bufSize = 0;
1175 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence,
1176 emptySequence[1] + 2,
1177 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1178 &buf, &bufSize);
1179 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1180 if (buf)
1182 ok(bufSize == sizeof(CERT_NAME_INFO),
1183 "Got wrong bufSize %d\n", bufSize);
1184 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
1185 "Expected 0 RDNs in empty info, got %d\n",
1186 ((CERT_NAME_INFO *)buf)->cRDN);
1187 LocalFree(buf);
1189 /* test empty RDN */
1190 bufSize = 0;
1191 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs,
1192 emptyRDNs[1] + 2,
1193 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1194 &buf, &bufSize);
1195 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1196 if (buf)
1198 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1200 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
1201 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
1202 "Got unexpected value for empty RDN\n");
1203 LocalFree(buf);
1205 /* test two RDN attrs */
1206 bufSize = 0;
1207 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull,
1208 sizeof(twoRDNsNoNull),
1209 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1210 &buf, &bufSize);
1211 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1212 if (buf)
1214 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1215 oid_common_name[] = szOID_COMMON_NAME;
1217 CERT_RDN_ATTR attrs[] = {
1218 { oid_sur_name, CERT_RDN_PRINTABLE_STRING,
1219 { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } },
1220 { oid_common_name, CERT_RDN_PRINTABLE_STRING,
1221 { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } },
1224 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1225 rdn.rgRDNAttr = attrs;
1226 compareNames(&info, (CERT_NAME_INFO *)buf);
1227 LocalFree(buf);
1231 struct EncodedNameValue
1233 CERT_NAME_VALUE value;
1234 const BYTE *encoded;
1235 DWORD encodedSize;
1238 static const char bogusIA5[] = "\x80";
1239 static const char bogusPrintable[] = "~";
1240 static const char bogusNumeric[] = "A";
1241 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 };
1242 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 };
1243 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 };
1244 static BYTE octetCommonNameValue[] = {
1245 0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1246 static BYTE numericCommonNameValue[] = {
1247 0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1248 static BYTE printableCommonNameValue[] = {
1249 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1250 static BYTE t61CommonNameValue[] = {
1251 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1252 static BYTE videotexCommonNameValue[] = {
1253 0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1254 static BYTE ia5CommonNameValue[] = {
1255 0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1256 static BYTE graphicCommonNameValue[] = {
1257 0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1258 static BYTE visibleCommonNameValue[] = {
1259 0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1260 static BYTE generalCommonNameValue[] = {
1261 0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1262 static BYTE bmpCommonNameValue[] = {
1263 0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00,
1264 0x61,0x00,0x6e,0x00,0x67,0x00,0x00 };
1265 static BYTE utf8CommonNameValue[] = {
1266 0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1268 static struct EncodedNameValue nameValues[] = {
1269 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1270 octetCommonNameValue, sizeof(octetCommonNameValue) },
1271 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1272 numericCommonNameValue, sizeof(numericCommonNameValue) },
1273 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1274 printableCommonNameValue, sizeof(printableCommonNameValue) },
1275 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1276 t61CommonNameValue, sizeof(t61CommonNameValue) },
1277 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1278 videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1279 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1280 ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1281 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1282 graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1283 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1284 visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1285 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1286 generalCommonNameValue, sizeof(generalCommonNameValue) },
1287 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1288 bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1289 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1290 utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1291 /* The following tests succeed under Windows, but really should fail,
1292 * they contain characters that are illegal for the encoding. I'm
1293 * including them to justify my lazy encoding.
1295 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1296 sizeof(bin42) },
1297 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1298 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1299 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1300 bin44, sizeof(bin44) },
1303 static void test_encodeNameValue(DWORD dwEncoding)
1305 BYTE *buf = NULL;
1306 DWORD size = 0, i;
1307 BOOL ret;
1308 CERT_NAME_VALUE value = { 0, { 0, NULL } };
1310 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1311 value.Value.pbData = printableCommonNameValue;
1312 value.Value.cbData = sizeof(printableCommonNameValue);
1313 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1314 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1315 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1316 if (buf)
1318 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1319 size);
1320 ok(!memcmp(buf, printableCommonNameValue, size),
1321 "Unexpected encoding\n");
1322 LocalFree(buf);
1324 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1326 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1327 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1328 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1329 "Type %d: CryptEncodeObjectEx failed: %08x\n",
1330 nameValues[i].value.dwValueType, GetLastError());
1331 if (ret)
1333 ok(size == nameValues[i].encodedSize,
1334 "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1335 ok(!memcmp(buf, nameValues[i].encoded, size),
1336 "Got unexpected encoding\n");
1337 LocalFree(buf);
1342 static void test_decodeNameValue(DWORD dwEncoding)
1344 int i;
1345 BYTE *buf = NULL;
1346 DWORD bufSize = 0;
1347 BOOL ret;
1349 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1351 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1352 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1353 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1354 &buf, &bufSize);
1355 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1356 nameValues[i].value.dwValueType, GetLastError());
1357 if (ret)
1359 compareNameValues(&nameValues[i].value,
1360 (const CERT_NAME_VALUE *)buf);
1361 LocalFree(buf);
1366 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1367 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1368 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1369 'h','q','.','o','r','g',0 };
1370 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1371 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1372 0x6f, 0x72, 0x67 };
1373 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1374 0x575b, 0 };
1375 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1376 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1377 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1378 static const BYTE localhost[] = { 127, 0, 0, 1 };
1379 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1380 0x01 };
1381 static const unsigned char encodedCommonName[] = {
1382 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1383 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1384 static const BYTE encodedDirectoryName[] = {
1385 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1386 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1388 static void test_encodeAltName(DWORD dwEncoding)
1390 CERT_ALT_NAME_INFO info = { 0 };
1391 CERT_ALT_NAME_ENTRY entry = { 0 };
1392 BYTE *buf = NULL;
1393 DWORD size = 0;
1394 BOOL ret;
1395 char oid[] = "1.2.3";
1397 /* Test with empty info */
1398 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1399 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1400 if (buf)
1402 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1403 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1404 LocalFree(buf);
1406 /* Test with an empty entry */
1407 info.cAltEntry = 1;
1408 info.rgAltEntry = &entry;
1409 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1410 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1411 ok(!ret && GetLastError() == E_INVALIDARG,
1412 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1413 /* Test with an empty pointer */
1414 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1415 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1416 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1417 if (buf)
1419 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1420 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1421 LocalFree(buf);
1423 /* Test with a real URL */
1424 U(entry).pwszURL = (LPWSTR)url;
1425 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1426 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1427 if (buf)
1429 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1430 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1431 LocalFree(buf);
1433 /* Now with the URL containing an invalid IA5 char */
1434 U(entry).pwszURL = (LPWSTR)nihongoURL;
1435 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1436 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1437 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1438 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1439 /* The first invalid character is at index 7 */
1440 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1441 "Expected invalid char at index 7, got %d\n",
1442 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1443 /* Now with the URL missing a scheme */
1444 U(entry).pwszURL = (LPWSTR)dnsName;
1445 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1446 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1447 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1448 if (buf)
1450 /* This succeeds, but it shouldn't, so don't worry about conforming */
1451 LocalFree(buf);
1453 /* Now with a DNS name */
1454 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1455 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1456 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1457 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1458 if (buf)
1460 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1461 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1462 LocalFree(buf);
1464 /* Test with an IP address */
1465 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1466 U(entry).IPAddress.cbData = sizeof(localhost);
1467 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1468 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1469 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1470 if (buf)
1472 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1473 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1474 LocalFree(buf);
1476 /* Test with OID */
1477 entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1478 U(entry).pszRegisteredID = oid;
1479 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1480 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1481 if (buf)
1483 ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1484 ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1485 LocalFree(buf);
1487 /* Test with directory name */
1488 entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1489 U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1490 U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1491 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1492 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1493 if (buf)
1495 ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1496 ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1497 LocalFree(buf);
1501 static void test_decodeAltName(DWORD dwEncoding)
1503 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1504 0x00, 0x00, 0x01 };
1505 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1506 0x01 };
1507 BOOL ret;
1508 BYTE *buf = NULL;
1509 DWORD bufSize = 0;
1510 CERT_ALT_NAME_INFO *info;
1512 /* Test some bogus ones first */
1513 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1514 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1515 NULL, &buf, &bufSize);
1516 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1517 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1518 "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1519 GetLastError());
1520 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1521 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1522 &bufSize);
1523 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1524 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1525 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1526 GetLastError());
1527 /* Now expected cases */
1528 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1529 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1530 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1531 if (buf)
1533 info = (CERT_ALT_NAME_INFO *)buf;
1535 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1536 info->cAltEntry);
1537 LocalFree(buf);
1539 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1540 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1541 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1542 if (buf)
1544 info = (CERT_ALT_NAME_INFO *)buf;
1546 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1547 info->cAltEntry);
1548 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1549 "Expected CERT_ALT_NAME_URL, got %d\n",
1550 info->rgAltEntry[0].dwAltNameChoice);
1551 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1552 "Expected empty URL\n");
1553 LocalFree(buf);
1555 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1556 emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1557 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1558 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1559 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1560 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1561 if (buf)
1563 info = (CERT_ALT_NAME_INFO *)buf;
1565 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1566 info->cAltEntry);
1567 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1568 "Expected CERT_ALT_NAME_URL, got %d\n",
1569 info->rgAltEntry[0].dwAltNameChoice);
1570 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1571 LocalFree(buf);
1573 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1574 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1575 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1576 if (buf)
1578 info = (CERT_ALT_NAME_INFO *)buf;
1580 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1581 info->cAltEntry);
1582 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1583 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1584 info->rgAltEntry[0].dwAltNameChoice);
1585 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1586 "Unexpected DNS name\n");
1587 LocalFree(buf);
1589 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1590 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1591 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1592 if (buf)
1594 info = (CERT_ALT_NAME_INFO *)buf;
1596 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1597 info->cAltEntry);
1598 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1599 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1600 info->rgAltEntry[0].dwAltNameChoice);
1601 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1602 "Unexpected IP address length %d\n",
1603 U(info->rgAltEntry[0]).IPAddress.cbData);
1604 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1605 sizeof(localhost)), "Unexpected IP address value\n");
1606 LocalFree(buf);
1608 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1609 sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1610 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1611 if (buf)
1613 info = (CERT_ALT_NAME_INFO *)buf;
1615 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1616 info->cAltEntry);
1617 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1618 "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1619 info->rgAltEntry[0].dwAltNameChoice);
1620 ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1621 "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1622 LocalFree(buf);
1624 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1625 encodedDirectoryName, sizeof(encodedDirectoryName),
1626 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1627 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1628 if (buf)
1630 info = (CERT_ALT_NAME_INFO *)buf;
1632 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1633 info->cAltEntry);
1634 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1635 "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1636 info->rgAltEntry[0].dwAltNameChoice);
1637 ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1638 sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1639 U(info->rgAltEntry[0]).DirectoryName.cbData);
1640 ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1641 encodedCommonName, sizeof(encodedCommonName)),
1642 "Unexpected directory name value\n");
1643 LocalFree(buf);
1647 struct UnicodeExpectedError
1649 DWORD valueType;
1650 LPCWSTR str;
1651 DWORD errorIndex;
1652 DWORD error;
1655 static const WCHAR oneW[] = { '1',0 };
1656 static const WCHAR aW[] = { 'a',0 };
1657 static const WCHAR quoteW[] = { '"', 0 };
1659 static struct UnicodeExpectedError unicodeErrors[] = {
1660 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1661 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1662 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1663 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1664 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1665 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1668 struct UnicodeExpectedResult
1670 DWORD valueType;
1671 LPCWSTR str;
1672 CRYPT_DATA_BLOB encoded;
1675 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1676 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1677 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1678 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1679 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1680 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1681 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1682 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1683 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1684 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1685 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1686 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1687 0x5b };
1688 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1689 0x6f,0x5b };
1690 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1691 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1692 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1693 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1695 static struct UnicodeExpectedResult unicodeResults[] = {
1696 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1697 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1698 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1699 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1700 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1701 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1702 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1703 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1704 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1705 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1706 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1707 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1708 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1711 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1712 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1713 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1716 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1718 BYTE *buf = NULL;
1719 DWORD size = 0, i;
1720 BOOL ret;
1721 CERT_NAME_VALUE value;
1723 if (0)
1725 /* Crashes on win9x */
1726 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1727 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1728 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1729 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1731 /* Have to have a string of some sort */
1732 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1733 value.Value.pbData = NULL;
1734 value.Value.cbData = 0;
1735 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1736 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1737 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1738 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1739 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1740 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1741 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1742 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1743 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1744 value.dwValueType = CERT_RDN_ANY_TYPE;
1745 value.Value.pbData = (LPBYTE)oneW;
1746 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1747 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1748 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1749 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1750 value.Value.cbData = sizeof(oneW);
1751 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1752 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1753 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1754 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1755 /* An encoded string with specified length isn't good enough either */
1756 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1757 value.Value.pbData = oneUniversal;
1758 value.Value.cbData = sizeof(oneUniversal);
1759 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1760 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1761 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1762 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1763 /* More failure checking */
1764 value.Value.cbData = 0;
1765 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1767 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1768 value.dwValueType = unicodeErrors[i].valueType;
1769 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1770 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1771 ok(!ret && GetLastError() == unicodeErrors[i].error,
1772 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1773 unicodeErrors[i].error, GetLastError());
1774 ok(size == unicodeErrors[i].errorIndex,
1775 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1776 size);
1778 /* cbData can be zero if the string is NULL-terminated */
1779 value.Value.cbData = 0;
1780 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1782 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1783 value.dwValueType = unicodeResults[i].valueType;
1784 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1785 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1786 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1787 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1788 if (buf)
1790 ok(size == unicodeResults[i].encoded.cbData,
1791 "Value type %d: expected size %d, got %d\n",
1792 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1793 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1794 "Value type %d: unexpected value\n", value.dwValueType);
1795 LocalFree(buf);
1798 /* These "encode," but they do so by truncating each unicode character
1799 * rather than properly encoding it. Kept separate from the proper results,
1800 * because the encoded forms won't decode to their original strings.
1802 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1804 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1805 value.dwValueType = unicodeWeirdness[i].valueType;
1806 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1807 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1808 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1809 if (buf)
1811 ok(size == unicodeWeirdness[i].encoded.cbData,
1812 "Value type %d: expected size %d, got %d\n",
1813 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1814 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1815 "Value type %d: unexpected value\n", value.dwValueType);
1816 LocalFree(buf);
1821 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1823 if (n <= 0) return 0;
1824 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1825 return *str1 - *str2;
1828 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1830 DWORD i;
1832 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1834 BYTE *buf = NULL;
1835 BOOL ret;
1836 DWORD size = 0;
1838 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1839 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1840 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1841 ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1842 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1843 if (ret && buf)
1845 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1847 ok(value->dwValueType == unicodeResults[i].valueType,
1848 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1849 value->dwValueType);
1850 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1851 value->Value.cbData / sizeof(WCHAR)),
1852 "Unexpected decoded value for index %d (value type %d)\n", i,
1853 unicodeResults[i].valueType);
1854 LocalFree(buf);
1859 struct encodedOctets
1861 const BYTE *val;
1862 const BYTE *encoded;
1865 static const unsigned char bin46[] = { 'h','i',0 };
1866 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1867 static const unsigned char bin48[] = {
1868 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1869 static const unsigned char bin49[] = {
1870 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1871 static const unsigned char bin50[] = { 0 };
1872 static const unsigned char bin51[] = { 0x04,0x00,0 };
1874 static const struct encodedOctets octets[] = {
1875 { bin46, bin47 },
1876 { bin48, bin49 },
1877 { bin50, bin51 },
1880 static void test_encodeOctets(DWORD dwEncoding)
1882 CRYPT_DATA_BLOB blob;
1883 DWORD i;
1885 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1887 BYTE *buf = NULL;
1888 BOOL ret;
1889 DWORD bufSize = 0;
1891 blob.cbData = strlen((const char*)octets[i].val);
1892 blob.pbData = (BYTE*)octets[i].val;
1893 ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1894 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1895 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1896 if (buf)
1898 ok(buf[0] == 4,
1899 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1900 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1901 buf[1], octets[i].encoded[1]);
1902 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1903 octets[i].encoded[1] + 1), "Got unexpected value\n");
1904 LocalFree(buf);
1909 static void test_decodeOctets(DWORD dwEncoding)
1911 DWORD i;
1913 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1915 BYTE *buf = NULL;
1916 BOOL ret;
1917 DWORD bufSize = 0;
1919 ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1920 octets[i].encoded, octets[i].encoded[1] + 2,
1921 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1922 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1923 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1924 "Expected size >= %d, got %d\n",
1925 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1926 ok(buf != NULL, "Expected allocated buffer\n");
1927 if (buf)
1929 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1931 if (blob->cbData)
1932 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1933 "Unexpected value\n");
1934 LocalFree(buf);
1939 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1941 struct encodedBits
1943 DWORD cUnusedBits;
1944 const BYTE *encoded;
1945 DWORD cbDecoded;
1946 const BYTE *decoded;
1949 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1950 static const unsigned char bin53[] = { 0xff,0xff };
1951 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1952 static const unsigned char bin55[] = { 0xff,0xfe };
1953 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1954 static const unsigned char bin57[] = { 0xfe };
1955 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1957 static const struct encodedBits bits[] = {
1958 /* normal test cases */
1959 { 0, bin52, 2, bin53 },
1960 { 1, bin54, 2, bin55 },
1961 /* strange test case, showing cUnusedBits >= 8 is allowed */
1962 { 9, bin56, 1, bin57 },
1965 static void test_encodeBits(DWORD dwEncoding)
1967 DWORD i;
1969 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1971 CRYPT_BIT_BLOB blob;
1972 BOOL ret;
1973 BYTE *buf = NULL;
1974 DWORD bufSize = 0;
1976 blob.cbData = sizeof(bytesToEncode);
1977 blob.pbData = (BYTE *)bytesToEncode;
1978 blob.cUnusedBits = bits[i].cUnusedBits;
1979 ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1980 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1981 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1982 if (buf)
1984 ok(bufSize == bits[i].encoded[1] + 2,
1985 "%d: Got unexpected size %d, expected %d\n", i, bufSize,
1986 bits[i].encoded[1] + 2);
1987 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1988 "%d: Unexpected value\n", i);
1989 LocalFree(buf);
1994 static void test_decodeBits(DWORD dwEncoding)
1996 static const BYTE ber[] = "\x03\x02\x01\xff";
1997 static const BYTE berDecoded = 0xfe;
1998 DWORD i;
1999 BOOL ret;
2000 BYTE *buf = NULL;
2001 DWORD bufSize = 0;
2003 /* normal cases */
2004 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2006 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2007 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2008 &bufSize);
2009 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2010 if (buf)
2012 CRYPT_BIT_BLOB *blob;
2014 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2015 "Got unexpected size %d\n", bufSize);
2016 blob = (CRYPT_BIT_BLOB *)buf;
2017 ok(blob->cbData == bits[i].cbDecoded,
2018 "Got unexpected length %d, expected %d\n", blob->cbData,
2019 bits[i].cbDecoded);
2020 if (blob->cbData && bits[i].cbDecoded)
2021 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2022 "Unexpected value\n");
2023 LocalFree(buf);
2026 /* special case: check that something that's valid in BER but not in DER
2027 * decodes successfully
2029 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2030 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2031 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2032 if (buf)
2034 CRYPT_BIT_BLOB *blob;
2036 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2037 "Got unexpected size %d\n", bufSize);
2038 blob = (CRYPT_BIT_BLOB *)buf;
2039 ok(blob->cbData == sizeof(berDecoded),
2040 "Got unexpected length %d\n", blob->cbData);
2041 if (blob->cbData)
2042 ok(*blob->pbData == berDecoded, "Unexpected value\n");
2043 LocalFree(buf);
2047 struct Constraints2
2049 CERT_BASIC_CONSTRAINTS2_INFO info;
2050 const BYTE *encoded;
2053 static const unsigned char bin59[] = { 0x30,0x00 };
2054 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2055 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2056 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2057 static const struct Constraints2 constraints2[] = {
2058 /* empty constraints */
2059 { { FALSE, FALSE, 0}, bin59 },
2060 /* can be a CA */
2061 { { TRUE, FALSE, 0}, bin60 },
2062 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2063 * but that's not the case
2065 { { FALSE, TRUE, 0}, bin61 },
2066 /* can be a CA and has path length constraints set */
2067 { { TRUE, TRUE, 1}, bin62 },
2070 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2071 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2072 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2073 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2074 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2075 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2076 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2077 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2078 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2079 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2081 static void test_encodeBasicConstraints(DWORD dwEncoding)
2083 DWORD i, bufSize = 0;
2084 CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2085 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2086 (LPBYTE)encodedDomainName };
2087 BOOL ret;
2088 BYTE *buf = NULL;
2090 /* First test with the simpler info2 */
2091 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2093 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2094 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2095 &bufSize);
2096 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2097 if (buf)
2099 ok(bufSize == constraints2[i].encoded[1] + 2,
2100 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2101 bufSize);
2102 ok(!memcmp(buf, constraints2[i].encoded,
2103 constraints2[i].encoded[1] + 2), "Unexpected value\n");
2104 LocalFree(buf);
2107 /* Now test with more complex basic constraints */
2108 info.SubjectType.cbData = 0;
2109 info.fPathLenConstraint = FALSE;
2110 info.cSubtreesConstraint = 0;
2111 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2112 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2113 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2114 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2115 if (buf)
2117 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2118 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2119 "Unexpected value\n");
2120 LocalFree(buf);
2122 /* None of the certs I examined had any subtree constraint, but I test one
2123 * anyway just in case.
2125 info.cSubtreesConstraint = 1;
2126 info.rgSubtreesConstraint = &nameBlob;
2127 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2128 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2129 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2130 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2131 if (buf)
2133 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2134 ok(!memcmp(buf, constraintWithDomainName,
2135 sizeof(constraintWithDomainName)), "Unexpected value\n");
2136 LocalFree(buf);
2138 /* FIXME: test encoding with subject type. */
2141 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2143 static void test_decodeBasicConstraints(DWORD dwEncoding)
2145 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2146 0xff };
2147 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2148 DWORD i;
2149 BOOL ret;
2150 BYTE *buf = NULL;
2151 DWORD bufSize = 0;
2153 /* First test with simpler info2 */
2154 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2156 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2157 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2158 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2159 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2160 GetLastError());
2161 if (buf)
2163 CERT_BASIC_CONSTRAINTS2_INFO *info =
2164 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2166 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2167 "Unexpected value for item %d\n", i);
2168 LocalFree(buf);
2171 /* Check with the order of encoded elements inverted */
2172 buf = (PBYTE)1;
2173 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2174 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2175 &bufSize);
2176 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2177 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2178 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2179 GetLastError());
2180 ok(!buf, "Expected buf to be set to NULL\n");
2181 /* Check with a non-DER bool */
2182 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2183 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2184 &buf, &bufSize);
2185 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2186 if (buf)
2188 CERT_BASIC_CONSTRAINTS2_INFO *info =
2189 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2191 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2192 LocalFree(buf);
2194 /* Check with a non-basic constraints value */
2195 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2196 encodedCommonName, encodedCommonName[1] + 2,
2197 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2198 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2199 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2200 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2201 GetLastError());
2202 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2203 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2204 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2205 &buf, &bufSize);
2206 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2207 if (buf)
2209 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2211 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2212 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2213 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2214 LocalFree(buf);
2216 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2217 constraintWithDomainName, sizeof(constraintWithDomainName),
2218 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2219 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2220 if (buf)
2222 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2224 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2225 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2226 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2227 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2229 ok(info->rgSubtreesConstraint[0].cbData ==
2230 sizeof(encodedDomainName), "Wrong size %d\n",
2231 info->rgSubtreesConstraint[0].cbData);
2232 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2233 sizeof(encodedDomainName)), "Unexpected value\n");
2235 LocalFree(buf);
2239 /* These are terrible public keys of course, I'm just testing encoding */
2240 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2241 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2242 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2243 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2244 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2245 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2246 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2247 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2249 struct EncodedRSAPubKey
2251 const BYTE *modulus;
2252 size_t modulusLen;
2253 const BYTE *encoded;
2254 size_t decodedModulusLen;
2257 struct EncodedRSAPubKey rsaPubKeys[] = {
2258 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2259 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2260 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2261 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2264 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2266 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2267 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2268 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2269 BOOL ret;
2270 BYTE *buf = NULL;
2271 DWORD bufSize = 0, i;
2273 /* Try with a bogus blob type */
2274 hdr->bType = 2;
2275 hdr->bVersion = CUR_BLOB_VERSION;
2276 hdr->reserved = 0;
2277 hdr->aiKeyAlg = CALG_RSA_KEYX;
2278 rsaPubKey->magic = 0x31415352;
2279 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2280 rsaPubKey->pubexp = 65537;
2281 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2282 sizeof(modulus1));
2284 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2285 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2286 ok(!ret && GetLastError() == E_INVALIDARG,
2287 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2288 /* Now with a bogus reserved field */
2289 hdr->bType = PUBLICKEYBLOB;
2290 hdr->reserved = 1;
2291 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2292 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2293 if (buf)
2295 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2296 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2297 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2298 LocalFree(buf);
2300 /* Now with a bogus blob version */
2301 hdr->reserved = 0;
2302 hdr->bVersion = 0;
2303 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2304 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2305 if (buf)
2307 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2308 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2309 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2310 LocalFree(buf);
2312 /* And with a bogus alg ID */
2313 hdr->bVersion = CUR_BLOB_VERSION;
2314 hdr->aiKeyAlg = CALG_DES;
2315 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2316 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2317 if (buf)
2319 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2320 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2321 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2322 LocalFree(buf);
2324 /* Check a couple of RSA-related OIDs */
2325 hdr->aiKeyAlg = CALG_RSA_KEYX;
2326 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2327 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2328 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2329 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2330 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2331 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2332 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2333 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2334 /* Finally, all valid */
2335 hdr->aiKeyAlg = CALG_RSA_KEYX;
2336 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2338 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2339 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2340 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2341 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2342 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2343 if (buf)
2345 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2346 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2347 bufSize);
2348 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2349 "Unexpected value\n");
2350 LocalFree(buf);
2355 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2357 DWORD i;
2358 LPBYTE buf = NULL;
2359 DWORD bufSize = 0;
2360 BOOL ret;
2362 /* Try with a bad length */
2363 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2364 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2365 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2366 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2367 GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2368 "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2369 GetLastError());
2370 /* Try with a couple of RSA-related OIDs */
2371 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2372 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2373 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2374 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2375 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2376 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2377 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2378 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2379 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2380 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2381 /* Now try success cases */
2382 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2384 bufSize = 0;
2385 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2386 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2387 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2388 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2389 if (buf)
2391 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2392 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2394 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2395 rsaPubKeys[i].decodedModulusLen,
2396 "Wrong size %d\n", bufSize);
2397 ok(hdr->bType == PUBLICKEYBLOB,
2398 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2399 hdr->bType);
2400 ok(hdr->bVersion == CUR_BLOB_VERSION,
2401 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2402 CUR_BLOB_VERSION, hdr->bVersion);
2403 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2404 hdr->reserved);
2405 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2406 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2407 ok(rsaPubKey->magic == 0x31415352,
2408 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2409 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2410 "Wrong bit len %d\n", rsaPubKey->bitlen);
2411 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2412 rsaPubKey->pubexp);
2413 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2414 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2415 "Unexpected modulus\n");
2416 LocalFree(buf);
2421 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2422 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2423 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2425 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2426 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2427 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2428 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2430 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2432 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2433 CRYPT_SEQUENCE_OF_ANY seq;
2434 DWORD i;
2435 BOOL ret;
2436 BYTE *buf = NULL;
2437 DWORD bufSize = 0;
2439 /* Encode a homogeneous sequence */
2440 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2442 blobs[i].cbData = ints[i].encoded[1] + 2;
2443 blobs[i].pbData = (BYTE *)ints[i].encoded;
2445 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2446 seq.rgValue = blobs;
2448 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2449 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2450 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2451 if (buf)
2453 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2454 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2455 LocalFree(buf);
2457 /* Change the type of the first element in the sequence, and give it
2458 * another go
2460 blobs[0].cbData = times[0].encodedTime[1] + 2;
2461 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2462 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2463 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2464 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2465 if (buf)
2467 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2468 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2469 "Unexpected value\n");
2470 LocalFree(buf);
2474 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2476 BOOL ret;
2477 BYTE *buf = NULL;
2478 DWORD bufSize = 0;
2480 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2481 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2482 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2483 if (buf)
2485 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2486 DWORD i;
2488 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2489 "Wrong elements %d\n", seq->cValue);
2490 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2492 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2493 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2494 seq->rgValue[i].cbData);
2495 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2496 ints[i].encoded[1] + 2), "Unexpected value\n");
2498 LocalFree(buf);
2500 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2501 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2502 &bufSize);
2503 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2504 if (buf)
2506 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2508 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2509 "Wrong elements %d\n", seq->cValue);
2510 /* Just check the first element since it's all that changed */
2511 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2512 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2513 seq->rgValue[0].cbData);
2514 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2515 times[0].encodedTime[1] + 2), "Unexpected value\n");
2516 LocalFree(buf);
2520 struct encodedExtensions
2522 CERT_EXTENSIONS exts;
2523 const BYTE *encoded;
2526 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2527 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2528 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2529 static CERT_EXTENSION criticalExt =
2530 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2531 static CERT_EXTENSION nonCriticalExt =
2532 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2533 static CHAR oid_short[] = "1.1";
2534 static CERT_EXTENSION extWithShortOid =
2535 { oid_short, FALSE, { 0, NULL } };
2537 static const BYTE ext0[] = { 0x30,0x00 };
2538 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2539 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2540 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2541 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2542 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2544 static const struct encodedExtensions exts[] = {
2545 { { 0, NULL }, ext0 },
2546 { { 1, &criticalExt }, ext1 },
2547 { { 1, &nonCriticalExt }, ext2 },
2548 { { 1, &extWithShortOid }, ext3 }
2551 static void test_encodeExtensions(DWORD dwEncoding)
2553 DWORD i;
2555 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2557 BOOL ret;
2558 BYTE *buf = NULL;
2559 DWORD bufSize = 0;
2561 ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2562 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2563 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2564 if (buf)
2566 ok(bufSize == exts[i].encoded[1] + 2,
2567 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2568 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2569 "Unexpected value\n");
2570 LocalFree(buf);
2575 static void test_decodeExtensions(DWORD dwEncoding)
2577 DWORD i;
2579 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2581 BOOL ret;
2582 BYTE *buf = NULL;
2583 DWORD bufSize = 0;
2585 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2586 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2587 NULL, &buf, &bufSize);
2588 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2589 if (buf)
2591 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2592 DWORD j;
2594 ok(ext->cExtension == exts[i].exts.cExtension,
2595 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2596 ext->cExtension);
2597 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2599 ok(!strcmp(ext->rgExtension[j].pszObjId,
2600 exts[i].exts.rgExtension[j].pszObjId),
2601 "Expected OID %s, got %s\n",
2602 exts[i].exts.rgExtension[j].pszObjId,
2603 ext->rgExtension[j].pszObjId);
2604 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2605 exts[i].exts.rgExtension[j].Value.pbData,
2606 exts[i].exts.rgExtension[j].Value.cbData),
2607 "Unexpected value\n");
2609 LocalFree(buf);
2614 /* MS encodes public key info with a NULL if the algorithm identifier's
2615 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2616 * it encodes them by omitting the algorithm parameters. It accepts either
2617 * form for decoding.
2619 struct encodedPublicKey
2621 CERT_PUBLIC_KEY_INFO info;
2622 const BYTE *encoded;
2623 const BYTE *encodedNoNull;
2624 CERT_PUBLIC_KEY_INFO decoded;
2627 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2628 0xe, 0xf };
2629 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2631 static const unsigned char bin64[] = {
2632 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2633 static const unsigned char bin65[] = {
2634 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2635 static const unsigned char bin66[] = {
2636 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2637 static const unsigned char bin67[] = {
2638 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2639 static const unsigned char bin68[] = {
2640 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2641 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2642 static const unsigned char bin69[] = {
2643 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2644 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2645 static const unsigned char bin70[] = {
2646 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2647 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2648 0x0f};
2649 static const unsigned char bin71[] = {
2650 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2651 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2652 0x0f};
2653 static unsigned char bin72[] = { 0x05,0x00};
2655 static CHAR oid_bogus[] = "1.2.3",
2656 oid_rsa[] = szOID_RSA;
2658 static const struct encodedPublicKey pubKeys[] = {
2659 /* with a bogus OID */
2660 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2661 bin64, bin65,
2662 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2663 /* some normal keys */
2664 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2665 bin66, bin67,
2666 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2667 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2668 bin68, bin69,
2669 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2670 /* with add'l parameters--note they must be DER-encoded */
2671 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2672 (BYTE *)aKey, 0 } },
2673 bin70, bin71,
2674 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2675 (BYTE *)aKey, 0 } } },
2678 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2680 DWORD i;
2682 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2684 BOOL ret;
2685 BYTE *buf = NULL;
2686 DWORD bufSize = 0;
2688 ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2689 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2690 &bufSize);
2691 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2692 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2693 if (buf)
2695 ok(bufSize == pubKeys[i].encoded[1] + 2,
2696 "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2697 if (bufSize == pubKeys[i].encoded[1] + 2)
2698 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2699 "Unexpected value\n");
2700 LocalFree(buf);
2705 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2706 const CERT_PUBLIC_KEY_INFO *got)
2708 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2709 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2710 got->Algorithm.pszObjId);
2711 ok(expected->Algorithm.Parameters.cbData ==
2712 got->Algorithm.Parameters.cbData,
2713 "Expected parameters of %d bytes, got %d\n",
2714 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2715 if (expected->Algorithm.Parameters.cbData)
2716 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2717 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2718 "Unexpected algorithm parameters\n");
2719 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2720 "Expected public key of %d bytes, got %d\n",
2721 expected->PublicKey.cbData, got->PublicKey.cbData);
2722 if (expected->PublicKey.cbData)
2723 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2724 got->PublicKey.cbData), "Unexpected public key value\n");
2727 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2729 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2730 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2731 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2732 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2733 DWORD i;
2734 BOOL ret;
2735 BYTE *buf = NULL;
2736 DWORD bufSize = 0;
2738 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2740 /* The NULL form decodes to the decoded member */
2741 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2742 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2743 NULL, &buf, &bufSize);
2744 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2745 if (buf)
2747 comparePublicKeyInfo(&pubKeys[i].decoded,
2748 (CERT_PUBLIC_KEY_INFO *)buf);
2749 LocalFree(buf);
2751 /* The non-NULL form decodes to the original */
2752 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2753 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2754 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2755 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2756 if (buf)
2758 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2759 LocalFree(buf);
2762 /* Test with bogus (not valid DER) parameters */
2763 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2764 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2765 NULL, &buf, &bufSize);
2766 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2767 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2768 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2769 GetLastError());
2772 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2773 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2774 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2775 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2776 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2777 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2778 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2779 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2780 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2781 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2782 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2783 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2784 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2785 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2786 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2787 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2788 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2789 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2790 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2791 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2792 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2793 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2794 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2795 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2796 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2797 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2798 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2799 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2800 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2801 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2802 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2803 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2804 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2805 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2806 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2807 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2808 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2809 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2810 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2811 static const BYTE v1CertWithPubKey[] = {
2812 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2813 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2814 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2815 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2816 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2817 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2818 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2819 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2820 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2821 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2822 0x01,0x01 };
2823 static const BYTE v1CertWithPubKeyNoNull[] = {
2824 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2825 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2826 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2827 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2828 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2829 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2830 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2831 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2832 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2833 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2834 static const BYTE v1CertWithSubjectKeyId[] = {
2835 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2836 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2837 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2838 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2839 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2840 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2841 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2842 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2843 0x4c,0x61,0x6e,0x67,0x00 };
2845 static const BYTE serialNum[] = { 0x01 };
2847 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2849 BOOL ret;
2850 BYTE *buf = NULL;
2851 DWORD size = 0;
2852 CERT_INFO info = { 0 };
2853 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2854 static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2855 CERT_EXTENSION ext;
2857 if (0)
2859 /* Test with NULL pvStructInfo (crashes on win9x) */
2860 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2861 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2862 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2863 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
2865 /* Test with a V1 cert */
2866 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2867 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2868 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2869 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2870 if (buf)
2872 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
2873 v1Cert[1] + 2, size);
2874 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2875 LocalFree(buf);
2877 /* Test v2 cert */
2878 info.dwVersion = CERT_V2;
2879 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2880 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2881 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2882 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2883 if (buf)
2885 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
2886 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2887 LocalFree(buf);
2889 /* Test v3 cert */
2890 info.dwVersion = CERT_V3;
2891 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2892 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2893 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2894 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2895 if (buf)
2897 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
2898 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2899 LocalFree(buf);
2901 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2902 * API doesn't prevent it)
2904 info.dwVersion = CERT_V1;
2905 info.cExtension = 1;
2906 info.rgExtension = &criticalExt;
2907 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2908 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2909 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2910 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2911 if (buf)
2913 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
2914 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2915 LocalFree(buf);
2917 /* test v1 cert with a serial number */
2918 info.SerialNumber.cbData = sizeof(serialNum);
2919 info.SerialNumber.pbData = (BYTE *)serialNum;
2920 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2921 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2922 if (buf)
2924 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
2925 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2926 LocalFree(buf);
2928 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2929 info.Issuer.cbData = sizeof(encodedCommonName);
2930 info.Issuer.pbData = (BYTE *)encodedCommonName;
2931 info.Subject.cbData = sizeof(encodedCommonName);
2932 info.Subject.pbData = (BYTE *)encodedCommonName;
2933 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2934 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2935 if (buf)
2937 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
2938 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2939 LocalFree(buf);
2941 /* Add a public key */
2942 info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
2943 info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
2944 info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
2945 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2946 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2947 if (buf)
2949 ok(size == sizeof(v1CertWithPubKey) ||
2950 size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
2951 if (size == sizeof(v1CertWithPubKey))
2952 ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
2953 else if (size == sizeof(v1CertWithPubKeyNoNull))
2954 ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
2955 "Got unexpected value\n");
2956 LocalFree(buf);
2958 /* Remove the public key, and add a subject key identifier extension */
2959 info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
2960 info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
2961 info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
2962 ext.pszObjId = oid_subject_key_identifier;
2963 ext.fCritical = FALSE;
2964 ext.Value.cbData = sizeof(octetCommonNameValue);
2965 ext.Value.pbData = octetCommonNameValue;
2966 info.cExtension = 1;
2967 info.rgExtension = &ext;
2968 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2969 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2970 if (buf)
2972 ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
2973 ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
2974 LocalFree(buf);
2978 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2980 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2981 v1CertWithConstraints, v1CertWithSerial };
2982 BOOL ret;
2983 BYTE *buf = NULL;
2984 DWORD size = 0, i;
2986 /* Test with NULL pbEncoded */
2987 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2988 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
2989 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2990 GetLastError() == OSS_BAD_ARG /* Win9x */),
2991 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
2992 if (0)
2994 /* Crashes on win9x */
2995 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2996 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
2997 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2998 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3000 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
3001 * minimum a cert must have a non-zero serial number, an issuer, and a
3002 * subject.
3004 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3006 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3007 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3008 &buf, &size);
3009 ok(!ret, "Expected failure\n");
3011 /* Now check with serial number, subject and issuer specified */
3012 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3013 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3014 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3015 if (buf)
3017 CERT_INFO *info = (CERT_INFO *)buf;
3019 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3020 ok(info->SerialNumber.cbData == 1,
3021 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3022 ok(*info->SerialNumber.pbData == *serialNum,
3023 "Expected serial number %d, got %d\n", *serialNum,
3024 *info->SerialNumber.pbData);
3025 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3026 "Wrong size %d\n", info->Issuer.cbData);
3027 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3028 "Unexpected issuer\n");
3029 ok(info->Subject.cbData == sizeof(encodedCommonName),
3030 "Wrong size %d\n", info->Subject.cbData);
3031 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3032 info->Subject.cbData), "Unexpected subject\n");
3033 LocalFree(buf);
3035 /* Check again with pub key specified */
3036 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3037 v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3038 &buf, &size);
3039 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3040 if (buf)
3042 CERT_INFO *info = (CERT_INFO *)buf;
3044 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3045 ok(info->SerialNumber.cbData == 1,
3046 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3047 ok(*info->SerialNumber.pbData == *serialNum,
3048 "Expected serial number %d, got %d\n", *serialNum,
3049 *info->SerialNumber.pbData);
3050 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3051 "Wrong size %d\n", info->Issuer.cbData);
3052 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3053 "Unexpected issuer\n");
3054 ok(info->Subject.cbData == sizeof(encodedCommonName),
3055 "Wrong size %d\n", info->Subject.cbData);
3056 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3057 info->Subject.cbData), "Unexpected subject\n");
3058 ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3059 szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3060 info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3061 ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3062 "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3063 ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3064 sizeof(aKey)), "Unexpected public key\n");
3065 LocalFree(buf);
3069 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3070 0xe, 0xf };
3072 static const BYTE signedBigCert[] = {
3073 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3074 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3075 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3076 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3077 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3078 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3079 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3080 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3081 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3082 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3083 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3084 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3086 static void test_encodeCert(DWORD dwEncoding)
3088 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
3089 * also that bigCert is a NULL-terminated string, so don't count its
3090 * last byte (otherwise the signed cert won't decode.)
3092 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3093 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3094 BOOL ret;
3095 BYTE *buf = NULL;
3096 DWORD bufSize = 0;
3098 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3099 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3100 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3101 if (buf)
3103 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3104 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3105 LocalFree(buf);
3109 static void test_decodeCert(DWORD dwEncoding)
3111 BOOL ret;
3112 BYTE *buf = NULL;
3113 DWORD size = 0;
3115 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3116 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3117 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3118 if (buf)
3120 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3122 ok(info->ToBeSigned.cbData == sizeof(bigCert),
3123 "Wrong cert size %d\n", info->ToBeSigned.cbData);
3124 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3125 "Unexpected cert\n");
3126 ok(info->Signature.cbData == sizeof(hash),
3127 "Wrong signature size %d\n", info->Signature.cbData);
3128 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3129 "Unexpected signature\n");
3130 LocalFree(buf);
3132 /* A signed cert decodes as a CERT_INFO too */
3133 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3134 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3135 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3136 if (buf)
3138 CERT_INFO *info = (CERT_INFO *)buf;
3140 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3141 ok(info->SerialNumber.cbData == 1,
3142 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3143 ok(*info->SerialNumber.pbData == *serialNum,
3144 "Expected serial number %d, got %d\n", *serialNum,
3145 *info->SerialNumber.pbData);
3146 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3147 "Wrong size %d\n", info->Issuer.cbData);
3148 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3149 "Unexpected issuer\n");
3150 ok(info->Subject.cbData == sizeof(encodedCommonName),
3151 "Wrong size %d\n", info->Subject.cbData);
3152 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3153 info->Subject.cbData), "Unexpected subject\n");
3154 LocalFree(buf);
3158 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3159 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3160 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3161 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3162 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3163 0x00, 0x03 };
3164 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3165 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3166 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3167 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3168 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3169 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3170 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3171 0x2e, 0x6f, 0x72, 0x67 };
3172 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3173 CRL_REASON_AFFILIATION_CHANGED;
3175 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3177 CRL_DIST_POINTS_INFO info = { 0 };
3178 CRL_DIST_POINT point = { { 0 } };
3179 CERT_ALT_NAME_ENTRY entry = { 0 };
3180 BOOL ret;
3181 BYTE *buf = NULL;
3182 DWORD size = 0;
3184 /* Test with an empty info */
3185 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3186 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3187 ok(!ret && GetLastError() == E_INVALIDARG,
3188 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3189 /* Test with one empty dist point */
3190 info.cDistPoint = 1;
3191 info.rgDistPoint = &point;
3192 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3193 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3194 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3195 if (buf)
3197 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3198 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3199 LocalFree(buf);
3201 /* A dist point with an invalid name */
3202 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3203 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3204 U(entry).pwszURL = (LPWSTR)nihongoURL;
3205 U(point.DistPointName).FullName.cAltEntry = 1;
3206 U(point.DistPointName).FullName.rgAltEntry = &entry;
3207 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3208 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3209 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3210 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3211 /* The first invalid character is at index 7 */
3212 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3213 "Expected invalid char at index 7, got %d\n",
3214 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3215 /* A dist point with (just) a valid name */
3216 U(entry).pwszURL = (LPWSTR)url;
3217 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3218 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3219 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3220 if (buf)
3222 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3223 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3224 LocalFree(buf);
3226 /* A dist point with (just) reason flags */
3227 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3228 point.ReasonFlags.cbData = sizeof(crlReason);
3229 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3230 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3231 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3232 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3233 if (buf)
3235 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3236 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3237 LocalFree(buf);
3239 /* A dist point with just an issuer */
3240 point.ReasonFlags.cbData = 0;
3241 point.CRLIssuer.cAltEntry = 1;
3242 point.CRLIssuer.rgAltEntry = &entry;
3243 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3244 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3245 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3246 if (buf)
3248 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3249 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3250 LocalFree(buf);
3252 /* A dist point with both a name and an issuer */
3253 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3254 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3255 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3256 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3257 if (buf)
3259 ok(size == sizeof(distPointWithUrlAndIssuer),
3260 "Wrong size %d\n", size);
3261 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3262 LocalFree(buf);
3266 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3268 BOOL ret;
3269 BYTE *buf = NULL;
3270 DWORD size = 0;
3271 PCRL_DIST_POINTS_INFO info;
3272 PCRL_DIST_POINT point;
3273 PCERT_ALT_NAME_ENTRY entry;
3275 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3276 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3277 &buf, &size);
3278 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3279 if (ret)
3281 info = (PCRL_DIST_POINTS_INFO)buf;
3282 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3283 "Wrong size %d\n", size);
3284 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3285 info->cDistPoint);
3286 point = info->rgDistPoint;
3287 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3288 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3289 point->DistPointName.dwDistPointNameChoice);
3290 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3291 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3292 LocalFree(buf);
3294 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3295 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3296 &buf, &size);
3297 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3298 if (ret)
3300 info = (PCRL_DIST_POINTS_INFO)buf;
3301 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3302 "Wrong size %d\n", size);
3303 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3304 info->cDistPoint);
3305 point = info->rgDistPoint;
3306 ok(point->DistPointName.dwDistPointNameChoice ==
3307 CRL_DIST_POINT_FULL_NAME,
3308 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3309 point->DistPointName.dwDistPointNameChoice);
3310 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3311 "Expected 1 name entry, got %d\n",
3312 U(point->DistPointName).FullName.cAltEntry);
3313 entry = U(point->DistPointName).FullName.rgAltEntry;
3314 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3315 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3316 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3317 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3318 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3319 LocalFree(buf);
3321 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3322 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3323 NULL, &buf, &size);
3324 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3325 if (ret)
3327 info = (PCRL_DIST_POINTS_INFO)buf;
3328 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3329 "Wrong size %d\n", size);
3330 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3331 info->cDistPoint);
3332 point = info->rgDistPoint;
3333 ok(point->DistPointName.dwDistPointNameChoice ==
3334 CRL_DIST_POINT_NO_NAME,
3335 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3336 point->DistPointName.dwDistPointNameChoice);
3337 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3338 "Expected reason length\n");
3339 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3340 "Unexpected reason\n");
3341 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3342 LocalFree(buf);
3344 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3345 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3346 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3347 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3348 if (ret)
3350 info = (PCRL_DIST_POINTS_INFO)buf;
3351 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3352 "Wrong size %d\n", size);
3353 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3354 info->cDistPoint);
3355 point = info->rgDistPoint;
3356 ok(point->DistPointName.dwDistPointNameChoice ==
3357 CRL_DIST_POINT_FULL_NAME,
3358 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3359 point->DistPointName.dwDistPointNameChoice);
3360 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3361 "Expected 1 name entry, got %d\n",
3362 U(point->DistPointName).FullName.cAltEntry);
3363 entry = U(point->DistPointName).FullName.rgAltEntry;
3364 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3365 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3366 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3367 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3368 ok(point->CRLIssuer.cAltEntry == 1,
3369 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3370 entry = point->CRLIssuer.rgAltEntry;
3371 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3372 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3373 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3374 LocalFree(buf);
3378 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3379 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3380 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3381 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3382 0x67 };
3384 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3386 BOOL ret;
3387 BYTE *buf = NULL;
3388 DWORD size = 0;
3389 CRL_ISSUING_DIST_POINT point = { { 0 } };
3390 CERT_ALT_NAME_ENTRY entry;
3392 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3393 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3394 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3396 skip("no X509_ISSUING_DIST_POINT encode support\n");
3397 return;
3399 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3400 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3401 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3402 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3403 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3404 if (buf)
3406 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3407 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3408 LocalFree(buf);
3410 /* nonsensical flags */
3411 point.fOnlyContainsUserCerts = TRUE;
3412 point.fOnlyContainsCACerts = TRUE;
3413 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3414 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3415 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3416 if (buf)
3418 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3419 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3420 LocalFree(buf);
3422 /* unimplemented name type */
3423 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3424 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3425 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3426 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3427 ok(!ret && GetLastError() == E_INVALIDARG,
3428 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3429 /* empty name */
3430 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3431 U(point.DistPointName).FullName.cAltEntry = 0;
3432 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3433 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3434 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3435 if (buf)
3437 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3438 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3439 LocalFree(buf);
3441 /* name with URL entry */
3442 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3443 U(entry).pwszURL = (LPWSTR)url;
3444 U(point.DistPointName).FullName.cAltEntry = 1;
3445 U(point.DistPointName).FullName.rgAltEntry = &entry;
3446 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3447 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3448 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3449 if (buf)
3451 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3452 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3453 LocalFree(buf);
3457 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3458 const CERT_ALT_NAME_ENTRY *got)
3460 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3461 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3462 got->dwAltNameChoice);
3463 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3465 switch (got->dwAltNameChoice)
3467 case CERT_ALT_NAME_RFC822_NAME:
3468 case CERT_ALT_NAME_DNS_NAME:
3469 case CERT_ALT_NAME_EDI_PARTY_NAME:
3470 case CERT_ALT_NAME_URL:
3471 case CERT_ALT_NAME_REGISTERED_ID:
3472 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3473 (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3474 (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3475 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3476 "Unexpected name\n");
3477 break;
3478 case CERT_ALT_NAME_X400_ADDRESS:
3479 case CERT_ALT_NAME_DIRECTORY_NAME:
3480 case CERT_ALT_NAME_IP_ADDRESS:
3481 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3482 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3483 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3484 U(*got).IPAddress.cbData), "Unexpected value\n");
3485 break;
3490 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3491 const CERT_ALT_NAME_INFO *got)
3493 DWORD i;
3495 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3496 expected->cAltEntry, got->cAltEntry);
3497 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3498 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3501 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3502 const CRL_DIST_POINT_NAME *got)
3504 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3505 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3506 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3507 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3510 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3511 const CRL_ISSUING_DIST_POINT *got)
3513 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3514 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3515 "Unexpected fOnlyContainsUserCerts\n");
3516 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3517 "Unexpected fOnlyContainsCACerts\n");
3518 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3519 "Unexpected reason flags\n");
3520 ok(got->fIndirectCRL == expected->fIndirectCRL,
3521 "Unexpected fIndirectCRL\n");
3524 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3526 BOOL ret;
3527 BYTE *buf = NULL;
3528 DWORD size = 0;
3529 CRL_ISSUING_DIST_POINT point = { { 0 } };
3531 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3532 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3533 &buf, &size);
3534 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3536 skip("no X509_ISSUING_DIST_POINT decode support\n");
3537 return;
3539 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3540 if (ret)
3542 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3543 LocalFree(buf);
3545 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3546 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3547 &buf, &size);
3548 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3549 if (ret)
3551 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3552 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3553 LocalFree(buf);
3555 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3556 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3557 &buf, &size);
3558 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3559 if (ret)
3561 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3562 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3563 U(point.DistPointName).FullName.cAltEntry = 0;
3564 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3565 LocalFree(buf);
3567 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3568 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3569 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3570 if (ret)
3572 CERT_ALT_NAME_ENTRY entry;
3574 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3575 U(entry).pwszURL = (LPWSTR)url;
3576 U(point.DistPointName).FullName.cAltEntry = 1;
3577 U(point.DistPointName).FullName.rgAltEntry = &entry;
3578 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3579 LocalFree(buf);
3583 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3584 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3585 0x30, 0x5a };
3586 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3587 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3588 0x30, 0x30, 0x30, 0x30, 0x5a };
3589 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3590 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3591 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3592 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3593 0x5a };
3594 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3595 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3596 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3597 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3598 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3599 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3600 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3601 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3602 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3603 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3604 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3605 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3606 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3607 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3608 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3609 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3610 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3611 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3612 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3613 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3614 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3615 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3616 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3617 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3618 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3619 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3620 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3621 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3622 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3623 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3624 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3625 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3626 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3627 static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01,
3628 0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
3629 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,
3630 0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,
3631 0x16,0x30,0x14,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3632 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,
3633 0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3635 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3637 BOOL ret;
3638 BYTE *buf = NULL;
3639 static CHAR oid_issuing_dist_point[] = szOID_ISSUING_DIST_POINT;
3640 DWORD size = 0;
3641 CRL_INFO info = { 0 };
3642 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3643 CERT_EXTENSION ext;
3645 /* Test with a V1 CRL */
3646 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3647 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3648 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3649 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3650 if (buf)
3652 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3653 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3654 LocalFree(buf);
3656 /* Test v2 CRL */
3657 info.dwVersion = CRL_V2;
3658 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3659 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3660 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3661 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3662 if (buf)
3664 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3665 v2CRL[1] + 2, size);
3666 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3667 LocalFree(buf);
3669 /* v1 CRL with a name */
3670 info.dwVersion = CRL_V1;
3671 info.Issuer.cbData = sizeof(encodedCommonName);
3672 info.Issuer.pbData = (BYTE *)encodedCommonName;
3673 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3674 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3675 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3676 if (buf)
3678 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3679 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3680 LocalFree(buf);
3682 if (0)
3684 /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3685 info.cCRLEntry = 1;
3686 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3687 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3688 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3689 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3691 /* now set an empty entry */
3692 info.cCRLEntry = 1;
3693 info.rgCRLEntry = &entry;
3694 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3695 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3696 if (buf)
3698 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3699 "Wrong size %d\n", size);
3700 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3701 "Got unexpected value\n");
3702 LocalFree(buf);
3704 /* an entry with a serial number */
3705 entry.SerialNumber.cbData = sizeof(serialNum);
3706 entry.SerialNumber.pbData = (BYTE *)serialNum;
3707 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3708 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3709 if (buf)
3711 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3712 "Wrong size %d\n", size);
3713 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3714 "Got unexpected value\n");
3715 LocalFree(buf);
3717 /* an entry with an extension */
3718 entry.cExtension = 1;
3719 entry.rgExtension = &criticalExt;
3720 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3721 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3722 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3723 if (buf)
3725 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3726 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3727 LocalFree(buf);
3729 /* a CRL with an extension */
3730 entry.cExtension = 0;
3731 info.cExtension = 1;
3732 info.rgExtension = &criticalExt;
3733 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3734 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3735 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3736 if (buf)
3738 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3739 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3740 LocalFree(buf);
3742 /* a v2 CRL with an extension, this time non-critical */
3743 info.dwVersion = CRL_V2;
3744 info.rgExtension = &nonCriticalExt;
3745 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3746 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3747 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3748 if (buf)
3750 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3751 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3752 LocalFree(buf);
3754 /* a v2 CRL with an issuing dist point extension */
3755 ext.pszObjId = oid_issuing_dist_point;
3756 ext.fCritical = TRUE;
3757 ext.Value.cbData = sizeof(urlIDP);
3758 ext.Value.pbData = (LPBYTE)urlIDP;
3759 entry.rgExtension = &ext;
3760 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3761 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3762 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3763 if (buf)
3765 ok(size == sizeof(v2CRLWithIssuingDistPoint), "Wrong size %d\n", size);
3766 ok(!memcmp(buf, v2CRLWithIssuingDistPoint, size), "Unexpected value\n");
3767 LocalFree(buf);
3771 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3772 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3773 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3774 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3775 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3776 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3777 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3778 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3779 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3780 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3781 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3782 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3783 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3784 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3785 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3786 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3787 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3788 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3789 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3790 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3791 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3792 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3793 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3794 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3795 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
3796 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
3797 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
3798 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
3799 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
3800 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
3801 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
3802 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
3803 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
3804 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
3805 0xcd };
3806 static const BYTE verisignCRLWithLotsOfEntries[] = {
3807 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
3808 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
3809 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
3810 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
3811 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
3812 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
3813 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
3814 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
3815 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
3816 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
3817 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
3818 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
3819 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
3820 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
3821 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
3822 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
3823 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3824 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
3825 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
3826 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3827 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
3828 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
3829 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
3830 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
3831 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
3832 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
3833 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
3834 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
3835 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
3836 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
3837 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
3838 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
3839 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
3840 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3841 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
3842 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
3843 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
3844 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
3845 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
3846 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
3847 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
3848 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
3849 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
3850 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
3851 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
3852 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
3853 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
3854 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
3855 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
3856 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
3857 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
3858 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
3859 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
3860 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
3861 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3862 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
3863 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
3864 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
3865 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
3866 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
3867 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
3868 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
3869 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
3870 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
3871 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
3872 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
3873 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
3874 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
3875 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
3876 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
3877 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
3878 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
3879 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
3880 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
3881 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
3882 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
3883 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
3884 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
3885 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
3886 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
3887 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
3888 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
3889 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
3890 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
3891 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
3892 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
3893 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
3894 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
3895 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
3896 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
3897 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
3898 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
3899 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
3900 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
3901 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
3902 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
3903 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
3904 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
3905 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
3906 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
3907 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
3908 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
3909 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
3910 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
3911 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
3912 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
3913 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
3914 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
3915 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
3916 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
3917 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
3918 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
3919 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
3920 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
3921 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
3922 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
3923 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
3924 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
3925 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
3926 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
3927 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
3928 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
3929 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
3930 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
3931 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
3932 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
3933 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
3934 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
3935 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
3936 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
3937 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
3938 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
3939 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
3940 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
3941 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
3942 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
3943 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
3944 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
3945 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
3946 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
3947 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
3948 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
3949 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
3950 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
3951 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
3952 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
3953 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
3954 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
3955 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
3956 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
3957 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
3958 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
3959 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
3960 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
3961 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
3962 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
3963 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
3964 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
3965 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
3966 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
3967 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
3968 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
3969 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
3970 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
3971 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
3972 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
3973 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
3974 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
3975 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
3976 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
3977 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
3978 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
3979 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
3980 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
3981 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
3982 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
3983 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
3984 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
3985 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
3986 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
3987 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
3988 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
3989 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
3990 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
3991 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
3992 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
3993 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
3994 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
3995 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
3996 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
3997 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
3998 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
3999 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4000 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4001 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4002 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4003 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4004 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4005 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4006 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4007 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4008 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4009 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4010 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4011 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4012 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4013 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4014 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4015 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4016 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4017 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4018 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4019 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4020 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4021 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4022 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4023 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4024 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4025 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4026 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4027 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4028 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4029 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4030 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4031 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4032 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4033 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4034 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4035 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4036 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4037 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4038 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4039 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4040 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4041 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4042 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4043 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4044 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4045 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4046 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4047 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4048 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4049 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4050 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4051 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4052 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4053 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4054 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4055 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4056 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4057 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4058 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4059 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4060 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4061 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4062 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4063 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4064 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4065 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4066 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4067 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4068 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4069 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4070 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4071 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4072 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4073 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4074 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4075 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4076 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4077 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4078 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4079 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4080 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4081 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4082 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4083 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4084 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4085 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4086 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4087 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4088 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4089 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4090 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4091 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4092 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4093 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4094 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4095 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4096 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4097 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4098 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4099 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4100 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4101 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4102 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4103 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4104 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4105 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4106 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4107 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4108 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4109 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4110 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4111 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4112 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4113 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4114 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4115 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4116 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4117 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4118 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4119 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4120 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4121 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4122 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4123 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4124 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4125 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4126 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4127 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4128 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4129 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4130 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4131 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4132 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4133 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4134 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4135 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4136 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4137 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4138 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4139 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4140 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4141 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4142 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4143 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4144 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4145 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4146 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4147 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4148 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4149 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4150 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4151 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4152 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4153 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4154 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4155 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4156 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4157 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4158 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4159 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4160 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4161 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4162 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4163 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4164 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4165 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4166 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4167 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4168 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4169 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4170 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4171 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4172 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4173 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4174 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4175 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4176 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4177 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4178 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4179 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4180 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4181 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4182 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4183 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4184 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4185 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4186 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4187 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4188 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4189 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4190 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4191 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4192 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4193 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4194 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4195 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4196 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4197 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4198 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4199 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4200 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4201 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4202 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4203 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4204 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4205 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4206 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4207 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4208 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4209 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4210 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4211 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4212 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4213 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4214 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4215 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4216 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4217 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4218 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4219 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4220 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4221 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4222 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4223 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4224 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4225 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4226 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4227 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4228 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4229 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4230 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4231 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4232 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4233 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4234 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4235 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4236 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4237 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4238 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4239 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4240 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4241 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4242 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4243 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4244 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4245 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4246 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4247 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4248 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4249 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4250 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4251 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4252 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4253 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4254 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4255 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4256 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4257 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4258 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4259 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4260 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4261 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4262 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4263 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4264 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4265 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4266 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4267 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4268 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4269 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4270 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4271 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4272 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4273 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4274 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4275 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4276 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4277 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4278 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4279 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4280 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4281 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4282 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4283 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4284 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4285 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4286 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4287 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4288 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4289 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4290 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4291 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4292 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4293 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4294 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4295 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4296 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4297 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4298 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4299 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4300 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4301 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4302 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4303 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4304 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4305 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4306 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4307 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4308 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4309 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4310 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4311 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4312 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4313 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4314 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4316 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4318 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4319 BOOL ret;
4320 BYTE *buf = NULL;
4321 DWORD size = 0, i;
4323 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4325 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4326 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4327 &buf, &size);
4328 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4329 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4330 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4331 GetLastError());
4333 /* at a minimum, a CRL must contain an issuer: */
4334 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4335 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4336 &buf, &size);
4337 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4338 if (buf)
4340 CRL_INFO *info = (CRL_INFO *)buf;
4342 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4343 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4344 info->cCRLEntry);
4345 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4346 "Wrong issuer size %d\n", info->Issuer.cbData);
4347 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4348 "Unexpected issuer\n");
4349 LocalFree(buf);
4351 /* check decoding with an empty CRL entry */
4352 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4353 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4354 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4355 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4356 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4357 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4358 GetLastError());
4359 /* with a real CRL entry */
4360 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4361 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4362 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4363 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4364 if (buf)
4366 CRL_INFO *info = (CRL_INFO *)buf;
4367 CRL_ENTRY *entry;
4369 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4370 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4371 info->cCRLEntry);
4372 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4373 entry = info->rgCRLEntry;
4374 ok(entry->SerialNumber.cbData == 1,
4375 "Expected serial number size 1, got %d\n",
4376 entry->SerialNumber.cbData);
4377 ok(*entry->SerialNumber.pbData == *serialNum,
4378 "Expected serial number %d, got %d\n", *serialNum,
4379 *entry->SerialNumber.pbData);
4380 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4381 "Wrong issuer size %d\n", info->Issuer.cbData);
4382 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4383 "Unexpected issuer\n");
4384 LocalFree(buf);
4386 /* a real CRL from verisign that has extensions */
4387 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4388 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4389 NULL, &buf, &size);
4390 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4391 if (buf)
4393 CRL_INFO *info = (CRL_INFO *)buf;
4394 CRL_ENTRY *entry;
4396 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4397 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4398 info->cCRLEntry);
4399 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4400 entry = info->rgCRLEntry;
4401 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4402 info->cExtension);
4403 LocalFree(buf);
4405 /* another real CRL from verisign that has lots of entries */
4406 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4407 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4408 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4409 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4410 if (buf)
4412 CRL_INFO *info = (CRL_INFO *)buf;
4414 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4415 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4416 info->cCRLEntry);
4417 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4418 info->cExtension);
4419 LocalFree(buf);
4421 /* and finally, with an extension */
4422 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4423 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4424 NULL, &buf, &size);
4425 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4426 if (buf)
4428 CRL_INFO *info = (CRL_INFO *)buf;
4429 CRL_ENTRY *entry;
4431 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4432 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4433 info->cCRLEntry);
4434 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4435 entry = info->rgCRLEntry;
4436 ok(entry->SerialNumber.cbData == 1,
4437 "Expected serial number size 1, got %d\n",
4438 entry->SerialNumber.cbData);
4439 ok(*entry->SerialNumber.pbData == *serialNum,
4440 "Expected serial number %d, got %d\n", *serialNum,
4441 *entry->SerialNumber.pbData);
4442 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4443 "Wrong issuer size %d\n", info->Issuer.cbData);
4444 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4445 "Unexpected issuer\n");
4446 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4447 info->cExtension);
4448 LocalFree(buf);
4450 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4451 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4452 NULL, &buf, &size);
4453 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4454 if (buf)
4456 CRL_INFO *info = (CRL_INFO *)buf;
4458 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4459 info->cExtension);
4460 LocalFree(buf);
4462 /* And again, with an issuing dist point */
4463 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4464 v2CRLWithIssuingDistPoint, sizeof(v2CRLWithIssuingDistPoint),
4465 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4466 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4467 if (buf)
4469 CRL_INFO *info = (CRL_INFO *)buf;
4471 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4472 info->cExtension);
4473 LocalFree(buf);
4477 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4478 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4479 static const BYTE encodedUsage[] = {
4480 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4481 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4482 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4484 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4486 BOOL ret;
4487 BYTE *buf = NULL;
4488 DWORD size = 0;
4489 CERT_ENHKEY_USAGE usage;
4491 /* Test with empty usage */
4492 usage.cUsageIdentifier = 0;
4493 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4494 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4495 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4496 if (buf)
4498 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4499 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4500 LocalFree(buf);
4502 /* Test with a few usages */
4503 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4504 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4505 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4506 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4507 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4508 if (buf)
4510 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4511 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4512 LocalFree(buf);
4516 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4518 BOOL ret;
4519 LPBYTE buf = NULL;
4520 DWORD size = 0;
4522 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4523 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4524 &buf, &size);
4525 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4526 if (buf)
4528 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4530 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4531 "Wrong size %d\n", size);
4532 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4533 usage->cUsageIdentifier);
4534 LocalFree(buf);
4536 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4537 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4538 &buf, &size);
4539 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4540 if (buf)
4542 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4543 DWORD i;
4545 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4546 "Wrong size %d\n", size);
4547 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4548 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4549 for (i = 0; i < usage->cUsageIdentifier; i++)
4550 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4551 "Expected OID %s, got %s\n", keyUsages[i],
4552 usage->rgpszUsageIdentifier[i]);
4553 LocalFree(buf);
4557 static BYTE keyId[] = { 1,2,3,4 };
4558 static const BYTE authorityKeyIdWithId[] = {
4559 0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4560 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4561 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4562 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4563 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4565 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4567 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4568 BOOL ret;
4569 BYTE *buf = NULL;
4570 DWORD size = 0;
4572 /* Test with empty id */
4573 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4574 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4575 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4576 if (buf)
4578 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4579 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4580 LocalFree(buf);
4582 /* With just a key id */
4583 info.KeyId.cbData = sizeof(keyId);
4584 info.KeyId.pbData = keyId;
4585 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4586 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4587 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4588 if (buf)
4590 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4591 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4592 LocalFree(buf);
4594 /* With just an issuer */
4595 info.KeyId.cbData = 0;
4596 info.CertIssuer.cbData = sizeof(encodedCommonName);
4597 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4598 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4599 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4600 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4601 if (buf)
4603 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4604 size);
4605 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4606 LocalFree(buf);
4608 /* With just a serial number */
4609 info.CertIssuer.cbData = 0;
4610 info.CertSerialNumber.cbData = sizeof(serialNum);
4611 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4612 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4613 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4614 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4615 if (buf)
4617 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4618 size);
4619 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4620 LocalFree(buf);
4624 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4626 BOOL ret;
4627 LPBYTE buf = NULL;
4628 DWORD size = 0;
4630 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4631 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4632 &buf, &size);
4633 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4634 if (buf)
4636 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4638 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4639 size);
4640 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4641 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4642 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4643 LocalFree(buf);
4645 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4646 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4647 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4648 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4649 if (buf)
4651 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4653 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4654 size);
4655 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4656 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4657 "Unexpected key id\n");
4658 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4659 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4660 LocalFree(buf);
4662 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4663 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4664 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4665 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4666 if (buf)
4668 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4670 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4671 size);
4672 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4673 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4674 "Unexpected issuer len\n");
4675 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4676 sizeof(encodedCommonName)), "Unexpected issuer\n");
4677 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4678 LocalFree(buf);
4680 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4681 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4682 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4683 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4684 if (buf)
4686 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4688 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4689 size);
4690 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4691 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4692 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4693 "Unexpected serial number len\n");
4694 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4695 "Unexpected serial number\n");
4696 LocalFree(buf);
4700 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4701 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4702 0x6f,0x72,0x67 };
4704 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4706 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4707 CERT_ALT_NAME_ENTRY entry = { 0 };
4708 BOOL ret;
4709 BYTE *buf = NULL;
4710 DWORD size = 0;
4712 /* Test with empty id */
4713 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4714 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4715 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4716 if (buf)
4718 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4719 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4720 LocalFree(buf);
4722 /* With just a key id */
4723 info.KeyId.cbData = sizeof(keyId);
4724 info.KeyId.pbData = keyId;
4725 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4726 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4727 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4728 if (buf)
4730 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4731 size);
4732 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4733 LocalFree(buf);
4735 /* With a bogus issuer name */
4736 info.KeyId.cbData = 0;
4737 info.AuthorityCertIssuer.cAltEntry = 1;
4738 info.AuthorityCertIssuer.rgAltEntry = &entry;
4739 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4740 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4741 ok(!ret && GetLastError() == E_INVALIDARG,
4742 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4743 /* With an issuer name */
4744 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4745 U(entry).pwszURL = (LPWSTR)url;
4746 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4747 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4748 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4749 if (buf)
4751 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4752 size);
4753 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4754 "Unexpected value\n");
4755 LocalFree(buf);
4757 /* With just a serial number */
4758 info.AuthorityCertIssuer.cAltEntry = 0;
4759 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4760 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4761 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4762 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4763 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4764 if (buf)
4766 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4767 size);
4768 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4769 LocalFree(buf);
4773 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4775 BOOL ret;
4776 LPBYTE buf = NULL;
4777 DWORD size = 0;
4779 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4780 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4781 &buf, &size);
4782 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4783 if (buf)
4785 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4787 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4788 size);
4789 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4790 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4791 "Expected no issuer name entries\n");
4792 ok(info->AuthorityCertSerialNumber.cbData == 0,
4793 "Expected no serial number\n");
4794 LocalFree(buf);
4796 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4797 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4798 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4799 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4800 if (buf)
4802 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4804 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4805 size);
4806 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4807 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4808 "Unexpected key id\n");
4809 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4810 "Expected no issuer name entries\n");
4811 ok(info->AuthorityCertSerialNumber.cbData == 0,
4812 "Expected no serial number\n");
4813 LocalFree(buf);
4815 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4816 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
4817 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4818 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4819 if (buf)
4821 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4823 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4824 size);
4825 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4826 ok(info->AuthorityCertIssuer.cAltEntry == 1,
4827 "Expected 1 issuer entry, got %d\n",
4828 info->AuthorityCertIssuer.cAltEntry);
4829 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
4830 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
4831 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
4832 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
4833 url), "Unexpected URL\n");
4834 ok(info->AuthorityCertSerialNumber.cbData == 0,
4835 "Expected no serial number\n");
4836 LocalFree(buf);
4838 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4839 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4840 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4841 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4842 if (buf)
4844 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4846 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4847 size);
4848 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4849 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4850 "Expected no issuer name entries\n");
4851 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
4852 "Unexpected serial number len\n");
4853 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
4854 sizeof(serialNum)), "Unexpected serial number\n");
4855 LocalFree(buf);
4859 static const BYTE authorityInfoAccessWithUrl[] = {
4860 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4861 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
4862 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
4863 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
4864 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
4865 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
4867 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
4869 static char oid1[] = "1.2.3";
4870 static char oid2[] = "1.5.6";
4871 BOOL ret;
4872 BYTE *buf = NULL;
4873 DWORD size = 0;
4874 CERT_ACCESS_DESCRIPTION accessDescription[2];
4875 CERT_AUTHORITY_INFO_ACCESS aia;
4877 memset(accessDescription, 0, sizeof(accessDescription));
4878 aia.cAccDescr = 0;
4879 aia.rgAccDescr = NULL;
4880 /* Having no access descriptions is allowed */
4881 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4882 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4883 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4884 if (buf)
4886 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
4887 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
4888 LocalFree(buf);
4889 buf = NULL;
4891 /* It can't have an empty access method */
4892 aia.cAccDescr = 1;
4893 aia.rgAccDescr = accessDescription;
4894 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4895 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4896 ok(!ret && (GetLastError() == E_INVALIDARG ||
4897 GetLastError() == OSS_LIMITED /* Win9x */),
4898 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
4899 /* It can't have an empty location */
4900 accessDescription[0].pszAccessMethod = oid1;
4901 SetLastError(0xdeadbeef);
4902 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4903 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4904 ok(!ret && GetLastError() == E_INVALIDARG,
4905 "expected E_INVALIDARG, got %08x\n", GetLastError());
4906 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4907 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
4908 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4909 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4910 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4911 if (buf)
4913 ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
4914 size);
4915 ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
4916 "unexpected value\n");
4917 LocalFree(buf);
4918 buf = NULL;
4920 accessDescription[1].pszAccessMethod = oid2;
4921 accessDescription[1].AccessLocation.dwAltNameChoice =
4922 CERT_ALT_NAME_IP_ADDRESS;
4923 U(accessDescription[1].AccessLocation).IPAddress.cbData =
4924 sizeof(encodedIPAddr);
4925 U(accessDescription[1].AccessLocation).IPAddress.pbData =
4926 (LPBYTE)encodedIPAddr;
4927 aia.cAccDescr = 2;
4928 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
4929 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4930 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4931 if (buf)
4933 ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
4934 "unexpected size %d\n", size);
4935 ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
4936 "unexpected value\n");
4937 LocalFree(buf);
4938 buf = NULL;
4942 static void compareAuthorityInfoAccess(LPCSTR header,
4943 const CERT_AUTHORITY_INFO_ACCESS *expected,
4944 const CERT_AUTHORITY_INFO_ACCESS *got)
4946 DWORD i;
4948 ok(expected->cAccDescr == got->cAccDescr,
4949 "%s: expected %d access descriptions, got %d\n", header,
4950 expected->cAccDescr, got->cAccDescr);
4951 for (i = 0; i < expected->cAccDescr; i++)
4953 ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
4954 got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
4955 header, i, expected->rgAccDescr[i].pszAccessMethod,
4956 got->rgAccDescr[i].pszAccessMethod);
4957 compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
4958 &got->rgAccDescr[i].AccessLocation);
4962 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
4964 static char oid1[] = "1.2.3";
4965 static char oid2[] = "1.5.6";
4966 BOOL ret;
4967 LPBYTE buf = NULL;
4968 DWORD size = 0;
4970 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4971 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4972 &buf, &size);
4973 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4974 if (buf)
4976 CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
4978 compareAuthorityInfoAccess("empty AIA", &aia,
4979 (CERT_AUTHORITY_INFO_ACCESS *)buf);
4980 LocalFree(buf);
4981 buf = NULL;
4983 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
4984 authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
4985 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4986 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
4987 if (buf)
4989 CERT_ACCESS_DESCRIPTION accessDescription;
4990 CERT_AUTHORITY_INFO_ACCESS aia;
4992 accessDescription.pszAccessMethod = oid1;
4993 accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
4994 U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
4995 aia.cAccDescr = 1;
4996 aia.rgAccDescr = &accessDescription;
4997 compareAuthorityInfoAccess("AIA with URL", &aia,
4998 (CERT_AUTHORITY_INFO_ACCESS *)buf);
4999 LocalFree(buf);
5000 buf = NULL;
5002 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5003 authorityInfoAccessWithUrlAndIPAddr,
5004 sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5005 NULL, &buf, &size);
5006 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5007 if (buf)
5009 CERT_ACCESS_DESCRIPTION accessDescription[2];
5010 CERT_AUTHORITY_INFO_ACCESS aia;
5012 accessDescription[0].pszAccessMethod = oid1;
5013 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5014 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5015 accessDescription[1].pszAccessMethod = oid2;
5016 accessDescription[1].AccessLocation.dwAltNameChoice =
5017 CERT_ALT_NAME_IP_ADDRESS;
5018 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5019 sizeof(encodedIPAddr);
5020 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5021 (LPBYTE)encodedIPAddr;
5022 aia.cAccDescr = 2;
5023 aia.rgAccDescr = accessDescription;
5024 compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5025 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5026 LocalFree(buf);
5027 buf = NULL;
5031 static const BYTE emptyCTL[] = {
5032 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5033 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5034 static const BYTE emptyCTLWithVersion1[] = {
5035 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5036 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5037 static const BYTE ctlWithUsageIdentifier[] = {
5038 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5039 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5040 static const BYTE ctlWithListIdentifier[] = {
5041 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5042 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5043 static const BYTE ctlWithSequenceNumber[] = {
5044 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5045 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5046 static const BYTE ctlWithThisUpdate[] = {
5047 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5048 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5049 static const BYTE ctlWithThisAndNextUpdate[] = {
5050 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5051 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5052 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5053 static const BYTE ctlWithAlgId[] = {
5054 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5055 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5056 static const BYTE ctlWithBogusEntry[] = {
5057 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5058 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5059 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5060 static const BYTE ctlWithOneEntry[] = {
5061 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5062 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5063 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5064 static const BYTE ctlWithTwoEntries[] = {
5065 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5066 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5067 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5068 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5069 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5071 static void test_encodeCTL(DWORD dwEncoding)
5073 static char oid1[] = "1.2.3";
5074 static char oid2[] = "1.5.6";
5075 char *pOid1 = oid1;
5076 BOOL ret;
5077 BYTE *buf = NULL;
5078 DWORD size = 0;
5079 CTL_INFO info;
5080 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5081 CTL_ENTRY ctlEntry[2];
5082 CRYPT_ATTRIBUTE attr1, attr2;
5083 CRYPT_ATTR_BLOB value1, value2;
5085 memset(&info, 0, sizeof(info));
5086 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5087 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5088 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5089 if (buf)
5091 ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5092 ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5093 LocalFree(buf);
5094 buf = NULL;
5096 info.dwVersion = 1;
5097 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5098 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5099 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5100 if (buf)
5102 ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5103 ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5104 LocalFree(buf);
5105 buf = NULL;
5107 info.dwVersion = 0;
5108 info.SubjectUsage.cUsageIdentifier = 1;
5109 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5110 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5111 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5112 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5113 if (buf)
5115 ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5116 size);
5117 ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5118 LocalFree(buf);
5119 buf = NULL;
5121 info.SubjectUsage.cUsageIdentifier = 0;
5122 info.ListIdentifier.cbData = sizeof(serialNum);
5123 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5124 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5125 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5126 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5127 if (buf)
5129 ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5130 ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5131 LocalFree(buf);
5132 buf = NULL;
5134 info.ListIdentifier.cbData = 0;
5135 info.SequenceNumber.cbData = sizeof(serialNum);
5136 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5137 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5138 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5139 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5140 if (buf)
5142 ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5143 size);
5144 ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5145 LocalFree(buf);
5146 buf = NULL;
5148 info.SequenceNumber.cbData = 0;
5149 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5150 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5151 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5152 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5153 if (buf)
5155 ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5156 ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5157 LocalFree(buf);
5158 buf = NULL;
5160 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5161 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5162 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5163 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5164 if (buf)
5166 ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5167 size);
5168 ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5169 LocalFree(buf);
5170 buf = NULL;
5172 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5173 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5174 info.SubjectAlgorithm.pszObjId = oid2;
5175 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5176 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5177 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5178 if (buf)
5180 ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5181 ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5182 LocalFree(buf);
5183 buf = NULL;
5185 /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5186 * (see tests below) but it'll encode fine.
5188 info.SubjectAlgorithm.pszObjId = NULL;
5189 value1.cbData = sizeof(serialNum);
5190 value1.pbData = (LPBYTE)serialNum;
5191 attr1.pszObjId = oid1;
5192 attr1.cValue = 1;
5193 attr1.rgValue = &value1;
5194 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5195 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5196 ctlEntry[0].cAttribute = 1;
5197 ctlEntry[0].rgAttribute = &attr1;
5198 info.cCTLEntry = 1;
5199 info.rgCTLEntry = ctlEntry;
5200 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5201 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5202 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5203 if (buf)
5205 ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5206 ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5207 LocalFree(buf);
5208 buf = NULL;
5210 value1.cbData = sizeof(emptySequence);
5211 value1.pbData = (LPBYTE)emptySequence;
5212 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5213 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5214 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5215 if (buf)
5217 ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5218 ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5219 LocalFree(buf);
5220 buf = NULL;
5222 value2.cbData = sizeof(encodedIPAddr);
5223 value2.pbData = (LPBYTE)encodedIPAddr;
5224 attr2.pszObjId = oid2;
5225 attr2.cValue = 1;
5226 attr2.rgValue = &value2;
5227 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5228 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5229 ctlEntry[1].cAttribute = 1;
5230 ctlEntry[1].rgAttribute = &attr2;
5231 info.cCTLEntry = 2;
5232 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5233 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5234 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5235 if (buf)
5237 ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5238 ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5239 LocalFree(buf);
5240 buf = NULL;
5244 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5245 const CTL_INFO *got)
5247 DWORD i, j, k;
5249 ok(expected->dwVersion == got->dwVersion,
5250 "%s: expected version %d, got %d\n", header, expected->dwVersion,
5251 got->dwVersion);
5252 ok(expected->SubjectUsage.cUsageIdentifier ==
5253 got->SubjectUsage.cUsageIdentifier,
5254 "%s: expected %d usage identifiers, got %d\n", header,
5255 expected->SubjectUsage.cUsageIdentifier,
5256 got->SubjectUsage.cUsageIdentifier);
5257 for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5258 ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5259 got->SubjectUsage.rgpszUsageIdentifier[i]),
5260 "%s[%d]: expected %s, got %s\n", header, i,
5261 expected->SubjectUsage.rgpszUsageIdentifier[i],
5262 got->SubjectUsage.rgpszUsageIdentifier[i]);
5263 ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5264 "%s: expected list identifier of %d bytes, got %d\n", header,
5265 expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5266 if (expected->ListIdentifier.cbData)
5267 ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5268 expected->ListIdentifier.cbData),
5269 "%s: unexpected list identifier value\n", header);
5270 ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5271 "%s: expected sequence number of %d bytes, got %d\n", header,
5272 expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5273 if (expected->SequenceNumber.cbData)
5274 ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5275 expected->SequenceNumber.cbData),
5276 "%s: unexpected sequence number value\n", header);
5277 ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5278 "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5279 expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5280 got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5281 ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5282 "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5283 expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5284 got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5285 if (expected->SubjectAlgorithm.pszObjId &&
5286 *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5287 ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5288 expected->SubjectAlgorithm.pszObjId);
5289 if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5290 ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5291 got->SubjectAlgorithm.pszObjId),
5292 "%s: expected subject algorithm %s, got %s\n", header,
5293 expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5294 ok(expected->SubjectAlgorithm.Parameters.cbData ==
5295 got->SubjectAlgorithm.Parameters.cbData,
5296 "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5297 expected->SubjectAlgorithm.Parameters.cbData,
5298 got->SubjectAlgorithm.Parameters.cbData);
5299 if (expected->SubjectAlgorithm.Parameters.cbData)
5300 ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5301 got->SubjectAlgorithm.Parameters.pbData,
5302 expected->SubjectAlgorithm.Parameters.cbData),
5303 "%s: unexpected subject algorithm parameter value\n", header);
5304 ok(expected->cCTLEntry == got->cCTLEntry,
5305 "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5306 got->cCTLEntry);
5307 for (i = 0; i < expected->cCTLEntry; i++)
5309 ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5310 got->rgCTLEntry[i].SubjectIdentifier.cbData,
5311 "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5312 header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5313 got->rgCTLEntry[i].SubjectIdentifier.cbData);
5314 if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5315 ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5316 got->rgCTLEntry[i].SubjectIdentifier.pbData,
5317 expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5318 "%s[%d]: unexpected subject identifier value\n",
5319 header, i);
5320 for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5322 ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5323 got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5324 "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5325 expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5326 got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5327 for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5329 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5330 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5331 "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5332 header, i, j, k,
5333 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5334 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5335 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5336 ok(!memcmp(
5337 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5338 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5339 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5340 "%s[%d][%d][%d]: unexpected value\n",
5341 header, i, j, k);
5345 ok(expected->cExtension == got->cExtension,
5346 "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5347 got->cExtension);
5348 for (i = 0; i < expected->cExtension; i++)
5350 ok(!strcmp(expected->rgExtension[i].pszObjId,
5351 got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5352 header, i, expected->rgExtension[i].pszObjId,
5353 got->rgExtension[i].pszObjId);
5354 ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5355 "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5356 expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5357 ok(expected->rgExtension[i].Value.cbData ==
5358 got->rgExtension[i].Value.cbData,
5359 "%s[%d]: expected extension value to have %d bytes, got %d\n",
5360 header, i, expected->rgExtension[i].Value.cbData,
5361 got->rgExtension[i].Value.cbData);
5362 if (expected->rgExtension[i].Value.cbData)
5363 ok(!memcmp(expected->rgExtension[i].Value.pbData,
5364 got->rgExtension[i].Value.pbData,
5365 expected->rgExtension[i].Value.cbData),
5366 "%s[%d]: unexpected extension value\n", header, i);
5370 static const BYTE signedCTL[] = {
5371 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5372 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5373 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5374 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5375 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5376 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5377 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5378 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5379 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5380 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5381 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5382 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5383 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5384 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5385 static const BYTE signedCTLWithCTLInnerContent[] = {
5386 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5387 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5388 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5389 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5390 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5391 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5392 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5393 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5394 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5395 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5396 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5397 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5398 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5399 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5400 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5401 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5402 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5403 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5404 0x57,0x6c,0x0b,0x47,0xb8 };
5406 static void test_decodeCTL(DWORD dwEncoding)
5408 static char oid1[] = "1.2.3";
5409 static char oid2[] = "1.5.6";
5410 static BYTE nullData[] = { 5,0 };
5411 char *pOid1 = oid1;
5412 BOOL ret;
5413 BYTE *buf = NULL;
5414 DWORD size = 0;
5415 CTL_INFO info;
5416 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5417 CTL_ENTRY ctlEntry[2];
5418 CRYPT_ATTRIBUTE attr1, attr2;
5419 CRYPT_ATTR_BLOB value1, value2;
5421 memset(&info, 0, sizeof(info));
5422 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5423 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5424 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5425 if (buf)
5427 compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5428 LocalFree(buf);
5429 buf = NULL;
5431 info.dwVersion = 1;
5432 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5433 sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5434 &size);
5435 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5436 if (buf)
5438 compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5439 LocalFree(buf);
5440 buf = NULL;
5442 info.dwVersion = 0;
5443 info.SubjectUsage.cUsageIdentifier = 1;
5444 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5445 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5446 sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5447 &buf, &size);
5448 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5449 if (buf)
5451 compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5452 LocalFree(buf);
5453 buf = NULL;
5455 info.SubjectUsage.cUsageIdentifier = 0;
5456 info.ListIdentifier.cbData = sizeof(serialNum);
5457 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5458 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5459 sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5460 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5461 if (buf)
5463 compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5464 LocalFree(buf);
5465 buf = NULL;
5467 info.ListIdentifier.cbData = 0;
5468 info.SequenceNumber.cbData = sizeof(serialNum);
5469 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5470 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5471 sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5472 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5473 if (buf)
5475 compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5476 LocalFree(buf);
5477 buf = NULL;
5479 info.SequenceNumber.cbData = 0;
5480 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5481 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5482 sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5483 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5484 if (buf)
5486 compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5487 LocalFree(buf);
5488 buf = NULL;
5490 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5491 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5492 sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5493 &buf, &size);
5494 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5495 if (buf)
5497 compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5498 LocalFree(buf);
5499 buf = NULL;
5501 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5502 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5503 info.SubjectAlgorithm.pszObjId = oid2;
5504 info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5505 info.SubjectAlgorithm.Parameters.pbData = nullData;
5506 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5507 sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5508 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5509 if (buf)
5511 compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5512 LocalFree(buf);
5513 buf = NULL;
5515 SetLastError(0xdeadbeef);
5516 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5517 sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5518 ok(!ret &&
5519 (GetLastError() == CRYPT_E_ASN1_EOD ||
5520 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5521 GetLastError() == OSS_MORE_INPUT), /* Win9x */
5522 "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5523 GetLastError());
5524 info.SubjectAlgorithm.Parameters.cbData = 0;
5525 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5526 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5527 info.SubjectAlgorithm.pszObjId = oid2;
5528 info.SubjectAlgorithm.pszObjId = NULL;
5529 value1.cbData = sizeof(emptySequence);
5530 value1.pbData = (LPBYTE)emptySequence;
5531 attr1.pszObjId = oid1;
5532 attr1.cValue = 1;
5533 attr1.rgValue = &value1;
5534 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5535 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5536 ctlEntry[0].cAttribute = 1;
5537 ctlEntry[0].rgAttribute = &attr1;
5538 info.cCTLEntry = 1;
5539 info.rgCTLEntry = ctlEntry;
5540 SetLastError(0xdeadbeef);
5541 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5542 sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5543 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5544 if (buf)
5546 compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5547 LocalFree(buf);
5548 buf = NULL;
5550 value2.cbData = sizeof(encodedIPAddr);
5551 value2.pbData = (LPBYTE)encodedIPAddr;
5552 attr2.pszObjId = oid2;
5553 attr2.cValue = 1;
5554 attr2.rgValue = &value2;
5555 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5556 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5557 ctlEntry[1].cAttribute = 1;
5558 ctlEntry[1].rgAttribute = &attr2;
5559 info.cCTLEntry = 2;
5560 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5561 sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5562 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5563 if (buf)
5565 compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5566 LocalFree(buf);
5567 buf = NULL;
5569 /* A signed CTL isn't decodable, even if the inner content is a CTL */
5570 SetLastError(0xdeadbeef);
5571 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5572 sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5573 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5574 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5575 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5576 GetLastError());
5577 SetLastError(0xdeadbeef);
5578 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5579 signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5580 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5581 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5582 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5583 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5584 GetLastError());
5587 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5588 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5589 0x03,0,0,0,0,0,0 };
5590 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5591 0xa0,0x01,0x01 };
5592 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5593 0x03,0x02,0x01,0x01 };
5594 static BYTE bogusDER[] = { 1 };
5596 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5598 BOOL ret;
5599 BYTE *buf = NULL;
5600 DWORD size = 0;
5601 CRYPT_CONTENT_INFO info = { 0 };
5602 char oid1[] = "1.2.3";
5604 if (0)
5606 /* Crashes on win9x */
5607 SetLastError(0xdeadbeef);
5608 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5609 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5610 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5611 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5613 SetLastError(0xdeadbeef);
5614 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5615 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5616 ok(!ret && (GetLastError() == E_INVALIDARG ||
5617 GetLastError() == OSS_LIMITED /* Win9x */),
5618 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5619 info.pszObjId = oid1;
5620 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5621 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5622 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5623 if (buf)
5625 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5626 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5627 LocalFree(buf);
5629 info.Content.pbData = bogusDER;
5630 info.Content.cbData = sizeof(bogusDER);
5631 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5632 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5633 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5634 if (buf)
5636 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5637 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5638 LocalFree(buf);
5640 info.Content.pbData = (BYTE *)ints[0].encoded;
5641 info.Content.cbData = ints[0].encoded[1] + 2;
5642 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5643 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5644 if (buf)
5646 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5647 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5648 LocalFree(buf);
5652 static const BYTE indefiniteSignedPKCSContent[] = {
5653 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5654 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5655 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5656 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5657 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5658 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5659 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5660 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5661 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5662 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5663 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5664 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5665 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5666 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5667 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5668 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5669 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5670 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5671 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5672 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5673 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5674 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5675 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5676 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5677 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5678 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5679 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5680 0x00,0x00,0x00,0x00,0x00,0x00 };
5682 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5684 BOOL ret;
5685 LPBYTE buf = NULL;
5686 DWORD size = 0;
5687 CRYPT_CONTENT_INFO *info;
5689 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5690 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5691 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5692 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5693 if (buf)
5695 info = (CRYPT_CONTENT_INFO *)buf;
5697 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5698 info->pszObjId);
5699 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5700 info->Content.cbData);
5701 LocalFree(buf);
5703 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5704 emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5705 0, NULL, NULL, &size);
5706 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5707 SetLastError(0xdeadbeef);
5708 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5709 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5710 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5711 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5712 * I doubt an app depends on that.
5714 ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5715 GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5716 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5717 GetLastError());
5718 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5719 intPKCSContentInfo, sizeof(intPKCSContentInfo),
5720 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5721 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5722 if (buf)
5724 info = (CRYPT_CONTENT_INFO *)buf;
5726 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5727 info->pszObjId);
5728 ok(info->Content.cbData == ints[0].encoded[1] + 2,
5729 "Unexpected size %d\n", info->Content.cbData);
5730 ok(!memcmp(info->Content.pbData, ints[0].encoded,
5731 info->Content.cbData), "Unexpected value\n");
5732 LocalFree(buf);
5734 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5735 indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5736 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5737 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5738 if (buf)
5740 info = (CRYPT_CONTENT_INFO *)buf;
5742 ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5743 "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5744 ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5745 info->Content.cbData);
5746 LocalFree(buf);
5750 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5751 0x00 };
5752 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5753 0x01 };
5754 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5755 0x02,0x01,0x01 };
5757 static void test_encodePKCSAttribute(DWORD dwEncoding)
5759 CRYPT_ATTRIBUTE attr = { 0 };
5760 BOOL ret;
5761 LPBYTE buf = NULL;
5762 DWORD size = 0;
5763 CRYPT_ATTR_BLOB blob;
5764 char oid[] = "1.2.3";
5766 if (0)
5768 /* Crashes on win9x */
5769 SetLastError(0xdeadbeef);
5770 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5771 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5772 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5773 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5775 SetLastError(0xdeadbeef);
5776 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5777 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5778 ok(!ret && (GetLastError() == E_INVALIDARG ||
5779 GetLastError() == OSS_LIMITED /* Win9x */),
5780 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5781 attr.pszObjId = oid;
5782 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5783 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5784 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5785 if (buf)
5787 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5788 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5789 LocalFree(buf);
5791 blob.cbData = sizeof(bogusDER);
5792 blob.pbData = bogusDER;
5793 attr.cValue = 1;
5794 attr.rgValue = &blob;
5795 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5796 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5797 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5798 if (buf)
5800 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5801 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5802 LocalFree(buf);
5804 blob.pbData = (BYTE *)ints[0].encoded;
5805 blob.cbData = ints[0].encoded[1] + 2;
5806 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5807 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5808 if (buf)
5810 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
5811 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
5812 LocalFree(buf);
5816 static void test_decodePKCSAttribute(DWORD dwEncoding)
5818 BOOL ret;
5819 LPBYTE buf = NULL;
5820 DWORD size = 0;
5821 CRYPT_ATTRIBUTE *attr;
5823 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5824 emptyPKCSAttr, sizeof(emptyPKCSAttr),
5825 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5826 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5827 if (buf)
5829 attr = (CRYPT_ATTRIBUTE *)buf;
5831 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5832 attr->pszObjId);
5833 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
5834 LocalFree(buf);
5836 SetLastError(0xdeadbeef);
5837 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5838 bogusPKCSAttr, sizeof(bogusPKCSAttr),
5839 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5840 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5841 * I doubt an app depends on that.
5843 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5844 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5845 GetLastError() == OSS_MORE_INPUT /* Win9x */),
5846 "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
5847 GetLastError());
5848 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
5849 intPKCSAttr, sizeof(intPKCSAttr),
5850 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5851 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5852 if (buf)
5854 attr = (CRYPT_ATTRIBUTE *)buf;
5856 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5857 attr->pszObjId);
5858 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
5859 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
5860 "Unexpected size %d\n", attr->rgValue[0].cbData);
5861 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
5862 attr->rgValue[0].cbData), "Unexpected value\n");
5863 LocalFree(buf);
5867 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
5868 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
5869 0x2a,0x03,0x31,0x00 };
5870 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
5871 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
5873 static void test_encodePKCSAttributes(DWORD dwEncoding)
5875 CRYPT_ATTRIBUTES attributes = { 0 };
5876 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
5877 CRYPT_ATTR_BLOB blob;
5878 BOOL ret;
5879 LPBYTE buf = NULL;
5880 DWORD size = 0;
5881 char oid1[] = "1.2.3", oid2[] = "1.5.6";
5883 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5884 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5885 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5886 if (buf)
5888 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
5889 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
5890 LocalFree(buf);
5892 attributes.cAttr = 1;
5893 attributes.rgAttr = attr;
5894 SetLastError(0xdeadbeef);
5895 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5896 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5897 ok(!ret && (GetLastError() == E_INVALIDARG ||
5898 GetLastError() == OSS_LIMITED /* Win9x */),
5899 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5900 attr[0].pszObjId = oid1;
5901 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5902 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5903 if (buf)
5905 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
5906 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
5907 LocalFree(buf);
5909 attr[1].pszObjId = oid2;
5910 attr[1].cValue = 1;
5911 attr[1].rgValue = &blob;
5912 blob.pbData = (BYTE *)ints[0].encoded;
5913 blob.cbData = ints[0].encoded[1] + 2;
5914 attributes.cAttr = 2;
5915 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
5916 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5917 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5918 if (buf)
5920 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
5921 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
5922 LocalFree(buf);
5926 static void test_decodePKCSAttributes(DWORD dwEncoding)
5928 BOOL ret;
5929 LPBYTE buf = NULL;
5930 DWORD size = 0;
5931 CRYPT_ATTRIBUTES *attributes;
5933 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5934 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
5935 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5936 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5937 if (buf)
5939 attributes = (CRYPT_ATTRIBUTES *)buf;
5940 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
5941 attributes->cAttr);
5942 LocalFree(buf);
5944 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5945 singlePKCSAttributes, sizeof(singlePKCSAttributes),
5946 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5947 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5948 if (buf)
5950 attributes = (CRYPT_ATTRIBUTES *)buf;
5951 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
5952 attributes->cAttr);
5953 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5954 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5955 ok(attributes->rgAttr[0].cValue == 0,
5956 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5957 LocalFree(buf);
5959 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
5960 doublePKCSAttributes, sizeof(doublePKCSAttributes),
5961 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5962 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5963 if (buf)
5965 attributes = (CRYPT_ATTRIBUTES *)buf;
5966 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
5967 attributes->cAttr);
5968 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
5969 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
5970 ok(attributes->rgAttr[0].cValue == 0,
5971 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
5972 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
5973 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
5974 ok(attributes->rgAttr[1].cValue == 1,
5975 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
5976 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
5977 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
5978 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
5979 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
5980 LocalFree(buf);
5984 static const BYTE singleCapability[] = {
5985 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
5986 static const BYTE twoCapabilities[] = {
5987 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
5988 static const BYTE singleCapabilitywithNULL[] = {
5989 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5991 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
5993 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
5994 BOOL ret;
5995 LPBYTE buf = NULL;
5996 DWORD size = 0;
5997 CRYPT_SMIME_CAPABILITY capability[2];
5998 CRYPT_SMIME_CAPABILITIES capabilities;
6000 /* An empty capabilities is allowed */
6001 capabilities.cCapability = 0;
6002 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6003 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6004 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6005 if (buf)
6007 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6008 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6009 LocalFree(buf);
6011 /* A non-empty capabilities with an empty capability (lacking an OID) is
6012 * not allowed
6014 capability[0].pszObjId = NULL;
6015 capability[0].Parameters.cbData = 0;
6016 capabilities.cCapability = 1;
6017 capabilities.rgCapability = capability;
6018 SetLastError(0xdeadbeef);
6019 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6020 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6021 ok(!ret && (GetLastError() == E_INVALIDARG ||
6022 GetLastError() == OSS_LIMITED /* Win9x */),
6023 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6024 capability[0].pszObjId = oid1;
6025 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6026 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6027 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6028 if (buf)
6030 ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6031 ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6032 LocalFree(buf);
6034 capability[1].pszObjId = oid2;
6035 capability[1].Parameters.cbData = 0;
6036 capabilities.cCapability = 2;
6037 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6038 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6039 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6040 if (buf)
6042 ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6043 ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6044 LocalFree(buf);
6048 static void compareSMimeCapabilities(LPCSTR header,
6049 const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6051 DWORD i;
6053 ok(got->cCapability == expected->cCapability,
6054 "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6055 got->cCapability);
6056 for (i = 0; i < expected->cCapability; i++)
6058 ok(!strcmp(expected->rgCapability[i].pszObjId,
6059 got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6060 header, i, expected->rgCapability[i].pszObjId,
6061 got->rgCapability[i].pszObjId);
6062 ok(expected->rgCapability[i].Parameters.cbData ==
6063 got->rgCapability[i].Parameters.cbData,
6064 "%s[%d]: expected %d bytes, got %d\n", header, i,
6065 expected->rgCapability[i].Parameters.cbData,
6066 got->rgCapability[i].Parameters.cbData);
6067 if (expected->rgCapability[i].Parameters.cbData)
6068 ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6069 got->rgCapability[i].Parameters.pbData,
6070 expected->rgCapability[i].Parameters.cbData),
6071 "%s[%d]: unexpected value\n", header, i);
6075 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6077 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6078 BOOL ret;
6079 DWORD size = 0;
6080 CRYPT_SMIME_CAPABILITY capability[2];
6081 CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6083 SetLastError(0xdeadbeef);
6084 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6085 emptySequence, sizeof(emptySequence),
6086 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6087 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6088 if (ret)
6090 capabilities.cCapability = 0;
6091 compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6092 LocalFree(ptr);
6094 SetLastError(0xdeadbeef);
6095 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6096 singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6097 &ptr, &size);
6098 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6099 if (ret)
6101 capability[0].pszObjId = oid1;
6102 capability[0].Parameters.cbData = 0;
6103 capabilities.cCapability = 1;
6104 capabilities.rgCapability = capability;
6105 compareSMimeCapabilities("single capability", &capabilities, ptr);
6106 LocalFree(ptr);
6108 SetLastError(0xdeadbeef);
6109 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6110 singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6111 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6112 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6113 if (ret)
6115 BYTE NULLparam[] = {0x05, 0x00};
6116 capability[0].pszObjId = oid1;
6117 capability[0].Parameters.cbData = 2;
6118 capability[0].Parameters.pbData = NULLparam;
6119 capabilities.cCapability = 1;
6120 capabilities.rgCapability = capability;
6121 compareSMimeCapabilities("single capability with NULL", &capabilities,
6122 ptr);
6123 LocalFree(ptr);
6125 SetLastError(0xdeadbeef);
6126 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6127 twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6128 &ptr, &size);
6129 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6130 if (ret)
6132 capability[0].Parameters.cbData = 0;
6133 capability[1].pszObjId = oid2;
6134 capability[1].Parameters.cbData = 0;
6135 capabilities.cCapability = 2;
6136 compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6137 LocalFree(ptr);
6141 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6142 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6143 0x67 };
6144 static const BYTE minimalPKCSSigner[] = {
6145 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6146 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6147 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6148 static const BYTE PKCSSignerWithSerial[] = {
6149 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6150 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6151 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6152 0x00 };
6153 static const BYTE PKCSSignerWithHashAlgo[] = {
6154 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6155 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6156 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6157 0x00,0x04,0x00 };
6158 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6159 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6160 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6161 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6162 0x06,0x05,0x00,0x04,0x00 };
6163 static const BYTE PKCSSignerWithHash[] = {
6164 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6165 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6166 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6167 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6168 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6169 static const BYTE PKCSSignerWithAuthAttr[] = {
6170 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6171 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6172 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6173 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6174 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6175 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6176 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6178 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6180 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6181 BOOL ret;
6182 LPBYTE buf = NULL;
6183 DWORD size = 0;
6184 CMSG_SIGNER_INFO info = { 0 };
6185 char oid_common_name[] = szOID_COMMON_NAME;
6186 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6187 (LPBYTE)encodedCommonName };
6188 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6190 SetLastError(0xdeadbeef);
6191 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6192 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6193 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6195 skip("no PKCS7_SIGNER_INFO encode support\n");
6196 return;
6198 ok(!ret && (GetLastError() == E_INVALIDARG ||
6199 GetLastError() == OSS_LIMITED /* Win9x */),
6200 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6201 /* To be encoded, a signer must have an issuer at least, and the encoding
6202 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
6203 * see decoding tests.)
6205 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6206 info.Issuer.pbData = encodedCommonNameNoNull;
6207 SetLastError(0xdeadbeef);
6208 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6209 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6210 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6211 ok(!ret && GetLastError() == E_INVALIDARG,
6212 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6213 else
6215 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6216 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6217 if (buf)
6219 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6220 if (size == sizeof(minimalPKCSSigner))
6221 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6222 else
6223 ok(0, "Unexpected value\n");
6224 LocalFree(buf);
6227 info.SerialNumber.cbData = sizeof(serialNum);
6228 info.SerialNumber.pbData = (BYTE *)serialNum;
6229 SetLastError(0xdeadbeef);
6230 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6231 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6232 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6233 ok(!ret && GetLastError() == E_INVALIDARG,
6234 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6235 else
6237 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6238 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6239 if (buf)
6241 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6242 size);
6243 if (size == sizeof(PKCSSignerWithSerial))
6244 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6245 "Unexpected value\n");
6246 else
6247 ok(0, "Unexpected value\n");
6248 LocalFree(buf);
6251 info.HashAlgorithm.pszObjId = oid1;
6252 SetLastError(0xdeadbeef);
6253 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6254 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6255 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6256 ok(!ret && GetLastError() == E_INVALIDARG,
6257 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6258 else
6260 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6261 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6262 if (buf)
6264 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6265 size);
6266 if (size == sizeof(PKCSSignerWithHashAlgo))
6267 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6268 "Unexpected value\n");
6269 else
6270 ok(0, "Unexpected value\n");
6271 LocalFree(buf);
6274 info.HashEncryptionAlgorithm.pszObjId = oid2;
6275 SetLastError(0xdeadbeef);
6276 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6277 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6278 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6279 ok(!ret && GetLastError() == E_INVALIDARG,
6280 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6281 else
6283 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6284 if (buf)
6286 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6287 "Unexpected size %d\n", size);
6288 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6289 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6290 "Unexpected value\n");
6291 else
6292 ok(0, "Unexpected value\n");
6293 LocalFree(buf);
6296 info.EncryptedHash.cbData = sizeof(hash);
6297 info.EncryptedHash.pbData = (BYTE *)hash;
6298 SetLastError(0xdeadbeef);
6299 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6300 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6301 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6302 ok(!ret && GetLastError() == E_INVALIDARG,
6303 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6304 else
6306 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6307 if (buf)
6309 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6310 size);
6311 if (size == sizeof(PKCSSignerWithHash))
6312 ok(!memcmp(buf, PKCSSignerWithHash, size),
6313 "Unexpected value\n");
6314 else
6315 ok(0, "Unexpected value\n");
6316 LocalFree(buf);
6319 info.AuthAttrs.cAttr = 1;
6320 info.AuthAttrs.rgAttr = &attr;
6321 SetLastError(0xdeadbeef);
6322 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6323 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6324 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6325 ok(!ret && GetLastError() == E_INVALIDARG,
6326 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6327 else
6329 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6330 if (buf)
6332 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6333 size);
6334 if (size == sizeof(PKCSSignerWithAuthAttr))
6335 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6336 "Unexpected value\n");
6337 else
6338 ok(0, "Unexpected value\n");
6339 LocalFree(buf);
6344 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6346 BOOL ret;
6347 LPBYTE buf = NULL;
6348 DWORD size = 0;
6349 CMSG_SIGNER_INFO *info;
6351 /* A PKCS signer can't be decoded without a serial number. */
6352 SetLastError(0xdeadbeef);
6353 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6354 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6355 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6356 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6357 GetLastError() == OSS_DATA_ERROR /* Win9x */),
6358 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6359 GetLastError());
6360 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6361 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6362 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6363 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6364 "CryptDecodeObjectEx failed: %x\n", GetLastError());
6365 if (buf)
6367 info = (CMSG_SIGNER_INFO *)buf;
6368 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6369 info->dwVersion);
6370 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6371 "Unexpected size %d\n", info->Issuer.cbData);
6372 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6373 info->Issuer.cbData), "Unexpected value\n");
6374 ok(info->SerialNumber.cbData == sizeof(serialNum),
6375 "Unexpected size %d\n", info->SerialNumber.cbData);
6376 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6377 "Unexpected value\n");
6378 LocalFree(buf);
6380 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6381 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6382 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6383 if (buf)
6385 info = (CMSG_SIGNER_INFO *)buf;
6386 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6387 info->dwVersion);
6388 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6389 "Unexpected size %d\n", info->Issuer.cbData);
6390 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6391 info->Issuer.cbData), "Unexpected value\n");
6392 ok(info->SerialNumber.cbData == sizeof(serialNum),
6393 "Unexpected size %d\n", info->SerialNumber.cbData);
6394 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6395 "Unexpected value\n");
6396 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6397 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6398 LocalFree(buf);
6400 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6401 PKCSSignerWithHashAndEncryptionAlgo,
6402 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6403 NULL, &buf, &size);
6404 if (buf)
6406 info = (CMSG_SIGNER_INFO *)buf;
6407 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6408 info->dwVersion);
6409 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6410 "Unexpected size %d\n", info->Issuer.cbData);
6411 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6412 info->Issuer.cbData), "Unexpected value\n");
6413 ok(info->SerialNumber.cbData == sizeof(serialNum),
6414 "Unexpected size %d\n", info->SerialNumber.cbData);
6415 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6416 "Unexpected value\n");
6417 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6418 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6419 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6420 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6421 LocalFree(buf);
6423 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6424 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6425 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6426 if (buf)
6428 info = (CMSG_SIGNER_INFO *)buf;
6429 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6430 info->dwVersion);
6431 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6432 "Unexpected size %d\n", info->Issuer.cbData);
6433 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6434 info->Issuer.cbData), "Unexpected value\n");
6435 ok(info->SerialNumber.cbData == sizeof(serialNum),
6436 "Unexpected size %d\n", info->SerialNumber.cbData);
6437 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6438 "Unexpected value\n");
6439 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6440 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6441 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6442 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6443 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6444 info->EncryptedHash.cbData);
6445 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6446 "Unexpected value\n");
6447 LocalFree(buf);
6449 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6450 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6451 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6452 if (buf)
6454 info = (CMSG_SIGNER_INFO *)buf;
6455 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6456 info->AuthAttrs.cAttr);
6457 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6458 "Expected %s, got %s\n", szOID_COMMON_NAME,
6459 info->AuthAttrs.rgAttr[0].pszObjId);
6460 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6461 info->AuthAttrs.rgAttr[0].cValue);
6462 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6463 sizeof(encodedCommonName), "Unexpected size %d\n",
6464 info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6465 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6466 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6467 LocalFree(buf);
6471 static const BYTE CMSSignerWithKeyId[] = {
6472 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6473 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6475 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6477 BOOL ret;
6478 LPBYTE buf = NULL;
6479 DWORD size = 0;
6480 CMSG_CMS_SIGNER_INFO info = { 0 };
6481 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6483 SetLastError(0xdeadbeef);
6484 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6485 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6486 ok(!ret, "Expected failure, got %d\n", ret);
6487 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6489 skip("no CMS_SIGNER_INFO encode support\n");
6490 return;
6492 ok(GetLastError() == E_INVALIDARG,
6493 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6494 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6495 SetLastError(0xdeadbeef);
6496 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6497 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6498 ok(!ret, "Expected failure, got %d\n", ret);
6499 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6501 skip("no CMS_SIGNER_INFO encode support\n");
6502 return;
6504 ok(GetLastError() == E_INVALIDARG,
6505 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6506 /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6507 * be a key id or a issuer serial number with at least the issuer set, and
6508 * the encoding must include PKCS_7_ASN_ENCODING.
6509 * (That isn't enough to be decoded, see decoding tests.)
6511 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6512 sizeof(encodedCommonNameNoNull);
6513 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6514 SetLastError(0xdeadbeef);
6515 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6516 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6517 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6518 ok(!ret && GetLastError() == E_INVALIDARG,
6519 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6520 else
6522 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6523 if (buf)
6525 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6526 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6527 LocalFree(buf);
6530 U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6531 U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6532 SetLastError(0xdeadbeef);
6533 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6534 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6535 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6536 ok(!ret && GetLastError() == E_INVALIDARG,
6537 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6538 else
6540 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6541 if (buf)
6543 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6544 size);
6545 ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6546 LocalFree(buf);
6549 info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6550 U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6551 U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6552 SetLastError(0xdeadbeef);
6553 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6554 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6555 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6556 ok(!ret && GetLastError() == E_INVALIDARG,
6557 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6558 else
6560 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6561 if (buf)
6563 ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6564 size);
6565 ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6566 LocalFree(buf);
6569 /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6570 * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6571 * (see RFC 3852, section 5.3.)
6573 info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6574 U(info.SignerId).HashId.cbData = sizeof(hash);
6575 U(info.SignerId).HashId.pbData = (BYTE *)hash;
6576 SetLastError(0xdeadbeef);
6577 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6578 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6579 ok(!ret && GetLastError() == E_INVALIDARG,
6580 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6581 /* Now with a hash algo */
6582 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6583 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6584 sizeof(encodedCommonNameNoNull);
6585 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6586 info.HashAlgorithm.pszObjId = oid1;
6587 SetLastError(0xdeadbeef);
6588 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6589 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6590 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6591 ok(!ret && GetLastError() == E_INVALIDARG,
6592 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6593 else
6595 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6596 if (buf)
6598 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6599 size);
6600 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6601 "Unexpected value\n");
6602 LocalFree(buf);
6605 info.HashEncryptionAlgorithm.pszObjId = oid2;
6606 SetLastError(0xdeadbeef);
6607 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6608 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6609 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6610 ok(!ret && GetLastError() == E_INVALIDARG,
6611 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6612 else
6614 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6615 if (buf)
6617 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6618 "Unexpected size %d\n", size);
6619 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6620 "Unexpected value\n");
6621 LocalFree(buf);
6624 info.EncryptedHash.cbData = sizeof(hash);
6625 info.EncryptedHash.pbData = (BYTE *)hash;
6626 SetLastError(0xdeadbeef);
6627 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6628 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6629 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6630 ok(!ret && GetLastError() == E_INVALIDARG,
6631 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6632 else
6634 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6635 if (buf)
6637 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6638 size);
6639 ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6640 LocalFree(buf);
6645 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6647 BOOL ret;
6648 LPBYTE buf = NULL;
6649 DWORD size = 0;
6650 CMSG_CMS_SIGNER_INFO *info;
6651 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6653 /* A CMS signer can't be decoded without a serial number. */
6654 SetLastError(0xdeadbeef);
6655 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6656 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6657 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6658 ok(!ret, "expected failure\n");
6659 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6661 skip("no CMS_SIGNER_INFO decode support\n");
6662 return;
6664 ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6665 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6666 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6667 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6668 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6669 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6670 if (buf)
6672 info = (CMSG_CMS_SIGNER_INFO *)buf;
6673 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6674 info->dwVersion);
6675 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6676 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6677 info->SignerId.dwIdChoice);
6678 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6679 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6680 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6681 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6682 encodedCommonNameNoNull,
6683 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6684 "Unexpected value\n");
6685 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6686 sizeof(serialNum), "Unexpected size %d\n",
6687 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6688 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6689 serialNum, sizeof(serialNum)), "Unexpected value\n");
6690 LocalFree(buf);
6692 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6693 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6694 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6695 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6696 if (buf)
6698 info = (CMSG_CMS_SIGNER_INFO *)buf;
6699 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6700 info->dwVersion);
6701 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6702 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6703 info->SignerId.dwIdChoice);
6704 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6705 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6706 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6707 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6708 encodedCommonNameNoNull,
6709 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6710 "Unexpected value\n");
6711 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6712 sizeof(serialNum), "Unexpected size %d\n",
6713 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6714 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6715 serialNum, sizeof(serialNum)), "Unexpected value\n");
6716 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6717 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6718 LocalFree(buf);
6720 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6721 PKCSSignerWithHashAndEncryptionAlgo,
6722 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6723 NULL, &buf, &size);
6724 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6725 if (buf)
6727 info = (CMSG_CMS_SIGNER_INFO *)buf;
6728 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6729 info->dwVersion);
6730 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6731 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6732 info->SignerId.dwIdChoice);
6733 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6734 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6735 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6736 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6737 encodedCommonNameNoNull,
6738 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6739 "Unexpected value\n");
6740 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6741 sizeof(serialNum), "Unexpected size %d\n",
6742 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6743 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6744 serialNum, sizeof(serialNum)), "Unexpected value\n");
6745 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6746 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6747 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6748 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6749 LocalFree(buf);
6751 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6752 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6753 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6754 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6755 if (buf)
6757 info = (CMSG_CMS_SIGNER_INFO *)buf;
6758 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6759 info->dwVersion);
6760 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6761 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6762 info->SignerId.dwIdChoice);
6763 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6764 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6765 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6766 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6767 encodedCommonNameNoNull,
6768 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6769 "Unexpected value\n");
6770 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6771 sizeof(serialNum), "Unexpected size %d\n",
6772 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6773 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6774 serialNum, sizeof(serialNum)), "Unexpected value\n");
6775 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6776 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6777 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6778 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6779 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6780 info->EncryptedHash.cbData);
6781 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6782 "Unexpected value\n");
6783 LocalFree(buf);
6785 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6786 CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6787 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6788 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6789 if (buf)
6791 info = (CMSG_CMS_SIGNER_INFO *)buf;
6792 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6793 info->dwVersion);
6794 ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6795 "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6796 info->SignerId.dwIdChoice);
6797 ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6798 "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6799 ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6800 "Unexpected value\n");
6801 LocalFree(buf);
6805 static BYTE emptyDNSPermittedConstraints[] = {
6806 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6807 static BYTE emptyDNSExcludedConstraints[] = {
6808 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6809 static BYTE DNSExcludedConstraints[] = {
6810 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
6811 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6812 static BYTE permittedAndExcludedConstraints[] = {
6813 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6814 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
6815 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6816 static BYTE permittedAndExcludedWithMinConstraints[] = {
6817 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6818 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
6819 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6820 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
6821 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
6822 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
6823 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
6825 static void test_encodeNameConstraints(DWORD dwEncoding)
6827 BOOL ret;
6828 CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
6829 CERT_GENERAL_SUBTREE permitted = { { 0 } };
6830 CERT_GENERAL_SUBTREE excluded = { { 0 } };
6831 LPBYTE buf;
6832 DWORD size;
6834 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6835 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6836 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6838 skip("no X509_NAME_CONSTRAINTS encode support\n");
6839 return;
6841 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6842 if (ret)
6844 ok(size == sizeof(emptySequence), "Unexpected size\n");
6845 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
6846 LocalFree(buf);
6848 constraints.cPermittedSubtree = 1;
6849 constraints.rgPermittedSubtree = &permitted;
6850 SetLastError(0xdeadbeef);
6851 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6852 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6853 ok(!ret && GetLastError() == E_INVALIDARG,
6854 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6855 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6856 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6857 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6858 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6859 if (ret)
6861 ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
6862 ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
6863 "Unexpected value\n");
6864 LocalFree(buf);
6866 constraints.cPermittedSubtree = 0;
6867 constraints.cExcludedSubtree = 1;
6868 constraints.rgExcludedSubtree = &excluded;
6869 excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
6870 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6871 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6872 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6873 if (ret)
6875 ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
6876 ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
6877 "Unexpected value\n");
6878 LocalFree(buf);
6880 U(excluded.Base).pwszURL = (LPWSTR)url;
6881 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6882 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6883 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6884 if (ret)
6886 ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
6887 ok(!memcmp(buf, DNSExcludedConstraints, size),
6888 "Unexpected value\n");
6889 LocalFree(buf);
6891 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
6892 U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6893 U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6894 constraints.cPermittedSubtree = 1;
6895 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6896 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6897 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6898 if (ret)
6900 ok(size == sizeof(permittedAndExcludedConstraints),
6901 "Unexpected size\n");
6902 ok(!memcmp(buf, permittedAndExcludedConstraints, size),
6903 "Unexpected value\n");
6904 LocalFree(buf);
6906 permitted.dwMinimum = 5;
6907 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6908 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6909 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6910 if (ret)
6912 ok(size == sizeof(permittedAndExcludedWithMinConstraints),
6913 "Unexpected size\n");
6914 ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
6915 "Unexpected value\n");
6916 LocalFree(buf);
6918 permitted.fMaximum = TRUE;
6919 permitted.dwMaximum = 3;
6920 SetLastError(0xdeadbeef);
6921 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
6922 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6923 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6924 if (ret)
6926 ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
6927 "Unexpected size\n");
6928 ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
6929 "Unexpected value\n");
6930 LocalFree(buf);
6934 struct EncodedNameConstraints
6936 CRYPT_DATA_BLOB encoded;
6937 CERT_NAME_CONSTRAINTS_INFO constraints;
6940 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
6941 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6942 static CERT_GENERAL_SUBTREE DNSSubtree = {
6943 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
6944 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
6945 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
6946 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
6947 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
6948 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
6949 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
6951 struct EncodedNameConstraints encodedNameConstraints[] = {
6952 { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
6953 { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
6954 { 1, &emptyDNSSubtree, 0, NULL } },
6955 { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
6956 { 0, NULL, 1, &emptyDNSSubtree } },
6957 { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
6958 { 0, NULL, 1, &DNSSubtree } },
6959 { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
6960 { 1, &IPAddressSubtree, 1, &DNSSubtree } },
6961 { { sizeof(permittedAndExcludedWithMinConstraints),
6962 permittedAndExcludedWithMinConstraints },
6963 { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
6964 { { sizeof(permittedAndExcludedWithMinMaxConstraints),
6965 permittedAndExcludedWithMinMaxConstraints },
6966 { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
6969 static void test_decodeNameConstraints(DWORD dwEncoding)
6971 BOOL ret;
6972 DWORD i;
6973 CERT_NAME_CONSTRAINTS_INFO *constraints;
6975 U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
6976 U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6977 U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6978 U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6979 U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6980 U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
6981 U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
6982 for (i = 0;
6983 i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
6984 i++)
6986 DWORD size;
6988 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
6989 encodedNameConstraints[i].encoded.pbData,
6990 encodedNameConstraints[i].encoded.cbData,
6991 CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
6992 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6994 skip("no X509_NAME_CONSTRAINTS decode support\n");
6995 return;
6997 ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
6998 if (ret)
7000 DWORD j;
7002 if (constraints->cPermittedSubtree !=
7003 encodedNameConstraints[i].constraints.cPermittedSubtree)
7004 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7005 encodedNameConstraints[i].constraints.cPermittedSubtree,
7006 constraints->cPermittedSubtree);
7007 if (constraints->cPermittedSubtree ==
7008 encodedNameConstraints[i].constraints.cPermittedSubtree)
7010 for (j = 0; j < constraints->cPermittedSubtree; j++)
7012 compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7013 &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7016 if (constraints->cExcludedSubtree !=
7017 encodedNameConstraints[i].constraints.cExcludedSubtree)
7018 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7019 encodedNameConstraints[i].constraints.cExcludedSubtree,
7020 constraints->cExcludedSubtree);
7021 if (constraints->cExcludedSubtree ==
7022 encodedNameConstraints[i].constraints.cExcludedSubtree)
7024 for (j = 0; j < constraints->cExcludedSubtree; j++)
7026 compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7027 &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7030 LocalFree(constraints);
7035 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7036 'n','o','t','i','c','e',0 };
7037 static const BYTE noticeWithDisplayText[] = {
7038 0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7039 0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7040 0x00,0x69,0x00,0x63,0x00,0x65
7042 static char org[] = "Wine";
7043 static int noticeNumbers[] = { 2,3 };
7044 static BYTE noticeWithReference[] = {
7045 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7046 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7047 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7048 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7051 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7053 BOOL ret;
7054 LPBYTE buf;
7055 DWORD size;
7056 CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7057 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7059 memset(&notice, 0, sizeof(notice));
7060 ret = pCryptEncodeObjectEx(dwEncoding,
7061 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7062 NULL, &buf, &size);
7063 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7065 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7066 return;
7068 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7069 if (ret)
7071 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7072 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7073 LocalFree(buf);
7075 notice.pszDisplayText = noticeText;
7076 ret = pCryptEncodeObjectEx(dwEncoding,
7077 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7078 NULL, &buf, &size);
7079 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7080 if (ret)
7082 ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7083 ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7084 LocalFree(buf);
7086 reference.pszOrganization = org;
7087 reference.cNoticeNumbers = 2;
7088 reference.rgNoticeNumbers = noticeNumbers;
7089 notice.pNoticeReference = &reference;
7090 ret = pCryptEncodeObjectEx(dwEncoding,
7091 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7092 NULL, &buf, &size);
7093 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7094 if (ret)
7096 ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7097 ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7098 LocalFree(buf);
7102 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7104 BOOL ret;
7105 CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7106 DWORD size;
7108 ret = pCryptDecodeObjectEx(dwEncoding,
7109 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7110 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7111 &notice, &size);
7112 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7114 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7115 return;
7117 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7118 if (ret)
7120 ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7121 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7122 LocalFree(notice);
7124 ret = pCryptDecodeObjectEx(dwEncoding,
7125 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7126 noticeWithDisplayText, sizeof(noticeWithDisplayText),
7127 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7128 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7129 if (ret)
7131 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7132 "unexpected display text\n");
7133 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7134 LocalFree(notice);
7136 ret = pCryptDecodeObjectEx(dwEncoding,
7137 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7138 noticeWithReference, sizeof(noticeWithReference),
7139 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7140 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7141 if (ret)
7143 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7144 "unexpected display text\n");
7145 ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7146 if (notice->pNoticeReference)
7148 ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7149 "unexpected organization %s\n",
7150 notice->pNoticeReference->pszOrganization);
7151 ok(notice->pNoticeReference->cNoticeNumbers == 2,
7152 "expected 2 notice numbers, got %d\n",
7153 notice->pNoticeReference->cNoticeNumbers);
7154 ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7155 "unexpected notice number %d\n",
7156 notice->pNoticeReference->rgNoticeNumbers[0]);
7157 ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7158 "unexpected notice number %d\n",
7159 notice->pNoticeReference->rgNoticeNumbers[1]);
7161 LocalFree(notice);
7165 static char oid_any_policy[] = "2.5.29.32.0";
7166 static const BYTE policiesWithAnyPolicy[] = {
7167 0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7169 static char oid1[] = "1.2.3";
7170 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7171 static const BYTE twoPolicies[] = {
7172 0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7173 0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7174 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7175 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7176 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7177 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7180 static void test_encodeCertPolicies(DWORD dwEncoding)
7182 BOOL ret;
7183 CERT_POLICIES_INFO info;
7184 CERT_POLICY_INFO policy[2];
7185 CERT_POLICY_QUALIFIER_INFO qualifier;
7186 LPBYTE buf;
7187 DWORD size;
7189 memset(&info, 0, sizeof(info));
7190 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7191 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7192 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7193 if (ret)
7195 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7196 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7197 LocalFree(buf);
7199 memset(policy, 0, sizeof(policy));
7200 info.cPolicyInfo = 1;
7201 info.rgPolicyInfo = policy;
7202 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7203 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7204 ok(!ret && (GetLastError() == E_INVALIDARG ||
7205 GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7206 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7207 policy[0].pszPolicyIdentifier = oid_any_policy;
7208 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7209 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7210 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7211 if (ret)
7213 ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7214 ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7215 LocalFree(buf);
7217 policy[1].pszPolicyIdentifier = oid1;
7218 memset(&qualifier, 0, sizeof(qualifier));
7219 qualifier.pszPolicyQualifierId = oid_user_notice;
7220 qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7221 qualifier.Qualifier.pbData = noticeWithReference;
7222 policy[1].cPolicyQualifier = 1;
7223 policy[1].rgPolicyQualifier = &qualifier;
7224 info.cPolicyInfo = 2;
7225 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7226 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7227 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7228 if (ret)
7230 ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7231 ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7232 LocalFree(buf);
7236 static void test_decodeCertPolicies(DWORD dwEncoding)
7238 BOOL ret;
7239 CERT_POLICIES_INFO *info;
7240 DWORD size;
7242 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7243 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7244 &info, &size);
7245 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7246 if (ret)
7248 ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7249 info->cPolicyInfo);
7250 LocalFree(info);
7252 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7253 policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7254 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7255 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7256 if (ret)
7258 ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7259 info->cPolicyInfo);
7260 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7261 "unexpected policy id %s\n",
7262 info->rgPolicyInfo[0].pszPolicyIdentifier);
7263 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7264 "unexpected policy qualifier count %d\n",
7265 info->rgPolicyInfo[0].cPolicyQualifier);
7266 LocalFree(info);
7268 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7269 twoPolicies, sizeof(twoPolicies),
7270 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7271 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7272 if (ret)
7274 ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7275 info->cPolicyInfo);
7276 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7277 "unexpected policy id %s\n",
7278 info->rgPolicyInfo[0].pszPolicyIdentifier);
7279 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7280 "unexpected policy qualifier count %d\n",
7281 info->rgPolicyInfo[0].cPolicyQualifier);
7282 ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7283 "unexpected policy id %s\n",
7284 info->rgPolicyInfo[1].pszPolicyIdentifier);
7285 ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7286 "unexpected policy qualifier count %d\n",
7287 info->rgPolicyInfo[1].cPolicyQualifier);
7288 ok(!strcmp(
7289 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7290 oid_user_notice), "unexpected policy qualifier id %s\n",
7291 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7292 ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7293 sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7294 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7295 ok(!memcmp(
7296 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7297 noticeWithReference, sizeof(noticeWithReference)),
7298 "unexpected qualifier value\n");
7299 LocalFree(info);
7303 /* Free *pInfo with HeapFree */
7304 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7306 BOOL ret;
7307 DWORD size = 0;
7308 HCRYPTKEY key;
7310 /* This crashes
7311 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7313 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7314 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7315 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7316 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7317 &size);
7318 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7319 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7320 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7321 NULL, &size);
7322 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7323 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7324 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7325 0, NULL, NULL, &size);
7326 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7327 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7328 /* Test with no key */
7329 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7330 0, NULL, NULL, &size);
7331 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7332 GetLastError());
7333 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7334 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7335 if (ret)
7337 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7338 NULL, 0, NULL, NULL, &size);
7339 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7340 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7341 if (*pInfo)
7343 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7344 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7345 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7346 GetLastError());
7347 if (ret)
7349 /* By default (we passed NULL as the OID) the OID is
7350 * szOID_RSA_RSA.
7352 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7353 "Expected %s, got %s\n", szOID_RSA_RSA,
7354 (*pInfo)->Algorithm.pszObjId);
7358 CryptDestroyKey(key);
7361 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7362 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7363 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7364 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7365 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7366 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7367 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7368 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7369 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7370 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7371 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7372 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7373 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7374 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7375 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7376 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7377 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7378 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7379 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7380 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7381 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7382 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7383 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7384 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7385 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7387 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7389 BOOL ret;
7390 HCRYPTKEY key;
7391 PCCERT_CONTEXT context;
7392 DWORD dwSize;
7393 ALG_ID ai;
7395 /* These crash
7396 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7397 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7398 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7399 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7400 NULL);
7402 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7403 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7404 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7405 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7406 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7407 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7408 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7409 &key);
7410 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7411 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7413 /* Export key with standard algorithm (CALG_RSA_KEYX) */
7414 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7415 &key);
7416 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7418 dwSize = sizeof(ai);
7419 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7420 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7421 if(ret)
7423 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7424 ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7427 CryptDestroyKey(key);
7429 /* Repeat with forced algorithm */
7430 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7431 &key);
7432 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7434 dwSize = sizeof(ai);
7435 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7436 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7437 if(ret)
7439 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7440 ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7443 CryptDestroyKey(key);
7445 /* Test importing a public key from a certificate context */
7446 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7447 sizeof(expiredCert));
7448 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7449 GetLastError());
7450 if (context)
7452 ok(!strcmp(szOID_RSA_RSA,
7453 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7454 "Expected %s, got %s\n", szOID_RSA_RSA,
7455 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7456 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7457 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7458 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7459 CryptDestroyKey(key);
7460 CertFreeCertificateContext(context);
7464 static const char cspName[] = "WineCryptTemp";
7466 static void testPortPublicKeyInfo(void)
7468 HCRYPTPROV csp;
7469 BOOL ret;
7470 PCERT_PUBLIC_KEY_INFO info = NULL;
7472 /* Just in case a previous run failed, delete this thing */
7473 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7474 CRYPT_DELETEKEYSET);
7475 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7476 CRYPT_NEWKEYSET);
7478 testExportPublicKey(csp, &info);
7479 testImportPublicKey(csp, info);
7481 HeapFree(GetProcessHeap(), 0, info);
7482 CryptReleaseContext(csp, 0);
7483 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7484 CRYPT_DELETEKEYSET);
7487 START_TEST(encode)
7489 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7490 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7491 HMODULE hCrypt32;
7492 DWORD i;
7494 hCrypt32 = GetModuleHandleA("crypt32.dll");
7495 pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7496 pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7497 if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7499 win_skip("CryptDecodeObjectEx() is not available\n");
7500 return;
7503 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7505 test_encodeInt(encodings[i]);
7506 test_decodeInt(encodings[i]);
7507 test_encodeEnumerated(encodings[i]);
7508 test_decodeEnumerated(encodings[i]);
7509 test_encodeFiletime(encodings[i]);
7510 test_decodeFiletime(encodings[i]);
7511 test_encodeName(encodings[i]);
7512 test_decodeName(encodings[i]);
7513 test_encodeUnicodeName(encodings[i]);
7514 test_decodeUnicodeName(encodings[i]);
7515 test_encodeNameValue(encodings[i]);
7516 test_decodeNameValue(encodings[i]);
7517 test_encodeUnicodeNameValue(encodings[i]);
7518 test_decodeUnicodeNameValue(encodings[i]);
7519 test_encodeAltName(encodings[i]);
7520 test_decodeAltName(encodings[i]);
7521 test_encodeOctets(encodings[i]);
7522 test_decodeOctets(encodings[i]);
7523 test_encodeBits(encodings[i]);
7524 test_decodeBits(encodings[i]);
7525 test_encodeBasicConstraints(encodings[i]);
7526 test_decodeBasicConstraints(encodings[i]);
7527 test_encodeRsaPublicKey(encodings[i]);
7528 test_decodeRsaPublicKey(encodings[i]);
7529 test_encodeSequenceOfAny(encodings[i]);
7530 test_decodeSequenceOfAny(encodings[i]);
7531 test_encodeExtensions(encodings[i]);
7532 test_decodeExtensions(encodings[i]);
7533 test_encodePublicKeyInfo(encodings[i]);
7534 test_decodePublicKeyInfo(encodings[i]);
7535 test_encodeCertToBeSigned(encodings[i]);
7536 test_decodeCertToBeSigned(encodings[i]);
7537 test_encodeCert(encodings[i]);
7538 test_decodeCert(encodings[i]);
7539 test_encodeCRLDistPoints(encodings[i]);
7540 test_decodeCRLDistPoints(encodings[i]);
7541 test_encodeCRLIssuingDistPoint(encodings[i]);
7542 test_decodeCRLIssuingDistPoint(encodings[i]);
7543 test_encodeCRLToBeSigned(encodings[i]);
7544 test_decodeCRLToBeSigned(encodings[i]);
7545 test_encodeEnhancedKeyUsage(encodings[i]);
7546 test_decodeEnhancedKeyUsage(encodings[i]);
7547 test_encodeAuthorityKeyId(encodings[i]);
7548 test_decodeAuthorityKeyId(encodings[i]);
7549 test_encodeAuthorityKeyId2(encodings[i]);
7550 test_decodeAuthorityKeyId2(encodings[i]);
7551 test_encodeAuthorityInfoAccess(encodings[i]);
7552 test_decodeAuthorityInfoAccess(encodings[i]);
7553 test_encodeCTL(encodings[i]);
7554 test_decodeCTL(encodings[i]);
7555 test_encodePKCSContentInfo(encodings[i]);
7556 test_decodePKCSContentInfo(encodings[i]);
7557 test_encodePKCSAttribute(encodings[i]);
7558 test_decodePKCSAttribute(encodings[i]);
7559 test_encodePKCSAttributes(encodings[i]);
7560 test_decodePKCSAttributes(encodings[i]);
7561 test_encodePKCSSMimeCapabilities(encodings[i]);
7562 test_decodePKCSSMimeCapabilities(encodings[i]);
7563 test_encodePKCSSignerInfo(encodings[i]);
7564 test_decodePKCSSignerInfo(encodings[i]);
7565 test_encodeCMSSignerInfo(encodings[i]);
7566 test_decodeCMSSignerInfo(encodings[i]);
7567 test_encodeNameConstraints(encodings[i]);
7568 test_decodeNameConstraints(encodings[i]);
7569 test_encodePolicyQualifierUserNotice(encodings[i]);
7570 test_decodePolicyQualifierUserNotice(encodings[i]);
7571 test_encodeCertPolicies(encodings[i]);
7572 test_decodeCertPolicies(encodings[i]);
7574 testPortPublicKeyInfo();