[THEMES]
[reactos.git] / rostests / winetests / crypt32 / encode.c
1 /*
2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
3 *
4 * Copyright 2005 Juan Lang
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 */
20 #include <stdio.h>
21 //#include <stdarg.h>
22 #include <windef.h>
23 #include <winbase.h>
24 //#include <winerror.h>
25 #include <wincrypt.h>
26
27 #include <wine/test.h>
28
29
30 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*);
31 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*);
32
33 struct encodedInt
34 {
35 int val;
36 const BYTE *encoded;
37 };
38
39 static const BYTE bin1[] = {0x02,0x01,0x01};
40 static const BYTE bin2[] = {0x02,0x01,0x7f};
41 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
42 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
43 static const BYTE bin5[] = {0x02,0x01,0x80};
44 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
45 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
46
47 static const struct encodedInt ints[] = {
48 { 1, bin1 },
49 { 127, bin2 },
50 { 128, bin3 },
51 { 256, bin4 },
52 { -128, bin5 },
53 { -129, bin6 },
54 { 0xbaddf00d, bin7 },
55 };
56
57 struct encodedBigInt
58 {
59 const BYTE *val;
60 const BYTE *encoded;
61 const BYTE *decoded;
62 };
63
64 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
65 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
66 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
67
68 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
69 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
70 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
71
72 static const struct encodedBigInt bigInts[] = {
73 { bin8, bin9, bin10 },
74 { bin11, bin12, bin13 },
75 };
76
77 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
79 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
80 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
81
82 /* Decoded is the same as original, so don't bother storing a separate copy */
83 static const struct encodedBigInt bigUInts[] = {
84 { bin14, bin15, NULL },
85 { bin16, bin17, NULL },
86 };
87
88 static void test_encodeInt(DWORD dwEncoding)
89 {
90 DWORD bufSize = 0;
91 int i;
92 BOOL ret;
93 CRYPT_INTEGER_BLOB blob;
94 BYTE *buf = NULL;
95
96 /* CryptEncodeObjectEx with NULL bufSize crashes..
97 ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
98 NULL);
99 */
100 /* check bogus encoding */
101 ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
102 &bufSize);
103 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
104 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
105 if (0)
106 {
107 /* check with NULL integer buffer. Windows XP incorrectly returns an
108 * NTSTATUS (crashes on win9x).
109 */
110 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
111 &bufSize);
112 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
113 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
114 }
115 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
116 {
117 /* encode as normal integer */
118 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
119 NULL, NULL, &bufSize);
120 ok(ret, "Expected success, got %d\n", GetLastError());
121 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
122 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
123 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
124 if (ret)
125 {
126 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127 buf[0]);
128 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129 buf[1], ints[i].encoded[1]);
130 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132 LocalFree(buf);
133 }
134 /* encode as multibyte integer */
135 blob.cbData = sizeof(ints[i].val);
136 blob.pbData = (BYTE *)&ints[i].val;
137 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138 0, NULL, NULL, &bufSize);
139 ok(ret, "Expected success, got %d\n", GetLastError());
140 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143 if (ret)
144 {
145 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146 buf[0]);
147 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148 buf[1], ints[i].encoded[1]);
149 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151 LocalFree(buf);
152 }
153 }
154 /* encode a couple bigger ints, just to show it's little-endian and leading
155 * sign bytes are dropped
156 */
157 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158 {
159 blob.cbData = strlen((const char*)bigInts[i].val);
160 blob.pbData = (BYTE *)bigInts[i].val;
161 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162 0, NULL, NULL, &bufSize);
163 ok(ret, "Expected success, got %d\n", GetLastError());
164 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167 if (ret)
168 {
169 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170 buf[0]);
171 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172 buf[1], bigInts[i].encoded[1]);
173 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174 bigInts[i].encoded[1] + 1),
175 "Encoded value didn't match expected\n");
176 LocalFree(buf);
177 }
178 }
179 /* and, encode some uints */
180 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181 {
182 blob.cbData = strlen((const char*)bigUInts[i].val);
183 blob.pbData = (BYTE*)bigUInts[i].val;
184 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185 0, NULL, NULL, &bufSize);
186 ok(ret, "Expected success, got %d\n", GetLastError());
187 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190 if (ret)
191 {
192 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193 buf[0]);
194 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195 buf[1], bigUInts[i].encoded[1]);
196 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197 bigUInts[i].encoded[1] + 1),
198 "Encoded value didn't match expected\n");
199 LocalFree(buf);
200 }
201 }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210 static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211 BYTE *buf = NULL;
212 DWORD bufSize = 0;
213 int i;
214 BOOL ret;
215
216 /* CryptDecodeObjectEx with NULL bufSize crashes..
217 ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219 */
220 /* check bogus encoding */
221 ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225 /* check with NULL integer buffer */
226 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227 &bufSize);
228 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229 GetLastError() == OSS_BAD_ARG /* Win9x */),
230 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231 /* check with a valid, but too large, integer */
232 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233 CRYPT_DECODE_ALLOC_FLAG, NULL, &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++)
245 {
246 /* When the output buffer is NULL, this always succeeds */
247 SetLastError(0xdeadbeef);
248 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
249 ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
250 &bufSize);
251 ok(ret && GetLastError() == NOERROR,
252 "Expected success and NOERROR, got %d\n", GetLastError());
253 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER,
254 ints[i].encoded, ints[i].encoded[1] + 2,
255 CRYPT_DECODE_ALLOC_FLAG, NULL, &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 (ret)
260 {
261 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262 ints[i].val, *(int *)buf);
263 LocalFree(buf);
264 }
265 }
266 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
267 {
268 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270 &bufSize);
271 ok(ret && GetLastError() == NOERROR,
272 "Expected success and NOERROR, got %d\n", GetLastError());
273 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274 bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275 CRYPT_DECODE_ALLOC_FLAG, NULL, &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 (ret)
280 {
281 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
282
283 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284 "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285 blob->cbData);
286 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287 "Unexpected value\n");
288 LocalFree(buf);
289 }
290 }
291 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
292 {
293 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295 &bufSize);
296 ok(ret && GetLastError() == NOERROR,
297 "Expected success and NOERROR, got %d\n", GetLastError());
298 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300 CRYPT_DECODE_ALLOC_FLAG, NULL, &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 (ret)
305 {
306 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
307
308 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309 "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310 blob->cbData);
311 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312 "Unexpected value\n");
313 LocalFree(buf);
314 }
315 }
316 /* Decode the value 1 with long-form length */
317 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
319 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320 if (ret)
321 {
322 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323 LocalFree(buf);
324 }
325 /* check with extra bytes at the end */
326 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327 sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
328 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329 if (ret)
330 {
331 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332 LocalFree(buf);
333 }
334 /* Try to decode some bogus large items */
335 /* The buffer size is smaller than the encoded length, so this should fail
336 * with CRYPT_E_ASN1_EOD if it's being decoded.
337 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339 * So this test unfortunately isn't useful.
340 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
342 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
343 "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError());
344 */
345 /* This will try to decode the buffer and overflow it, check that it's
346 * caught.
347 */
348 if (0)
349 {
350 /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */
351 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
352 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
353 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
354 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
355 }
356 }
357
358 static const BYTE bin18[] = {0x0a,0x01,0x01};
359 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
360
361 /* These are always encoded unsigned, and aren't constrained to be any
362 * particular value
363 */
364 static const struct encodedInt enums[] = {
365 { 1, bin18 },
366 { -128, bin19 },
367 };
368
369 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
370 * X509_ENUMERATED.
371 */
372 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
373 szOID_CRL_REASON_CODE };
374
375 static void test_encodeEnumerated(DWORD dwEncoding)
376 {
377 DWORD i, j;
378
379 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
380 {
381 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
382 {
383 BOOL ret;
384 BYTE *buf = NULL;
385 DWORD bufSize = 0;
386
387 ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
388 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
389 &bufSize);
390 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
391 if (ret)
392 {
393 ok(buf[0] == 0xa,
394 "Got unexpected type %d for enumerated (expected 0xa)\n",
395 buf[0]);
396 ok(buf[1] == enums[j].encoded[1],
397 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399 enums[j].encoded[1] + 1),
400 "Encoded value of 0x%08x didn't match expected\n",
401 enums[j].val);
402 LocalFree(buf);
403 }
404 }
405 }
406 }
407
408 static void test_decodeEnumerated(DWORD dwEncoding)
409 {
410 DWORD i, j;
411
412 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
413 {
414 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
415 {
416 BOOL ret;
417 DWORD bufSize = sizeof(int);
418 int val;
419
420 ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422 &val, &bufSize);
423 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
424 ok(bufSize == sizeof(int),
425 "Got unexpected size %d for enumerated\n", bufSize);
426 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
427 val, enums[j].val);
428 }
429 }
430 }
431
432 struct encodedFiletime
433 {
434 SYSTEMTIME sysTime;
435 const BYTE *encodedTime;
436 };
437
438 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
439 const struct encodedFiletime *time)
440 {
441 FILETIME ft = { 0 };
442 BYTE *buf = NULL;
443 DWORD bufSize = 0;
444 BOOL ret;
445
446 ret = SystemTimeToFileTime(&time->sysTime, &ft);
447 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
448 ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft,
449 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
450 /* years other than 1950-2050 are not allowed for encodings other than
451 * X509_CHOICE_OF_TIME.
452 */
453 if (structType == X509_CHOICE_OF_TIME ||
454 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
455 {
456 ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
457 GetLastError());
458 ok(buf != NULL, "Expected an allocated buffer\n");
459 if (ret)
460 {
461 ok(buf[0] == time->encodedTime[0],
462 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463 buf[0]);
464 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465 time->encodedTime[1], bufSize);
466 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467 "Got unexpected value for time encoding\n");
468 LocalFree(buf);
469 }
470 }
471 else
472 ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473 broken(GetLastError() == ERROR_SUCCESS),
474 "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
475 }
476
477 static const char *printSystemTime(const SYSTEMTIME *st)
478 {
479 static char buf[25];
480
481 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482 st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483 return buf;
484 }
485
486 static const char *printFileTime(const FILETIME *ft)
487 {
488 static char buf[25];
489 SYSTEMTIME st;
490
491 FileTimeToSystemTime(ft, &st);
492 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493 st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494 return buf;
495 }
496
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
498 {
499 SYSTEMTIME st;
500
501 FileTimeToSystemTime(got, &st);
502 ok((expected->wYear == st.wYear &&
503 expected->wMonth == st.wMonth &&
504 expected->wDay == st.wDay &&
505 expected->wHour == st.wHour &&
506 expected->wMinute == st.wMinute &&
507 expected->wSecond == st.wSecond &&
508 abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509 /* Some Windows systems only seem to be accurate in their time decoding to
510 * within about an hour.
511 */
512 broken(expected->wYear == st.wYear &&
513 expected->wMonth == st.wMonth &&
514 expected->wDay == st.wDay &&
515 abs(expected->wHour - st.wHour) <= 1),
516 "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517 printSystemTime(expected), printFileTime(got));
518 }
519
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521 const struct encodedFiletime *time)
522 {
523 FILETIME ft = { 0 };
524 DWORD size = sizeof(ft);
525 BOOL ret;
526
527 ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528 time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529 /* years other than 1950-2050 are not allowed for encodings other than
530 * X509_CHOICE_OF_TIME.
531 */
532 if (structType == X509_CHOICE_OF_TIME ||
533 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
534 {
535 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536 "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537 GetLastError());
538 if (ret)
539 compareTime(&time->sysTime, &ft);
540 }
541 else
542 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543 GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544 "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545 GetLastError());
546 }
547
548 static const BYTE bin20[] = {
549 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
554
555 static const struct encodedFiletime times[] = {
556 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
559 };
560
561 static void test_encodeFiletime(DWORD dwEncoding)
562 {
563 DWORD i;
564
565 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
566 {
567 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
570 }
571 }
572
573 static const BYTE bin23[] = {
574 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598 0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602 0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604 0x18,0x08, '2','1','4','5','0','6','0','6'};
605
606 static void test_decodeFiletime(DWORD dwEncoding)
607 {
608 static const struct encodedFiletime otherTimes[] = {
609 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
610 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
612 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
613 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
614 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
615 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
616 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
617 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
618 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
619 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
620 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
621 };
622 /* An oddball case that succeeds in Windows, but doesn't seem correct
623 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
624 */
625 static const unsigned char *bogusTimes[] = {
626 /* oddly, this succeeds on Windows, with year 2765
627 "\x18" "\x0f" "21r50606161000Z",
628 */
629 bin35,
630 bin36,
631 bin37,
632 bin38,
633 };
634 DWORD i, size;
635 FILETIME ft1 = { 0 }, ft2 = { 0 };
636 BOOL ret;
637
638 /* Check bogus length with non-NULL buffer */
639 ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641 size = 1;
642 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644 ok(!ret && GetLastError() == ERROR_MORE_DATA,
645 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646 /* Normal tests */
647 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
648 {
649 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
652 }
653 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
654 {
655 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
658 }
659 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
660 {
661 size = sizeof(ft1);
662 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664 ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665 GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666 broken(ret), /* Win9x and NT4 for bin38 */
667 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668 GetLastError());
669 }
670 }
671
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
674
675 static const BYTE emptySequence[] = { 0x30, 0 };
676 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
677 static const BYTE twoRDNs[] = {
678 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
679 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
680 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
681 static const BYTE encodedTwoRDNs[] = {
682 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
683 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
684 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
685 0x6e,0x67,0x00,
686 };
687
688 static const BYTE us[] = { 0x55, 0x53 };
689 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
690 0x74, 0x61 };
691 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
692 0x6f, 0x6c, 0x69, 0x73 };
693 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
694 0x76, 0x65, 0x72, 0x73 };
695 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
696 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
697 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
698 0x73, 0x74 };
699 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
700 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
701
702 #define RDNA(arr) oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
703 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING, { sizeof(arr), (LPBYTE)arr }
704
705 static CHAR oid_us[] = "2.5.4.6",
706 oid_minnesota[] = "2.5.4.8",
707 oid_minneapolis[] = "2.5.4.7",
708 oid_codeweavers[] = "2.5.4.10",
709 oid_wine[] = "2.5.4.11",
710 oid_localhostAttr[] = "2.5.4.3",
711 oid_aric[] = "1.2.840.113549.1.9.1";
712 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
713 { RDNA(minnesota) },
714 { RDNA(minneapolis) },
715 { RDNA(codeweavers) },
716 { RDNA(wine) },
717 { RDNA(localhostAttr) },
718 { RDNIA5(aric) } };
719 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
720 { RDNA(localhostAttr) },
721 { RDNA(minnesota) },
722 { RDNA(minneapolis) },
723 { RDNA(codeweavers) },
724 { RDNA(wine) },
725 { RDNIA5(aric) } };
726
727 #undef RDNIA5
728 #undef RDNA
729
730 static const BYTE encodedRDNAttrs[] = {
731 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
732 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
733 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
734 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
735 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
736 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
737 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
738 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
739 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
740 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
741 };
742
743 static void test_encodeName(DWORD dwEncoding)
744 {
745 CERT_RDN_ATTR attrs[2];
746 CERT_RDN rdn;
747 CERT_NAME_INFO info;
748 static CHAR oid_common_name[] = szOID_COMMON_NAME,
749 oid_sur_name[] = szOID_SUR_NAME;
750 BYTE *buf = NULL;
751 DWORD size = 0;
752 BOOL ret;
753
754 if (0)
755 {
756 /* Test with NULL pvStructInfo (crashes on win9x) */
757 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
758 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
759 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
760 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
761 }
762 /* Test with empty CERT_NAME_INFO */
763 info.cRDN = 0;
764 info.rgRDN = NULL;
765 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
766 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
767 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
768 if (ret)
769 {
770 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771 "Got unexpected encoding for empty name\n");
772 LocalFree(buf);
773 }
774 if (0)
775 {
776 /* Test with bogus CERT_RDN (crashes on win9x) */
777 info.cRDN = 1;
778 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
780 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
781 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
782 }
783 /* Test with empty CERT_RDN */
784 rdn.cRDNAttr = 0;
785 rdn.rgRDNAttr = NULL;
786 info.cRDN = 1;
787 info.rgRDN = &rdn;
788 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
789 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
790 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
791 if (ret)
792 {
793 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794 "Got unexpected encoding for empty RDN array\n");
795 LocalFree(buf);
796 }
797 if (0)
798 {
799 /* Test with bogus attr array (crashes on win9x) */
800 rdn.cRDNAttr = 1;
801 rdn.rgRDNAttr = NULL;
802 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
803 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
804 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
805 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
806 }
807 /* oddly, a bogus OID is accepted by Windows XP; not testing.
808 attrs[0].pszObjId = "bogus";
809 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
810 attrs[0].Value.cbData = sizeof(commonName);
811 attrs[0].Value.pbData = 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");
817 */
818 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
819 * the encoded attributes to be swapped.
820 */
821 attrs[0].pszObjId = oid_common_name;
822 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
823 attrs[0].Value.cbData = sizeof(commonName);
824 attrs[0].Value.pbData = (BYTE *)commonName;
825 attrs[1].pszObjId = oid_sur_name;
826 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
827 attrs[1].Value.cbData = sizeof(surName);
828 attrs[1].Value.pbData = (BYTE *)surName;
829 rdn.cRDNAttr = 2;
830 rdn.rgRDNAttr = attrs;
831 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
832 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
833 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
834 if (ret)
835 {
836 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837 "Got unexpected encoding for two RDN array\n");
838 LocalFree(buf);
839 }
840 /* A name can be "encoded" with previously encoded RDN attrs. */
841 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
842 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
843 attrs[0].Value.cbData = sizeof(twoRDNs);
844 rdn.cRDNAttr = 1;
845 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
846 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
847 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
848 if (ret)
849 {
850 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851 ok(!memcmp(buf, encodedTwoRDNs, size),
852 "Unexpected value for re-endoded two RDN array\n");
853 LocalFree(buf);
854 }
855 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
856 rdn.cRDNAttr = 1;
857 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
858 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
859 CRYPT_ENCODE_ALLOC_FLAG, NULL, &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)
873 {
874 ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size);
875 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
876 LocalFree(buf);
877 }
878 }
879
880 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 };
881 static WCHAR surNameW[] = { 'L','a','n','g',0 };
882
883 static const BYTE twoRDNsNoNull[] = {
884 0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61,
885 0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,
886 0x20,0x4c,0x61,0x6e,0x67 };
887 static const BYTE anyType[] = {
888 0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30,
889 0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00,
890 0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e,
891 0x61,0x4c,0x67,0x6e };
892
893 static void test_encodeUnicodeName(DWORD dwEncoding)
894 {
895 CERT_RDN_ATTR attrs[2];
896 CERT_RDN rdn;
897 CERT_NAME_INFO info;
898 static CHAR oid_common_name[] = szOID_COMMON_NAME,
899 oid_sur_name[] = szOID_SUR_NAME;
900 BYTE *buf = NULL;
901 DWORD size = 0;
902 BOOL ret;
903
904 if (0)
905 {
906 /* Test with NULL pvStructInfo (crashes on win9x) */
907 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL,
908 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
909 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
910 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
911 }
912 /* Test with empty CERT_NAME_INFO */
913 info.cRDN = 0;
914 info.rgRDN = NULL;
915 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
916 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
917 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
918 if (ret)
919 {
920 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921 "Got unexpected encoding for empty name\n");
922 LocalFree(buf);
923 }
924 /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925 * encoding (the NULL).
926 */
927 attrs[0].pszObjId = oid_common_name;
928 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
929 attrs[0].Value.cbData = sizeof(commonNameW);
930 attrs[0].Value.pbData = (BYTE *)commonNameW;
931 rdn.cRDNAttr = 1;
932 rdn.rgRDNAttr = attrs;
933 info.cRDN = 1;
934 info.rgRDN = &rdn;
935 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
937 ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING,
938 "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError());
939 ok(size == 9, "Unexpected error index %08x\n", size);
940 /* Check with two NULL-terminated CERT_RDN_ATTRs. Note DER encoding
941 * forces the order of the encoded attributes to be swapped.
942 */
943 attrs[0].pszObjId = oid_common_name;
944 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
945 attrs[0].Value.cbData = 0;
946 attrs[0].Value.pbData = (BYTE *)commonNameW;
947 attrs[1].pszObjId = oid_sur_name;
948 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
949 attrs[1].Value.cbData = 0;
950 attrs[1].Value.pbData = (BYTE *)surNameW;
951 rdn.cRDNAttr = 2;
952 rdn.rgRDNAttr = attrs;
953 info.cRDN = 1;
954 info.rgRDN = &rdn;
955 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
956 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
957 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
958 if (ret)
959 {
960 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961 "Got unexpected encoding for two RDN array\n");
962 LocalFree(buf);
963 }
964 /* A name can be "encoded" with previously encoded RDN attrs. */
965 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
966 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
967 attrs[0].Value.cbData = sizeof(twoRDNs);
968 rdn.cRDNAttr = 1;
969 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
970 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
971 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
972 if (ret)
973 {
974 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975 ok(!memcmp(buf, encodedTwoRDNs, size),
976 "Unexpected value for re-endoded two RDN array\n");
977 LocalFree(buf);
978 }
979 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980 rdn.cRDNAttr = 1;
981 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
984 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985 if (ret)
986 {
987 ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988 ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989 LocalFree(buf);
990 }
991 }
992
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994 const CERT_NAME_VALUE *got)
995 {
996 if (expected->dwValueType == CERT_RDN_UTF8_STRING &&
997 got->dwValueType == CERT_RDN_ENCODED_BLOB)
998 {
999 win_skip("Can't handle CERT_RDN_UTF8_STRING\n");
1000 return;
1001 }
1002
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);
1013 }
1014
1015 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
1016 const CERT_RDN_ATTR *got)
1017 {
1018 if (expected->pszObjId && strlen(expected->pszObjId))
1019 {
1020 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
1021 expected->pszObjId);
1022 if (got->pszObjId)
1023 {
1024 ok(!strcmp(got->pszObjId, expected->pszObjId),
1025 "Got unexpected OID %s, expected %s\n", got->pszObjId,
1026 expected->pszObjId);
1027 }
1028 }
1029 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType,
1030 (const CERT_NAME_VALUE *)&got->dwValueType);
1031 }
1032
1033 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
1034 {
1035 ok(got->cRDNAttr == expected->cRDNAttr,
1036 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr);
1037 if (got->cRDNAttr)
1038 {
1039 DWORD i;
1040
1041 for (i = 0; i < got->cRDNAttr; i++)
1042 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
1043 }
1044 }
1045
1046 static void compareNames(const CERT_NAME_INFO *expected,
1047 const CERT_NAME_INFO *got)
1048 {
1049 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n",
1050 expected->cRDN, got->cRDN);
1051 if (got->cRDN)
1052 {
1053 DWORD i;
1054
1055 for (i = 0; i < got->cRDN; i++)
1056 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
1057 }
1058 }
1059
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};
1065
1066 static void test_decodeName(DWORD dwEncoding)
1067 {
1068 BYTE *buf = NULL;
1069 DWORD bufSize = 0;
1070 BOOL ret;
1071 CERT_RDN rdn;
1072 CERT_NAME_INFO info = { 1, &rdn };
1073
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.
1083 */
1084 if (ret)
1085 {
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);
1091 }
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)
1098 {
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);
1104 }
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 (ret)
1113 {
1114 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1115
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);
1120 }
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 (ret)
1129 {
1130 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1131 oid_common_name[] = szOID_COMMON_NAME;
1132
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 } },
1138 };
1139
1140 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1141 rdn.rgRDNAttr = attrs;
1142 compareNames(&info, (CERT_NAME_INFO *)buf);
1143 LocalFree(buf);
1144 }
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)
1157 {
1158 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
1159 rdn.rgRDNAttr = decodedRdnAttrs;
1160 compareNames(&info, (CERT_NAME_INFO *)buf);
1161 LocalFree(buf);
1162 }
1163 }
1164
1165 static void test_decodeUnicodeName(DWORD dwEncoding)
1166 {
1167 BYTE *buf = NULL;
1168 DWORD bufSize = 0;
1169 BOOL ret;
1170 CERT_RDN rdn;
1171 CERT_NAME_INFO info = { 1, &rdn };
1172
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 (ret)
1181 {
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);
1188 }
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 (ret)
1197 {
1198 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
1199
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);
1204 }
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 (ret)
1213 {
1214 static CHAR oid_sur_name[] = szOID_SUR_NAME,
1215 oid_common_name[] = szOID_COMMON_NAME;
1216
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 } },
1222 };
1223
1224 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
1225 rdn.rgRDNAttr = attrs;
1226 compareNames(&info, (CERT_NAME_INFO *)buf);
1227 LocalFree(buf);
1228 }
1229 }
1230
1231 struct EncodedNameValue
1232 {
1233 CERT_NAME_VALUE value;
1234 const BYTE *encoded;
1235 DWORD encodedSize;
1236 };
1237
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 };
1267 static char embedded_null[] = "foo\0com";
1268 static BYTE ia5EmbeddedNull[] = {
1269 0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d };
1270
1271 static struct EncodedNameValue nameValues[] = {
1272 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } },
1273 octetCommonNameValue, sizeof(octetCommonNameValue) },
1274 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1275 numericCommonNameValue, sizeof(numericCommonNameValue) },
1276 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1277 printableCommonNameValue, sizeof(printableCommonNameValue) },
1278 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } },
1279 t61CommonNameValue, sizeof(t61CommonNameValue) },
1280 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } },
1281 videotexCommonNameValue, sizeof(videotexCommonNameValue) },
1282 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } },
1283 ia5CommonNameValue, sizeof(ia5CommonNameValue) },
1284 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } },
1285 graphicCommonNameValue, sizeof(graphicCommonNameValue) },
1286 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } },
1287 visibleCommonNameValue, sizeof(visibleCommonNameValue) },
1288 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } },
1289 generalCommonNameValue, sizeof(generalCommonNameValue) },
1290 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1291 bmpCommonNameValue, sizeof(bmpCommonNameValue) },
1292 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } },
1293 utf8CommonNameValue, sizeof(utf8CommonNameValue) },
1294 /* The following tests succeed under Windows, but really should fail,
1295 * they contain characters that are illegal for the encoding. I'm
1296 * including them to justify my lazy encoding.
1297 */
1298 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42,
1299 sizeof(bin42) },
1300 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable),
1301 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) },
1302 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } },
1303 bin44, sizeof(bin44) },
1304 };
1305 /* This is kept separate, because the decoding doesn't return to the original
1306 * value.
1307 */
1308 static struct EncodedNameValue embeddedNullNameValue = {
1309 { CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } },
1310 ia5EmbeddedNull, sizeof(ia5EmbeddedNull) };
1311
1312 static void test_encodeNameValue(DWORD dwEncoding)
1313 {
1314 BYTE *buf = NULL;
1315 DWORD size = 0, i;
1316 BOOL ret;
1317 CERT_NAME_VALUE value = { 0, { 0, NULL } };
1318
1319 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1320 value.Value.pbData = printableCommonNameValue;
1321 value.Value.cbData = sizeof(printableCommonNameValue);
1322 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value,
1323 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1324 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1325 if (ret)
1326 {
1327 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n",
1328 size);
1329 ok(!memcmp(buf, printableCommonNameValue, size),
1330 "Unexpected encoding\n");
1331 LocalFree(buf);
1332 }
1333 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1334 {
1335 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1336 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1337 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1338 "Type %d: CryptEncodeObjectEx failed: %08x\n",
1339 nameValues[i].value.dwValueType, GetLastError());
1340 if (ret)
1341 {
1342 ok(size == nameValues[i].encodedSize,
1343 "Expected size %d, got %d\n", nameValues[i].encodedSize, size);
1344 ok(!memcmp(buf, nameValues[i].encoded, size),
1345 "Got unexpected encoding\n");
1346 LocalFree(buf);
1347 }
1348 }
1349 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE,
1350 &embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1351 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */,
1352 "Type %d: CryptEncodeObjectEx failed: %08x\n",
1353 embeddedNullNameValue.value.dwValueType, GetLastError());
1354 if (ret)
1355 {
1356 ok(size == embeddedNullNameValue.encodedSize,
1357 "Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size);
1358 ok(!memcmp(buf, embeddedNullNameValue.encoded, size),
1359 "Got unexpected encoding\n");
1360 LocalFree(buf);
1361 }
1362 }
1363
1364 static void test_decodeNameValue(DWORD dwEncoding)
1365 {
1366 int i;
1367 BYTE *buf = NULL;
1368 DWORD bufSize = 0;
1369 BOOL ret;
1370
1371 for (i = 0; i < sizeof(nameValues) / sizeof(nameValues[0]); i++)
1372 {
1373 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1374 nameValues[i].encoded, nameValues[i].encoded[1] + 2,
1375 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1376 &buf, &bufSize);
1377 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n",
1378 nameValues[i].value.dwValueType, GetLastError());
1379 if (ret)
1380 {
1381 compareNameValues(&nameValues[i].value,
1382 (const CERT_NAME_VALUE *)buf);
1383 LocalFree(buf);
1384 }
1385 }
1386 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE,
1387 embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize,
1388 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
1389 &buf, &bufSize);
1390 /* Some Windows versions disallow name values with embedded NULLs, so
1391 * either success or failure is acceptable.
1392 */
1393 if (ret)
1394 {
1395 CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB,
1396 { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } };
1397 CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING,
1398 { sizeof(embedded_null) - 1, (BYTE *)embedded_null } };
1399 const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf,
1400 *expected = NULL;
1401
1402 /* Some Windows versions decode name values with embedded NULLs,
1403 * others leave them encoded, even with the same version of crypt32.
1404 * Accept either.
1405 */
1406 ok(got->dwValueType == CERT_RDN_ENCODED_BLOB ||
1407 got->dwValueType == CERT_RDN_IA5_STRING,
1408 "Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n",
1409 got->dwValueType);
1410 if (got->dwValueType == CERT_RDN_ENCODED_BLOB)
1411 expected = &rdnEncodedValue;
1412 else if (got->dwValueType == CERT_RDN_IA5_STRING)
1413 expected = &embeddedNullValue;
1414 if (expected)
1415 {
1416 ok(got->Value.cbData == expected->Value.cbData,
1417 "String type %d: unexpected data size, got %d, expected %d\n",
1418 got->dwValueType, got->Value.cbData, expected->Value.cbData);
1419 if (got->Value.cbData && got->Value.pbData)
1420 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
1421 min(got->Value.cbData, expected->Value.cbData)),
1422 "String type %d: unexpected value\n", expected->dwValueType);
1423 }
1424 LocalFree(buf);
1425 }
1426 }
1427
1428 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
1429 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 };
1430 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
1431 'h','q','.','o','r','g',0 };
1432 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
1433 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
1434 0x6f, 0x72, 0x67 };
1435 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1436 0x575b, 0 };
1437 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1438 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1439 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1440 static const BYTE localhost[] = { 127, 0, 0, 1 };
1441 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1442 0x01 };
1443 static const unsigned char encodedCommonName[] = {
1444 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
1445 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 };
1446 static const BYTE encodedDirectoryName[] = {
1447 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
1448 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 };
1449
1450 static void test_encodeAltName(DWORD dwEncoding)
1451 {
1452 CERT_ALT_NAME_INFO info = { 0 };
1453 CERT_ALT_NAME_ENTRY entry = { 0 };
1454 BYTE *buf = NULL;
1455 DWORD size = 0;
1456 BOOL ret;
1457 char oid[] = "1.2.3";
1458
1459 /* Test with empty info */
1460 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1461 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1462 if (ret)
1463 {
1464 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
1465 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1466 LocalFree(buf);
1467 }
1468 /* Test with an empty entry */
1469 info.cAltEntry = 1;
1470 info.rgAltEntry = &entry;
1471 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1472 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1473 ok(!ret && GetLastError() == E_INVALIDARG,
1474 "Expected E_INVALIDARG, got %08x\n", GetLastError());
1475 /* Test with an empty pointer */
1476 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1477 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1478 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1479 if (ret)
1480 {
1481 ok(size == sizeof(emptyURL), "Wrong size %d\n", size);
1482 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1483 LocalFree(buf);
1484 }
1485 /* Test with a real URL */
1486 U(entry).pwszURL = (LPWSTR)url;
1487 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1488 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1489 if (ret)
1490 {
1491 ok(size == sizeof(encodedURL), "Wrong size %d\n", size);
1492 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1493 LocalFree(buf);
1494 }
1495 /* Now with the URL containing an invalid IA5 char */
1496 U(entry).pwszURL = (LPWSTR)nihongoURL;
1497 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1498 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1499 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1500 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
1501 /* The first invalid character is at index 7 */
1502 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1503 "Expected invalid char at index 7, got %d\n",
1504 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1505 /* Now with the URL missing a scheme */
1506 U(entry).pwszURL = (LPWSTR)dnsName;
1507 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1508 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1509 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1510 if (ret)
1511 {
1512 /* This succeeds, but it shouldn't, so don't worry about conforming */
1513 LocalFree(buf);
1514 }
1515 /* Now with a DNS name */
1516 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1517 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1518 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1519 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1520 if (ret)
1521 {
1522 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size);
1523 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1524 LocalFree(buf);
1525 }
1526 /* Test with an IP address */
1527 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1528 U(entry).IPAddress.cbData = sizeof(localhost);
1529 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1530 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1531 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1532 if (ret)
1533 {
1534 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size);
1535 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1536 LocalFree(buf);
1537 }
1538 /* Test with OID */
1539 entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID;
1540 U(entry).pszRegisteredID = oid;
1541 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1542 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1543 if (ret)
1544 {
1545 ok(size == sizeof(encodedOidName), "Wrong size %d\n", size);
1546 ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n");
1547 LocalFree(buf);
1548 }
1549 /* Test with directory name */
1550 entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME;
1551 U(entry).DirectoryName.cbData = sizeof(encodedCommonName);
1552 U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName;
1553 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1554 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1555 if (ret)
1556 {
1557 ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size);
1558 ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n");
1559 LocalFree(buf);
1560 }
1561 }
1562
1563 static void test_decodeAltName(DWORD dwEncoding)
1564 {
1565 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1566 0x00, 0x00, 0x01 };
1567 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1568 0x01 };
1569 static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1570 0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1571 static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f,
1572 0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 };
1573 static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f,
1574 0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 };
1575 BOOL ret;
1576 BYTE *buf = NULL;
1577 DWORD bufSize = 0;
1578 CERT_ALT_NAME_INFO *info;
1579
1580 /* Test some bogus ones first */
1581 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1582 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1583 NULL, &buf, &bufSize);
1584 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
1585 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1586 "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
1587 GetLastError());
1588 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1589 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
1590 &bufSize);
1591 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
1592 GetLastError() == OSS_DATA_ERROR /* Win9x */),
1593 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
1594 GetLastError());
1595 /* Now expected cases */
1596 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1597 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1598 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1599 if (ret)
1600 {
1601 info = (CERT_ALT_NAME_INFO *)buf;
1602
1603 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n",
1604 info->cAltEntry);
1605 LocalFree(buf);
1606 }
1607 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1608 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1609 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1610 if (ret)
1611 {
1612 info = (CERT_ALT_NAME_INFO *)buf;
1613
1614 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1615 info->cAltEntry);
1616 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1617 "Expected CERT_ALT_NAME_URL, got %d\n",
1618 info->rgAltEntry[0].dwAltNameChoice);
1619 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1620 "Expected empty URL\n");
1621 LocalFree(buf);
1622 }
1623 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1624 emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize);
1625 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1626 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1627 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1628 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1629 if (ret)
1630 {
1631 info = (CERT_ALT_NAME_INFO *)buf;
1632
1633 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1634 info->cAltEntry);
1635 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1636 "Expected CERT_ALT_NAME_URL, got %d\n",
1637 info->rgAltEntry[0].dwAltNameChoice);
1638 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1639 LocalFree(buf);
1640 }
1641 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1642 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1643 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1644 if (ret)
1645 {
1646 info = (CERT_ALT_NAME_INFO *)buf;
1647
1648 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1649 info->cAltEntry);
1650 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1651 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1652 info->rgAltEntry[0].dwAltNameChoice);
1653 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1654 "Unexpected DNS name\n");
1655 LocalFree(buf);
1656 }
1657 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1658 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1659 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1660 if (ret)
1661 {
1662 info = (CERT_ALT_NAME_INFO *)buf;
1663
1664 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1665 info->cAltEntry);
1666 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1667 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n",
1668 info->rgAltEntry[0].dwAltNameChoice);
1669 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1670 "Unexpected IP address length %d\n",
1671 U(info->rgAltEntry[0]).IPAddress.cbData);
1672 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1673 sizeof(localhost)), "Unexpected IP address value\n");
1674 LocalFree(buf);
1675 }
1676 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName,
1677 sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1678 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1679 if (ret)
1680 {
1681 info = (CERT_ALT_NAME_INFO *)buf;
1682
1683 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1684 info->cAltEntry);
1685 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID,
1686 "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n",
1687 info->rgAltEntry[0].dwAltNameChoice);
1688 ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"),
1689 "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID);
1690 LocalFree(buf);
1691 }
1692 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1693 encodedDirectoryName, sizeof(encodedDirectoryName),
1694 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1695 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1696 if (ret)
1697 {
1698 info = (CERT_ALT_NAME_INFO *)buf;
1699
1700 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1701 info->cAltEntry);
1702 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME,
1703 "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n",
1704 info->rgAltEntry[0].dwAltNameChoice);
1705 ok(U(info->rgAltEntry[0]).DirectoryName.cbData ==
1706 sizeof(encodedCommonName), "Unexpected directory name length %d\n",
1707 U(info->rgAltEntry[0]).DirectoryName.cbData);
1708 ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData,
1709 encodedCommonName, sizeof(encodedCommonName)),
1710 "Unexpected directory name value\n");
1711 LocalFree(buf);
1712 }
1713 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1714 dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1715 NULL, &buf, &bufSize);
1716 /* Fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned about the
1717 * particular failure, just that it doesn't decode.
1718 * It succeeds on (broken) Windows versions that haven't addressed
1719 * embedded NULLs in alternate names.
1720 */
1721 ok(!ret || broken(ret), "expected failure\n");
1722 /* An embedded bell character is allowed, however. */
1723 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1724 dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG,
1725 NULL, &buf, &bufSize);
1726 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1727 if (ret)
1728 {
1729 info = (CERT_ALT_NAME_INFO *)buf;
1730
1731 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n",
1732 info->cAltEntry);
1733 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1734 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n",
1735 info->rgAltEntry[0].dwAltNameChoice);
1736 LocalFree(buf);
1737 }
1738 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1739 url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG,
1740 NULL, &buf, &bufSize);
1741 /* Again, fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned
1742 * about the particular failure, just that it doesn't decode.
1743 * It succeeds on (broken) Windows versions that haven't addressed
1744 * embedded NULLs in alternate names.
1745 */
1746 ok(!ret || broken(ret), "expected failure\n");
1747 }
1748
1749 struct UnicodeExpectedError
1750 {
1751 DWORD valueType;
1752 LPCWSTR str;
1753 DWORD errorIndex;
1754 DWORD error;
1755 };
1756
1757 static const WCHAR oneW[] = { '1',0 };
1758 static const WCHAR aW[] = { 'a',0 };
1759 static const WCHAR quoteW[] = { '"', 0 };
1760
1761 static struct UnicodeExpectedError unicodeErrors[] = {
1762 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1763 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1764 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING },
1765 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING },
1766 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING },
1767 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING },
1768 };
1769
1770 struct UnicodeExpectedResult
1771 {
1772 DWORD valueType;
1773 LPCWSTR str;
1774 CRYPT_DATA_BLOB encoded;
1775 };
1776
1777 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 };
1778 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 };
1779 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 };
1780 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 };
1781 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 };
1782 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 };
1783 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 };
1784 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 };
1785 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 };
1786 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 };
1787 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 };
1788 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f,
1789 0x5b };
1790 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1791 0x6f,0x5b };
1792 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70,
1793 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b };
1794 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
1795 0xe2,0x89,0xaf,0xe5,0x9d,0x9b };
1796
1797 static struct UnicodeExpectedResult unicodeResults[] = {
1798 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } },
1799 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } },
1800 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } },
1801 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } },
1802 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } },
1803 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } },
1804 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } },
1805 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } },
1806 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } },
1807 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } },
1808 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } },
1809 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } },
1810 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } },
1811 };
1812
1813 static struct UnicodeExpectedResult unicodeWeirdness[] = {
1814 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } },
1815 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } },
1816 };
1817
1818 static void test_encodeUnicodeNameValue(DWORD dwEncoding)
1819 {
1820 BYTE *buf = NULL;
1821 DWORD size = 0, i;
1822 BOOL ret;
1823 CERT_NAME_VALUE value;
1824
1825 if (0)
1826 {
1827 /* Crashes on win9x */
1828 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL,
1829 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1830 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
1831 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
1832 }
1833 /* Have to have a string of some sort */
1834 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */
1835 value.Value.pbData = NULL;
1836 value.Value.cbData = 0;
1837 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1838 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1839 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1840 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1841 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1842 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1843 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1844 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1845 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1846 value.dwValueType = CERT_RDN_ANY_TYPE;
1847 value.Value.pbData = (LPBYTE)oneW;
1848 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1849 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1850 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1851 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1852 value.Value.cbData = sizeof(oneW);
1853 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1854 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1855 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1856 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1857 /* An encoded string with specified length isn't good enough either */
1858 value.dwValueType = CERT_RDN_ENCODED_BLOB;
1859 value.Value.pbData = oneUniversal;
1860 value.Value.cbData = sizeof(oneUniversal);
1861 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1862 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1863 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING,
1864 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError());
1865 /* More failure checking */
1866 value.Value.cbData = 0;
1867 for (i = 0; i < sizeof(unicodeErrors) / sizeof(unicodeErrors[0]); i++)
1868 {
1869 value.Value.pbData = (LPBYTE)unicodeErrors[i].str;
1870 value.dwValueType = unicodeErrors[i].valueType;
1871 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1872 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1873 ok(!ret && GetLastError() == unicodeErrors[i].error,
1874 "Value type %d: expected %08x, got %08x\n", value.dwValueType,
1875 unicodeErrors[i].error, GetLastError());
1876 ok(size == unicodeErrors[i].errorIndex,
1877 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex,
1878 size);
1879 }
1880 /* cbData can be zero if the string is NULL-terminated */
1881 value.Value.cbData = 0;
1882 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1883 {
1884 value.Value.pbData = (LPBYTE)unicodeResults[i].str;
1885 value.dwValueType = unicodeResults[i].valueType;
1886 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1887 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1888 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */),
1889 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1890 if (ret)
1891 {
1892 ok(size == unicodeResults[i].encoded.cbData,
1893 "Value type %d: expected size %d, got %d\n",
1894 value.dwValueType, unicodeResults[i].encoded.cbData, size);
1895 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size),
1896 "Value type %d: unexpected value\n", value.dwValueType);
1897 LocalFree(buf);
1898 }
1899 }
1900 /* These "encode," but they do so by truncating each unicode character
1901 * rather than properly encoding it. Kept separate from the proper results,
1902 * because the encoded forms won't decode to their original strings.
1903 */
1904 for (i = 0; i < sizeof(unicodeWeirdness) / sizeof(unicodeWeirdness[0]); i++)
1905 {
1906 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str;
1907 value.dwValueType = unicodeWeirdness[i].valueType;
1908 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value,
1909 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
1910 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
1911 if (ret)
1912 {
1913 ok(size == unicodeWeirdness[i].encoded.cbData,
1914 "Value type %d: expected size %d, got %d\n",
1915 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size);
1916 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size),
1917 "Value type %d: unexpected value\n", value.dwValueType);
1918 LocalFree(buf);
1919 }
1920 }
1921 }
1922
1923 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n )
1924 {
1925 if (n <= 0) return 0;
1926 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; }
1927 return *str1 - *str2;
1928 }
1929
1930 static void test_decodeUnicodeNameValue(DWORD dwEncoding)
1931 {
1932 DWORD i;
1933
1934 for (i = 0; i < sizeof(unicodeResults) / sizeof(unicodeResults[0]); i++)
1935 {
1936 BYTE *buf = NULL;
1937 BOOL ret;
1938 DWORD size = 0;
1939
1940 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE,
1941 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData,
1942 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
1943 ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */),
1944 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
1945 if (ret && buf)
1946 {
1947 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf;
1948
1949 ok(value->dwValueType == unicodeResults[i].valueType,
1950 "Expected value type %d, got %d\n", unicodeResults[i].valueType,
1951 value->dwValueType);
1952 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str,
1953 value->Value.cbData / sizeof(WCHAR)),
1954 "Unexpected decoded value for index %d (value type %d)\n", i,
1955 unicodeResults[i].valueType);
1956 LocalFree(buf);
1957 }
1958 }
1959 }
1960
1961 struct encodedOctets
1962 {
1963 const BYTE *val;
1964 const BYTE *encoded;
1965 };
1966
1967 static const unsigned char bin46[] = { 'h','i',0 };
1968 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1969 static const unsigned char bin48[] = {
1970 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1971 static const unsigned char bin49[] = {
1972 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1973 static const unsigned char bin50[] = { 0 };
1974 static const unsigned char bin51[] = { 0x04,0x00,0 };
1975
1976 static const struct encodedOctets octets[] = {
1977 { bin46, bin47 },
1978 { bin48, bin49 },
1979 { bin50, bin51 },
1980 };
1981
1982 static void test_encodeOctets(DWORD dwEncoding)
1983 {
1984 CRYPT_DATA_BLOB blob;
1985 DWORD i;
1986
1987 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1988 {
1989 BYTE *buf = NULL;
1990 BOOL ret;
1991 DWORD bufSize = 0;
1992
1993 blob.cbData = strlen((const char*)octets[i].val);
1994 blob.pbData = (BYTE*)octets[i].val;
1995 ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1996 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1997 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
1998 if (ret)
1999 {
2000 ok(buf[0] == 4,
2001 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
2002 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
2003 buf[1], octets[i].encoded[1]);
2004 ok(!memcmp(buf + 1, octets[i].encoded + 1,
2005 octets[i].encoded[1] + 1), "Got unexpected value\n");
2006 LocalFree(buf);
2007 }
2008 }
2009 }
2010
2011 static void test_decodeOctets(DWORD dwEncoding)
2012 {
2013 DWORD i;
2014
2015 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
2016 {
2017 BYTE *buf = NULL;
2018 BOOL ret;
2019 DWORD bufSize = 0;
2020
2021 ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
2022 octets[i].encoded, octets[i].encoded[1] + 2,
2023 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2024 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2025 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
2026 "Expected size >= %d, got %d\n",
2027 (int)sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
2028 ok(buf != NULL, "Expected allocated buffer\n");
2029 if (ret)
2030 {
2031 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
2032
2033 if (blob->cbData)
2034 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
2035 "Unexpected value\n");
2036 LocalFree(buf);
2037 }
2038 }
2039 }
2040
2041 static const BYTE bytesToEncode[] = { 0xff, 0xff };
2042
2043 struct encodedBits
2044 {
2045 DWORD cUnusedBits;
2046 const BYTE *encoded;
2047 DWORD cbDecoded;
2048 const BYTE *decoded;
2049 };
2050
2051 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
2052 static const unsigned char bin53[] = { 0xff,0xff };
2053 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
2054 static const unsigned char bin55[] = { 0xff,0xfe };
2055 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
2056 static const unsigned char bin57[] = { 0xfe };
2057 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
2058
2059 static const struct encodedBits bits[] = {
2060 /* normal test cases */
2061 { 0, bin52, 2, bin53 },
2062 { 1, bin54, 2, bin55 },
2063 /* strange test case, showing cUnusedBits >= 8 is allowed */
2064 { 9, bin56, 1, bin57 },
2065 };
2066
2067 static void test_encodeBits(DWORD dwEncoding)
2068 {
2069 DWORD i;
2070
2071 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2072 {
2073 CRYPT_BIT_BLOB blob;
2074 BOOL ret;
2075 BYTE *buf = NULL;
2076 DWORD bufSize = 0;
2077
2078 blob.cbData = sizeof(bytesToEncode);
2079 blob.pbData = (BYTE *)bytesToEncode;
2080 blob.cUnusedBits = bits[i].cUnusedBits;
2081 ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
2082 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2083 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2084 if (ret)
2085 {
2086 ok(bufSize == bits[i].encoded[1] + 2,
2087 "%d: Got unexpected size %d, expected %d\n", i, bufSize,
2088 bits[i].encoded[1] + 2);
2089 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
2090 "%d: Unexpected value\n", i);
2091 LocalFree(buf);
2092 }
2093 }
2094 }
2095
2096 static void test_decodeBits(DWORD dwEncoding)
2097 {
2098 static const BYTE ber[] = "\x03\x02\x01\xff";
2099 static const BYTE berDecoded = 0xfe;
2100 DWORD i;
2101 BOOL ret;
2102 BYTE *buf = NULL;
2103 DWORD bufSize = 0;
2104
2105 /* normal cases */
2106 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
2107 {
2108 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
2109 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2110 &bufSize);
2111 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2112 if (ret)
2113 {
2114 CRYPT_BIT_BLOB *blob;
2115
2116 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
2117 "Got unexpected size %d\n", bufSize);
2118 blob = (CRYPT_BIT_BLOB *)buf;
2119 ok(blob->cbData == bits[i].cbDecoded,
2120 "Got unexpected length %d, expected %d\n", blob->cbData,
2121 bits[i].cbDecoded);
2122 if (blob->cbData && bits[i].cbDecoded)
2123 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
2124 "Unexpected value\n");
2125 LocalFree(buf);
2126 }
2127 }
2128 /* special case: check that something that's valid in BER but not in DER
2129 * decodes successfully
2130 */
2131 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
2132 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2133 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2134 if (ret)
2135 {
2136 CRYPT_BIT_BLOB *blob;
2137
2138 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
2139 "Got unexpected size %d\n", bufSize);
2140 blob = (CRYPT_BIT_BLOB *)buf;
2141 ok(blob->cbData == sizeof(berDecoded),
2142 "Got unexpected length %d\n", blob->cbData);
2143 if (blob->cbData)
2144 ok(*blob->pbData == berDecoded, "Unexpected value\n");
2145 LocalFree(buf);
2146 }
2147 }
2148
2149 struct Constraints2
2150 {
2151 CERT_BASIC_CONSTRAINTS2_INFO info;
2152 const BYTE *encoded;
2153 };
2154
2155 static const unsigned char bin59[] = { 0x30,0x00 };
2156 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
2157 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
2158 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2159 static const struct Constraints2 constraints2[] = {
2160 /* empty constraints */
2161 { { FALSE, FALSE, 0}, bin59 },
2162 /* can be a CA */
2163 { { TRUE, FALSE, 0}, bin60 },
2164 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
2165 * but that's not the case
2166 */
2167 { { FALSE, TRUE, 0}, bin61 },
2168 /* can be a CA and has path length constraints set */
2169 { { TRUE, TRUE, 1}, bin62 },
2170 };
2171
2172 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
2173 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
2174 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
2175 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
2176 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2177 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
2178 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
2179 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
2180 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
2181 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
2182
2183 static void test_encodeBasicConstraints(DWORD dwEncoding)
2184 {
2185 DWORD i, bufSize = 0;
2186 CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } };
2187 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
2188 (LPBYTE)encodedDomainName };
2189 BOOL ret;
2190 BYTE *buf = NULL;
2191
2192 /* First test with the simpler info2 */
2193 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2194 {
2195 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2196 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2197 &bufSize);
2198 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2199 if (ret)
2200 {
2201 ok(bufSize == constraints2[i].encoded[1] + 2,
2202 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2,
2203 bufSize);
2204 ok(!memcmp(buf, constraints2[i].encoded,
2205 constraints2[i].encoded[1] + 2), "Unexpected value\n");
2206 LocalFree(buf);
2207 }
2208 }
2209 /* Now test with more complex basic constraints */
2210 info.SubjectType.cbData = 0;
2211 info.fPathLenConstraint = FALSE;
2212 info.cSubtreesConstraint = 0;
2213 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2214 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2215 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2216 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2217 if (ret)
2218 {
2219 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize);
2220 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
2221 "Unexpected value\n");
2222 LocalFree(buf);
2223 }
2224 /* None of the certs I examined had any subtree constraint, but I test one
2225 * anyway just in case.
2226 */
2227 info.cSubtreesConstraint = 1;
2228 info.rgSubtreesConstraint = &nameBlob;
2229 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
2230 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2231 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2232 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2233 if (ret)
2234 {
2235 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize);
2236 ok(!memcmp(buf, constraintWithDomainName,
2237 sizeof(constraintWithDomainName)), "Unexpected value\n");
2238 LocalFree(buf);
2239 }
2240 /* FIXME: test encoding with subject type. */
2241 }
2242
2243 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
2244
2245 static void test_decodeBasicConstraints(DWORD dwEncoding)
2246 {
2247 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
2248 0xff };
2249 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
2250 DWORD i;
2251 BOOL ret;
2252 BYTE *buf = NULL;
2253 DWORD bufSize = 0;
2254
2255 /* First test with simpler info2 */
2256 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
2257 {
2258 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2259 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
2260 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2261 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i,
2262 GetLastError());
2263 if (ret)
2264 {
2265 CERT_BASIC_CONSTRAINTS2_INFO *info =
2266 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2267
2268 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
2269 "Unexpected value for item %d\n", i);
2270 LocalFree(buf);
2271 }
2272 }
2273 /* Check with the order of encoded elements inverted */
2274 buf = (PBYTE)1;
2275 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2276 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2277 &bufSize);
2278 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2279 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2280 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2281 GetLastError());
2282 ok(!buf, "Expected buf to be set to NULL\n");
2283 /* Check with a non-DER bool */
2284 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2285 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2286 &buf, &bufSize);
2287 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2288 if (ret)
2289 {
2290 CERT_BASIC_CONSTRAINTS2_INFO *info =
2291 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
2292
2293 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
2294 LocalFree(buf);
2295 }
2296 /* Check with a non-basic constraints value */
2297 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
2298 encodedCommonName, encodedCommonName[1] + 2,
2299 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2300 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2301 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2302 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2303 GetLastError());
2304 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
2305 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2306 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
2307 &buf, &bufSize);
2308 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2309 if (ret)
2310 {
2311 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2312
2313 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2314 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2315 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
2316 LocalFree(buf);
2317 }
2318 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
2319 constraintWithDomainName, sizeof(constraintWithDomainName),
2320 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2321 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2322 if (ret)
2323 {
2324 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
2325
2326 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
2327 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
2328 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
2329 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
2330 {
2331 ok(info->rgSubtreesConstraint[0].cbData ==
2332 sizeof(encodedDomainName), "Wrong size %d\n",
2333 info->rgSubtreesConstraint[0].cbData);
2334 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
2335 sizeof(encodedDomainName)), "Unexpected value\n");
2336 }
2337 LocalFree(buf);
2338 }
2339 }
2340
2341 /* These are terrible public keys of course, I'm just testing encoding */
2342 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
2343 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
2344 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
2345 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
2346 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
2347 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2348 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
2349 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
2350
2351 struct EncodedRSAPubKey
2352 {
2353 const BYTE *modulus;
2354 size_t modulusLen;
2355 const BYTE *encoded;
2356 size_t decodedModulusLen;
2357 };
2358
2359 static const struct EncodedRSAPubKey rsaPubKeys[] = {
2360 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
2361 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
2362 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
2363 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
2364 };
2365
2366 static void test_encodeRsaPublicKey(DWORD dwEncoding)
2367 {
2368 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
2369 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
2370 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
2371 BOOL ret;
2372 BYTE *buf = NULL;
2373 DWORD bufSize = 0, i;
2374
2375 /* Try with a bogus blob type */
2376 hdr->bType = 2;
2377 hdr->bVersion = CUR_BLOB_VERSION;
2378 hdr->reserved = 0;
2379 hdr->aiKeyAlg = CALG_RSA_KEYX;
2380 rsaPubKey->magic = 0x31415352;
2381 rsaPubKey->bitlen = sizeof(modulus1) * 8;
2382 rsaPubKey->pubexp = 65537;
2383 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
2384 sizeof(modulus1));
2385
2386 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2387 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2388 ok(!ret && GetLastError() == E_INVALIDARG,
2389 "Expected E_INVALIDARG, got %08x\n", GetLastError());
2390 /* Now with a bogus reserved field */
2391 hdr->bType = PUBLICKEYBLOB;
2392 hdr->reserved = 1;
2393 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2394 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2395 if (ret)
2396 {
2397 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2398 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2399 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2400 LocalFree(buf);
2401 }
2402 /* Now with a bogus blob version */
2403 hdr->reserved = 0;
2404 hdr->bVersion = 0;
2405 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2406 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2407 if (ret)
2408 {
2409 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2410 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2411 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2412 LocalFree(buf);
2413 }
2414 /* And with a bogus alg ID */
2415 hdr->bVersion = CUR_BLOB_VERSION;
2416 hdr->aiKeyAlg = CALG_DES;
2417 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2418 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2419 if (ret)
2420 {
2421 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
2422 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
2423 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
2424 LocalFree(buf);
2425 }
2426 /* Check a couple of RSA-related OIDs */
2427 hdr->aiKeyAlg = CALG_RSA_KEYX;
2428 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
2429 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2430 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2431 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2432 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2433 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2434 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2435 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2436 /* Finally, all valid */
2437 hdr->aiKeyAlg = CALG_RSA_KEYX;
2438 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2439 {
2440 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2441 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
2442 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2443 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2444 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2445 if (ret)
2446 {
2447 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
2448 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2,
2449 bufSize);
2450 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
2451 "Unexpected value\n");
2452 LocalFree(buf);
2453 }
2454 }
2455 }
2456
2457 static void test_decodeRsaPublicKey(DWORD dwEncoding)
2458 {
2459 DWORD i;
2460 LPBYTE buf = NULL;
2461 DWORD bufSize = 0;
2462 BOOL ret;
2463
2464 /* Try with a bad length */
2465 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2466 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
2467 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2468 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
2469 GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */),
2470 "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n",
2471 GetLastError());
2472 /* Try with a couple of RSA-related OIDs */
2473 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
2474 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2475 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2476 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2477 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2478 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
2479 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
2480 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2481 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2482 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
2483 /* Now try success cases */
2484 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
2485 {
2486 bufSize = 0;
2487 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
2488 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
2489 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2490 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2491 if (ret)
2492 {
2493 BLOBHEADER *hdr = (BLOBHEADER *)buf;
2494 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
2495
2496 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
2497 rsaPubKeys[i].decodedModulusLen,
2498 "Wrong size %d\n", bufSize);
2499 ok(hdr->bType == PUBLICKEYBLOB,
2500 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
2501 hdr->bType);
2502 ok(hdr->bVersion == CUR_BLOB_VERSION,
2503 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
2504 CUR_BLOB_VERSION, hdr->bVersion);
2505 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
2506 hdr->reserved);
2507 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
2508 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
2509 ok(rsaPubKey->magic == 0x31415352,
2510 "Expected magic RSA1, got %08x\n", rsaPubKey->magic);
2511 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
2512 "Wrong bit len %d\n", rsaPubKey->bitlen);
2513 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n",
2514 rsaPubKey->pubexp);
2515 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
2516 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
2517 "Unexpected modulus\n");
2518 LocalFree(buf);
2519 }
2520 }
2521 }
2522
2523 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
2524 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
2525 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2526
2527 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
2528 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
2529 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
2530 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
2531
2532 static void test_encodeSequenceOfAny(DWORD dwEncoding)
2533 {
2534 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
2535 CRYPT_SEQUENCE_OF_ANY seq;
2536 DWORD i;
2537 BOOL ret;
2538 BYTE *buf = NULL;
2539 DWORD bufSize = 0;
2540
2541 /* Encode a homogeneous sequence */
2542 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
2543 {
2544 blobs[i].cbData = ints[i].encoded[1] + 2;
2545 blobs[i].pbData = (BYTE *)ints[i].encoded;
2546 }
2547 seq.cValue = sizeof(ints) / sizeof(ints[0]);
2548 seq.rgValue = blobs;
2549
2550 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2551 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2552 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2553 if (ret)
2554 {
2555 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize);
2556 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
2557 LocalFree(buf);
2558 }
2559 /* Change the type of the first element in the sequence, and give it
2560 * another go
2561 */
2562 blobs[0].cbData = times[0].encodedTime[1] + 2;
2563 blobs[0].pbData = (BYTE *)times[0].encodedTime;
2564 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
2565 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2566 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2567 if (ret)
2568 {
2569 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize);
2570 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
2571 "Unexpected value\n");
2572 LocalFree(buf);
2573 }
2574 }
2575
2576 static void test_decodeSequenceOfAny(DWORD dwEncoding)
2577 {
2578 BOOL ret;
2579 BYTE *buf = NULL;
2580 DWORD bufSize = 0;
2581
2582 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
2583 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2584 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2585 if (ret)
2586 {
2587 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2588 DWORD i;
2589
2590 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2591 "Wrong elements %d\n", seq->cValue);
2592 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
2593 {
2594 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
2595 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2,
2596 seq->rgValue[i].cbData);
2597 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
2598 ints[i].encoded[1] + 2), "Unexpected value\n");
2599 }
2600 LocalFree(buf);
2601 }
2602 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
2603 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
2604 &bufSize);
2605 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2606 if (ret)
2607 {
2608 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
2609
2610 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
2611 "Wrong elements %d\n", seq->cValue);
2612 /* Just check the first element since it's all that changed */
2613 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
2614 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2,
2615 seq->rgValue[0].cbData);
2616 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
2617 times[0].encodedTime[1] + 2), "Unexpected value\n");
2618 LocalFree(buf);
2619 }
2620 }
2621
2622 struct encodedExtensions
2623 {
2624 CERT_EXTENSIONS exts;
2625 const BYTE *encoded;
2626 };
2627
2628 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2629 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2630 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2;
2631 static CERT_EXTENSION criticalExt =
2632 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } };
2633 static CERT_EXTENSION nonCriticalExt =
2634 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } };
2635 static CHAR oid_short[] = "1.1";
2636 static CERT_EXTENSION extWithShortOid =
2637 { oid_short, FALSE, { 0, NULL } };
2638
2639 static const BYTE ext0[] = { 0x30,0x00 };
2640 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
2641 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2642 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
2643 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2644 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 };
2645
2646 static const struct encodedExtensions exts[] = {
2647 { { 0, NULL }, ext0 },
2648 { { 1, &criticalExt }, ext1 },
2649 { { 1, &nonCriticalExt }, ext2 },
2650 { { 1, &extWithShortOid }, ext3 }
2651 };
2652
2653 static void test_encodeExtensions(DWORD dwEncoding)
2654 {
2655 DWORD i;
2656
2657 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2658 {
2659 BOOL ret;
2660 BYTE *buf = NULL;
2661 DWORD bufSize = 0;
2662
2663 ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
2664 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2665 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2666 if (ret)
2667 {
2668 ok(bufSize == exts[i].encoded[1] + 2,
2669 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize);
2670 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
2671 "Unexpected value\n");
2672 LocalFree(buf);
2673 }
2674 }
2675 }
2676
2677 static void test_decodeExtensions(DWORD dwEncoding)
2678 {
2679 DWORD i;
2680
2681 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
2682 {
2683 BOOL ret;
2684 BYTE *buf = NULL;
2685 DWORD bufSize = 0;
2686
2687 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2688 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2689 NULL, &buf, &bufSize);
2690 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2691 if (ret)
2692 {
2693 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
2694 DWORD j;
2695
2696 ok(ext->cExtension == exts[i].exts.cExtension,
2697 "Expected %d extensions, see %d\n", exts[i].exts.cExtension,
2698 ext->cExtension);
2699 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
2700 {
2701 ok(!strcmp(ext->rgExtension[j].pszObjId,
2702 exts[i].exts.rgExtension[j].pszObjId),
2703 "Expected OID %s, got %s\n",
2704 exts[i].exts.rgExtension[j].pszObjId,
2705 ext->rgExtension[j].pszObjId);
2706 ok(!memcmp(ext->rgExtension[j].Value.pbData,
2707 exts[i].exts.rgExtension[j].Value.pbData,
2708 exts[i].exts.rgExtension[j].Value.cbData),
2709 "Unexpected value\n");
2710 }
2711 LocalFree(buf);
2712 }
2713 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2714 exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
2715 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2716 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize);
2717 if (buf)
2718 {
2719 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
2720 exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, buf, &bufSize);
2721 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2722 HeapFree(GetProcessHeap(), 0, buf);
2723 }
2724 }
2725 }
2726
2727 /* MS encodes public key info with a NULL if the algorithm identifier's
2728 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2729 * it encodes them by omitting the algorithm parameters. It accepts either
2730 * form for decoding.
2731 */
2732 struct encodedPublicKey
2733 {
2734 CERT_PUBLIC_KEY_INFO info;
2735 const BYTE *encoded;
2736 const BYTE *encodedNoNull;
2737 CERT_PUBLIC_KEY_INFO decoded;
2738 };
2739
2740 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2741 0xe, 0xf };
2742 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2743
2744 static const unsigned char bin64[] = {
2745 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2746 static const unsigned char bin65[] = {
2747 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2748 static const unsigned char bin66[] = {
2749 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2750 static const unsigned char bin67[] = {
2751 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2752 static const unsigned char bin68[] = {
2753 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2754 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2755 static const unsigned char bin69[] = {
2756 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2757 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2758 static const unsigned char bin70[] = {
2759 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2760 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2761 0x0f};
2762 static const unsigned char bin71[] = {
2763 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2764 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2765 0x0f};
2766 static unsigned char bin72[] = { 0x05,0x00};
2767
2768 static CHAR oid_bogus[] = "1.2.3",
2769 oid_rsa[] = szOID_RSA;
2770
2771 static const struct encodedPublicKey pubKeys[] = {
2772 /* with a bogus OID */
2773 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2774 bin64, bin65,
2775 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2776 /* some normal keys */
2777 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2778 bin66, bin67,
2779 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2780 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2781 bin68, bin69,
2782 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2783 /* with add'l parameters--note they must be DER-encoded */
2784 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2785 (BYTE *)aKey, 0 } },
2786 bin70, bin71,
2787 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2788 (BYTE *)aKey, 0 } } },
2789 };
2790
2791 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2792 {
2793 DWORD i;
2794
2795 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2796 {
2797 BOOL ret;
2798 BYTE *buf = NULL;
2799 DWORD bufSize = 0;
2800
2801 ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2802 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2803 &bufSize);
2804 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2805 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2806 if (ret)
2807 {
2808 ok(bufSize == pubKeys[i].encoded[1] + 2,
2809 "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2810 if (bufSize == pubKeys[i].encoded[1] + 2)
2811 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2812 "Unexpected value\n");
2813 LocalFree(buf);
2814 }
2815 }
2816 }
2817
2818 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2819 const CERT_PUBLIC_KEY_INFO *got)
2820 {
2821 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2822 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2823 got->Algorithm.pszObjId);
2824 ok(expected->Algorithm.Parameters.cbData ==
2825 got->Algorithm.Parameters.cbData,
2826 "Expected parameters of %d bytes, got %d\n",
2827 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2828 if (expected->Algorithm.Parameters.cbData)
2829 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2830 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2831 "Unexpected algorithm parameters\n");
2832 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2833 "Expected public key of %d bytes, got %d\n",
2834 expected->PublicKey.cbData, got->PublicKey.cbData);
2835 if (expected->PublicKey.cbData)
2836 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2837 got->PublicKey.cbData), "Unexpected public key value\n");
2838 }
2839
2840 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2841 {
2842 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2843 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2844 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2845 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2846 DWORD i;
2847 BOOL ret;
2848 BYTE *buf = NULL;
2849 DWORD bufSize = 0;
2850
2851 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2852 {
2853 /* The NULL form decodes to the decoded member */
2854 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2855 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2856 NULL, &buf, &bufSize);
2857 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2858 if (ret)
2859 {
2860 comparePublicKeyInfo(&pubKeys[i].decoded,
2861 (CERT_PUBLIC_KEY_INFO *)buf);
2862 LocalFree(buf);
2863 }
2864 /* The non-NULL form decodes to the original */
2865 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2866 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2867 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2868 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2869 if (ret)
2870 {
2871 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2872 LocalFree(buf);
2873 }
2874 }
2875 /* Test with bogus (not valid DER) parameters */
2876 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2877 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2878 NULL, &buf, &bufSize);
2879 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2880 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2881 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2882 GetLastError());
2883 }
2884
2885 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2886 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2887 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2888 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2889 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2890 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2891 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2892 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2893 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2894 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2895 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2896 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2897 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2898 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2899 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2900 static const BYTE v4Cert[] = {
2901 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2902 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2903 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2904 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2905 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2906 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2907 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2908 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2909 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2910 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2911 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2912 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2913 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2914 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2915 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2916 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2917 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2918 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2919 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2920 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2921 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2922 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2923 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2924 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2925 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2926 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2927 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2928 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2929 static const BYTE v1CertWithPubKey[] = {
2930 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2931 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2932 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2933 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2934 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2935 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2936 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2937 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2938 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2939 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2940 0x01,0x01 };
2941 static const BYTE v1CertWithPubKeyNoNull[] = {
2942 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2943 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2944 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2945 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2946 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2947 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2948 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2949 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2950 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2951 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2952 static const BYTE v1CertWithSubjectKeyId[] = {
2953 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2954 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2955 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2956 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2957 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2958 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2959 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2960 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2961 0x4c,0x61,0x6e,0x67,0x00 };
2962 static const BYTE v1CertWithIssuerUniqueId[] = {
2963 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2964 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2965 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2966 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2967 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2968 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2969 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2970 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2971 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2972 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2973 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2974 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2975 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2976 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2977 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2978 0x01,0x01,0xff,0x02,0x01,0x01 };
2979 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2980 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2981 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2982 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2983 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2984 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2985 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2986 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2987 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2988 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2989 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2990 0xff,0x02,0x01,0x01 };
2991
2992 static const BYTE serialNum[] = { 0x01 };
2993
2994 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2995 {
2996 BOOL ret;
2997 BYTE *buf = NULL;
2998 DWORD size = 0;
2999 CERT_INFO info = { 0 };
3000 static char oid_rsa_rsa[] = szOID_RSA_RSA;
3001 static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
3002 CERT_EXTENSION ext;
3003
3004 if (0)
3005 {
3006 /* Test with NULL pvStructInfo (crashes on win9x) */
3007 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
3008 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3009 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3010 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3011 }
3012 /* Test with a V1 cert */
3013 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3014 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3015 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3016 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3017 if (ret)
3018 {
3019 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3020 v1Cert[1] + 2, size);
3021 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3022 LocalFree(buf);
3023 }
3024 /* Test v2 cert */
3025 info.dwVersion = CERT_V2;
3026 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3027 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3028 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3029 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3030 if (ret)
3031 {
3032 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3033 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3034 LocalFree(buf);
3035 }
3036 /* Test v3 cert */
3037 info.dwVersion = CERT_V3;
3038 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3039 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3040 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3041 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3042 if (ret)
3043 {
3044 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3045 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3046 LocalFree(buf);
3047 }
3048 /* A v4 cert? */
3049 info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3050 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3051 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3052 if (ret)
3053 {
3054 ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3055 ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3056 LocalFree(buf);
3057 }
3058 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3059 * API doesn't prevent it)
3060 */
3061 info.dwVersion = CERT_V1;
3062 info.cExtension = 1;
3063 info.rgExtension = &criticalExt;
3064 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3065 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3066 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3067 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3068 if (ret)
3069 {
3070 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3071 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3072 LocalFree(buf);
3073 }
3074 /* test v1 cert with a serial number */
3075 info.SerialNumber.cbData = sizeof(serialNum);
3076 info.SerialNumber.pbData = (BYTE *)serialNum;
3077 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3078 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3079 if (ret)
3080 {
3081 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3082 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3083 LocalFree(buf);
3084 }
3085 /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3086 info.dwVersion = CERT_V1;
3087 info.cExtension = 0;
3088 info.IssuerUniqueId.cbData = sizeof(serialNum);
3089 info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3090 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3091 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3092 ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
3093 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3094 if (ret)
3095 {
3096 ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3097 ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3098 "Got unexpected value\n");
3099 LocalFree(buf);
3100 }
3101 /* Test v1 cert with an issuer name, a subject name, and a serial number */
3102 info.IssuerUniqueId.cbData = 0;
3103 info.IssuerUniqueId.pbData = NULL;
3104 info.cExtension = 1;
3105 info.rgExtension = &criticalExt;
3106 info.Issuer.cbData = sizeof(encodedCommonName);
3107 info.Issuer.pbData = (BYTE *)encodedCommonName;
3108 info.Subject.cbData = sizeof(encodedCommonName);
3109 info.Subject.pbData = (BYTE *)encodedCommonName;
3110 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3111 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3112 if (ret)
3113 {
3114 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3115 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3116 LocalFree(buf);
3117 }
3118 /* Add a public key */
3119 info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3120 info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3121 info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3122 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3123 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3124 if (ret)
3125 {
3126 ok(size == sizeof(v1CertWithPubKey) ||
3127 size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3128 if (size == sizeof(v1CertWithPubKey))
3129 ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3130 else if (size == sizeof(v1CertWithPubKeyNoNull))
3131 ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3132 "Got unexpected value\n");
3133 LocalFree(buf);
3134 }
3135 /* Again add an issuer unique id */
3136 info.IssuerUniqueId.cbData = sizeof(serialNum);
3137 info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3138 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3139 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3140 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3141 if (ret)
3142 {
3143 ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3144 size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3145 "Wrong size %d\n", size);
3146 if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3147 ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3148 size), "unexpected value\n");
3149 else if (size ==
3150 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3151 ok(!memcmp(buf,
3152 v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3153 "unexpected value\n");
3154 LocalFree(buf);
3155 }
3156 /* Remove the public key, and add a subject key identifier extension */
3157 info.IssuerUniqueId.cbData = 0;
3158 info.IssuerUniqueId.pbData = NULL;
3159 info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3160 info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3161 info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3162 ext.pszObjId = oid_subject_key_identifier;
3163 ext.fCritical = FALSE;
3164 ext.Value.cbData = sizeof(octetCommonNameValue);
3165 ext.Value.pbData = octetCommonNameValue;
3166 info.cExtension = 1;
3167 info.rgExtension = &ext;
3168 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3169 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3170 if (ret)
3171 {
3172 ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3173 ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3174 LocalFree(buf);
3175 }
3176 }
3177
3178 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3179 {
3180 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3181 v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3182 BOOL ret;
3183 BYTE *buf = NULL;
3184 DWORD size = 0, i;
3185
3186 /* Test with NULL pbEncoded */
3187 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3188 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3189 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3190 GetLastError() == OSS_BAD_ARG /* Win9x */),
3191 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3192 if (0)
3193 {
3194 /* Crashes on win9x */
3195 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3196 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3197 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3198 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3199 }
3200 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3201 * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3202 * serial number, an issuer, a subject, and a public key.
3203 */
3204 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3205 {
3206 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3207 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3208 &buf, &size);
3209 ok(!ret, "Expected failure\n");
3210 }
3211 /* The following succeeds, even though v1 certs are not allowed to have
3212 * extensions.
3213 */
3214 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3215 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3216 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3217 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3218 if (ret)
3219 {
3220 CERT_INFO *info = (CERT_INFO *)buf;
3221
3222 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3223 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3224 info->dwVersion);
3225 ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3226 info->cExtension);
3227 LocalFree(buf);
3228 }
3229 /* The following also succeeds, even though V1 certs are not allowed to
3230 * have issuer unique ids.
3231 */
3232 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3233 v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3234 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3235 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3236 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3237 if (ret)
3238 {
3239 CERT_INFO *info = (CERT_INFO *)buf;
3240
3241 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3242 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3243 info->dwVersion);
3244 ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3245 "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3246 ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3247 "unexpected issuer unique id value\n");
3248 LocalFree(buf);
3249 }
3250 /* Now check with serial number, subject and issuer specified */
3251 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3252 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3253 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3254 if (ret)
3255 {
3256 CERT_INFO *info = (CERT_INFO *)buf;
3257
3258 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3259 ok(info->SerialNumber.cbData == 1,
3260 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3261 ok(*info->SerialNumber.pbData == *serialNum,
3262 "Expected serial number %d, got %d\n", *serialNum,
3263 *info->SerialNumber.pbData);
3264 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3265 "Wrong size %d\n", info->Issuer.cbData);
3266 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3267 "Unexpected issuer\n");
3268 ok(info->Subject.cbData == sizeof(encodedCommonName),
3269 "Wrong size %d\n", info->Subject.cbData);
3270 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3271 info->Subject.cbData), "Unexpected subject\n");
3272 LocalFree(buf);
3273 }
3274 /* Check again with pub key specified */
3275 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3276 v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3277 &buf, &size);
3278 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3279 if (ret)
3280 {
3281 CERT_INFO *info = (CERT_INFO *)buf;
3282
3283 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3284 ok(info->SerialNumber.cbData == 1,
3285 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3286 ok(*info->SerialNumber.pbData == *serialNum,
3287 "Expected serial number %d, got %d\n", *serialNum,
3288 *info->SerialNumber.pbData);
3289 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3290 "Wrong size %d\n", info->Issuer.cbData);
3291 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3292 "Unexpected issuer\n");
3293 ok(info->Subject.cbData == sizeof(encodedCommonName),
3294 "Wrong size %d\n", info->Subject.cbData);
3295 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3296 info->Subject.cbData), "Unexpected subject\n");
3297 ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3298 szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3299 info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3300 ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3301 "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3302 ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3303 sizeof(aKey)), "Unexpected public key\n");
3304 LocalFree(buf);
3305 }
3306 }
3307
3308 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3309 0xe, 0xf };
3310
3311 static const BYTE signedBigCert[] = {
3312 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3313 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3314 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3315 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3316 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3317 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3318 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3319 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3320 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3321 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3322 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3323 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3324
3325 static void test_encodeCert(DWORD dwEncoding)
3326 {
3327 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
3328 * also that bigCert is a NULL-terminated string, so don't count its
3329 * last byte (otherwise the signed cert won't decode.)
3330 */
3331 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3332 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3333 BOOL ret;
3334 BYTE *buf = NULL;
3335 DWORD bufSize = 0;
3336
3337 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3338 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3339 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3340 if (ret)
3341 {
3342 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3343 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3344 LocalFree(buf);
3345 }
3346 }
3347
3348 static void test_decodeCert(DWORD dwEncoding)
3349 {
3350 BOOL ret;
3351 BYTE *buf = NULL;
3352 DWORD size = 0;
3353
3354 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3355 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3356 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3357 if (ret)
3358 {
3359 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3360
3361 ok(info->ToBeSigned.cbData == sizeof(bigCert),
3362 "Wrong cert size %d\n", info->ToBeSigned.cbData);
3363 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3364 "Unexpected cert\n");
3365 ok(info->Signature.cbData == sizeof(hash),
3366 "Wrong signature size %d\n", info->Signature.cbData);
3367 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3368 "Unexpected signature\n");
3369 LocalFree(buf);
3370 }
3371 /* A signed cert decodes as a CERT_INFO too */
3372 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3373 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3374 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3375 if (ret)
3376 {
3377 CERT_INFO *info = (CERT_INFO *)buf;
3378
3379 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3380 ok(info->SerialNumber.cbData == 1,
3381 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3382 ok(*info->SerialNumber.pbData == *serialNum,
3383 "Expected serial number %d, got %d\n", *serialNum,
3384 *info->SerialNumber.pbData);
3385 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3386 "Wrong size %d\n", info->Issuer.cbData);
3387 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3388 "Unexpected issuer\n");
3389 ok(info->Subject.cbData == sizeof(encodedCommonName),
3390 "Wrong size %d\n", info->Subject.cbData);
3391 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3392 info->Subject.cbData), "Unexpected subject\n");
3393 LocalFree(buf);
3394 }
3395 }
3396
3397 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3398 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3399 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3400 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3401 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3402 0x00, 0x03 };
3403 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3404 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3405 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3406 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3407 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3408 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3409 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3410 0x2e, 0x6f, 0x72, 0x67 };
3411 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3412 CRL_REASON_AFFILIATION_CHANGED;
3413
3414 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3415 {
3416 CRL_DIST_POINTS_INFO info = { 0 };
3417 CRL_DIST_POINT point = { { 0 } };
3418 CERT_ALT_NAME_ENTRY entry = { 0 };
3419 BOOL ret;
3420 BYTE *buf = NULL;
3421 DWORD size = 0;
3422
3423 /* Test with an empty info */
3424 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3425 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3426 ok(!ret && GetLastError() == E_INVALIDARG,
3427 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3428 /* Test with one empty dist point */
3429 info.cDistPoint = 1;
3430 info.rgDistPoint = &point;
3431 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3432 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3433 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3434 if (ret)
3435 {
3436 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3437 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3438 LocalFree(buf);
3439 }
3440 /* A dist point with an invalid name */
3441 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3442 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3443 U(entry).pwszURL = (LPWSTR)nihongoURL;
3444 U(point.DistPointName).FullName.cAltEntry = 1;
3445 U(point.DistPointName).FullName.rgAltEntry = &entry;
3446 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3447 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3448 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3449 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3450 /* The first invalid character is at index 7 */
3451 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3452 "Expected invalid char at index 7, got %d\n",
3453 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3454 /* A dist point with (just) a valid name */
3455 U(entry).pwszURL = (LPWSTR)url;
3456 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3457 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3458 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3459 if (ret)
3460 {
3461 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3462 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3463 LocalFree(buf);
3464 }
3465 /* A dist point with (just) reason flags */
3466 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3467 point.ReasonFlags.cbData = sizeof(crlReason);
3468 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3469 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3470 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3471 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3472 if (ret)
3473 {
3474 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3475 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3476 LocalFree(buf);
3477 }
3478 /* A dist point with just an issuer */
3479 point.ReasonFlags.cbData = 0;
3480 point.CRLIssuer.cAltEntry = 1;
3481 point.CRLIssuer.rgAltEntry = &entry;
3482 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3483 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3484 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3485 if (ret)
3486 {
3487 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3488 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3489 LocalFree(buf);
3490 }
3491 /* A dist point with both a name and an issuer */
3492 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3493 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3494 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3495 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3496 if (ret)
3497 {
3498 ok(size == sizeof(distPointWithUrlAndIssuer),
3499 "Wrong size %d\n", size);
3500 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3501 LocalFree(buf);
3502 }
3503 }
3504
3505 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3506 {
3507 BOOL ret;
3508 BYTE *buf = NULL;
3509 DWORD size = 0;
3510 PCRL_DIST_POINTS_INFO info;
3511 PCRL_DIST_POINT point;
3512 PCERT_ALT_NAME_ENTRY entry;
3513
3514 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3515 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3516 &buf, &size);
3517 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3518 if (ret)
3519 {
3520 info = (PCRL_DIST_POINTS_INFO)buf;
3521 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3522 "Wrong size %d\n", size);
3523 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3524 info->cDistPoint);
3525 point = info->rgDistPoint;
3526 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3527 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3528 point->DistPointName.dwDistPointNameChoice);
3529 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3530 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3531 LocalFree(buf);
3532 }
3533 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3534 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3535 &buf, &size);
3536 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3537 if (ret)
3538 {
3539 info = (PCRL_DIST_POINTS_INFO)buf;
3540 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3541 "Wrong size %d\n", size);
3542 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3543 info->cDistPoint);
3544 point = info->rgDistPoint;
3545 ok(point->DistPointName.dwDistPointNameChoice ==
3546 CRL_DIST_POINT_FULL_NAME,
3547 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3548 point->DistPointName.dwDistPointNameChoice);
3549 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3550 "Expected 1 name entry, got %d\n",
3551 U(point->DistPointName).FullName.cAltEntry);
3552 entry = U(point->DistPointName).FullName.rgAltEntry;
3553 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3554 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3555 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3556 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3557 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3558 LocalFree(buf);
3559 }
3560 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3561 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3562 NULL, &buf, &size);
3563 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3564 if (ret)
3565 {
3566 info = (PCRL_DIST_POINTS_INFO)buf;
3567 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3568 "Wrong size %d\n", size);
3569 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3570 info->cDistPoint);
3571 point = info->rgDistPoint;
3572 ok(point->DistPointName.dwDistPointNameChoice ==
3573 CRL_DIST_POINT_NO_NAME,
3574 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3575 point->DistPointName.dwDistPointNameChoice);
3576 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3577 "Expected reason length\n");
3578 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3579 "Unexpected reason\n");
3580 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3581 LocalFree(buf);
3582 }
3583 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3584 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3585 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3586 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3587 if (ret)
3588 {
3589 info = (PCRL_DIST_POINTS_INFO)buf;
3590 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3591 "Wrong size %d\n", size);
3592 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3593 info->cDistPoint);
3594 point = info->rgDistPoint;
3595 ok(point->DistPointName.dwDistPointNameChoice ==
3596 CRL_DIST_POINT_FULL_NAME,
3597 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3598 point->DistPointName.dwDistPointNameChoice);
3599 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3600 "Expected 1 name entry, got %d\n",
3601 U(point->DistPointName).FullName.cAltEntry);
3602 entry = U(point->DistPointName).FullName.rgAltEntry;
3603 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3604 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3605 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3606 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3607 ok(point->CRLIssuer.cAltEntry == 1,
3608 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3609 entry = point->CRLIssuer.rgAltEntry;
3610 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3611 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3612 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3613 LocalFree(buf);
3614 }
3615 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3616 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3617 NULL, NULL, &size);
3618 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3619 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
3620 if (buf)
3621 {
3622 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3623 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0,
3624 NULL, buf, &size);
3625 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3626 HeapFree(GetProcessHeap(), 0, buf);
3627 }
3628 }
3629
3630 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3631 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3632 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3633 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3634 0x67 };
3635
3636 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3637 {
3638 BOOL ret;
3639 BYTE *buf = NULL;
3640 DWORD size = 0;
3641 CRL_ISSUING_DIST_POINT point = { { 0 } };
3642 CERT_ALT_NAME_ENTRY entry;
3643
3644 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3645 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3646 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3647 {
3648 skip("no X509_ISSUING_DIST_POINT encode support\n");
3649 return;
3650 }
3651 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3652 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3653 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3654 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3655 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3656 if (ret)
3657 {
3658 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3659 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3660 LocalFree(buf);
3661 }
3662 /* nonsensical flags */
3663 point.fOnlyContainsUserCerts = TRUE;
3664 point.fOnlyContainsCACerts = TRUE;
3665 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3666 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3667 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3668 if (ret)
3669 {
3670 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3671 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3672 LocalFree(buf);
3673 }
3674 /* unimplemented name type */
3675 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3676 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3677 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3678 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3679 ok(!ret && GetLastError() == E_INVALIDARG,
3680 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3681 /* empty name */
3682 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3683 U(point.DistPointName).FullName.cAltEntry = 0;
3684 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3685 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3686 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3687 if (ret)
3688 {
3689 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3690 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3691 LocalFree(buf);
3692 }
3693 /* name with URL entry */
3694 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3695 U(entry).pwszURL = (LPWSTR)url;
3696 U(point.DistPointName).FullName.cAltEntry = 1;
3697 U(point.DistPointName).FullName.rgAltEntry = &entry;
3698 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3699 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3700 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3701 if (ret)
3702 {
3703 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3704 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3705 LocalFree(buf);
3706 }
3707 }
3708
3709 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3710 const CERT_ALT_NAME_ENTRY *got)
3711 {
3712 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3713 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3714 got->dwAltNameChoice);
3715 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3716 {
3717 switch (got->dwAltNameChoice)
3718 {
3719 case CERT_ALT_NAME_RFC822_NAME:
3720 case CERT_ALT_NAME_DNS_NAME:
3721 case CERT_ALT_NAME_EDI_PARTY_NAME:
3722 case CERT_ALT_NAME_URL:
3723 case CERT_ALT_NAME_REGISTERED_ID:
3724 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3725 (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3726 (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3727 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3728 "Unexpected name\n");
3729 break;
3730 case CERT_ALT_NAME_X400_ADDRESS:
3731 case CERT_ALT_NAME_DIRECTORY_NAME:
3732 case CERT_ALT_NAME_IP_ADDRESS:
3733 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3734 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3735 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3736 U(*got).IPAddress.cbData), "Unexpected value\n");
3737 break;
3738 }
3739 }
3740 }
3741
3742 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3743 const CERT_ALT_NAME_INFO *got)
3744 {
3745 DWORD i;
3746
3747 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3748 expected->cAltEntry, got->cAltEntry);
3749 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3750 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3751 }
3752
3753 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3754 const CRL_DIST_POINT_NAME *got)
3755 {
3756 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3757 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3758 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3759 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3760 }
3761
3762 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3763 const CRL_ISSUING_DIST_POINT *got)
3764 {
3765 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3766 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3767 "Unexpected fOnlyContainsUserCerts\n");
3768 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3769 "Unexpected fOnlyContainsCACerts\n");
3770 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3771 "Unexpected reason flags\n");
3772 ok(got->fIndirectCRL == expected->fIndirectCRL,
3773 "Unexpected fIndirectCRL\n");
3774 }
3775
3776 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3777 {
3778 BOOL ret;
3779 BYTE *buf = NULL;
3780 DWORD size = 0;
3781 CRL_ISSUING_DIST_POINT point = { { 0 } };
3782
3783 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3784 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3785 &buf, &size);
3786 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3787 {
3788 skip("no X509_ISSUING_DIST_POINT decode support\n");
3789 return;
3790 }
3791 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3792 if (ret)
3793 {
3794 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3795 LocalFree(buf);
3796 }
3797 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3798 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3799 &buf, &size);
3800 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3801 if (ret)
3802 {
3803 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3804 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3805 LocalFree(buf);
3806 }
3807 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3808 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3809 &buf, &size);
3810 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3811 if (ret)
3812 {
3813 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3814 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3815 U(point.DistPointName).FullName.cAltEntry = 0;
3816 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3817 LocalFree(buf);
3818 }
3819 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3820 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3821 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3822 if (ret)
3823 {
3824 CERT_ALT_NAME_ENTRY entry;
3825
3826 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3827 U(entry).pwszURL = (LPWSTR)url;
3828 U(point.DistPointName).FullName.cAltEntry = 1;
3829 U(point.DistPointName).FullName.rgAltEntry = &entry;
3830 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3831 LocalFree(buf);
3832 }
3833 }
3834
3835 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3836 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3837 0x30, 0x5a };
3838 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3839 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3840 0x30, 0x30, 0x30, 0x30, 0x5a };
3841 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3842 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3843 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3844 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3845 0x5a };
3846 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3847 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3848 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3849 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3850 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3851 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3852 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3853 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3854 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3855 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3856 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3857 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3858 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3859 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3860 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3861 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3862 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3863 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3864 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3865 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3866 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3867 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3868 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3869 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3870 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3871 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3872 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3873 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3874 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3875 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3876 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3877 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3878 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3879
3880 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3881 {
3882 BOOL ret;
3883 BYTE *buf = NULL;
3884 DWORD size = 0;
3885 CRL_INFO info = { 0 };
3886 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3887
3888 /* Test with a V1 CRL */
3889 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3890 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3891 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3892 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3893 if (ret)
3894 {
3895 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3896 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3897 LocalFree(buf);
3898 }
3899 /* Test v2 CRL */
3900 info.dwVersion = CRL_V2;
3901 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3902 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3903 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3904 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3905 if (ret)
3906 {
3907 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3908 v2CRL[1] + 2, size);
3909 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3910 LocalFree(buf);
3911 }
3912 /* v1 CRL with a name */
3913 info.dwVersion = CRL_V1;
3914 info.Issuer.cbData = sizeof(encodedCommonName);
3915 info.Issuer.pbData = (BYTE *)encodedCommonName;
3916 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3917 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3918 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3919 if (ret)
3920 {
3921 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3922 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3923 LocalFree(buf);
3924 }
3925 if (0)
3926 {
3927 /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3928 info.cCRLEntry = 1;
3929 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3930 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3931 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3932 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3933 }
3934 /* now set an empty entry */
3935 info.cCRLEntry = 1;
3936 info.rgCRLEntry = &entry;
3937 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3938 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3939 if (ret)
3940 {
3941 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3942 "Wrong size %d\n", size);
3943 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3944 "Got unexpected value\n");
3945 LocalFree(buf);
3946 }
3947 /* an entry with a serial number */
3948 entry.SerialNumber.cbData = sizeof(serialNum);
3949 entry.SerialNumber.pbData = (BYTE *)serialNum;
3950 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3951 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3952 if (ret)
3953 {
3954 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3955 "Wrong size %d\n", size);
3956 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3957 "Got unexpected value\n");
3958 LocalFree(buf);
3959 }
3960 /* an entry with an extension */
3961 entry.cExtension = 1;
3962 entry.rgExtension = &criticalExt;
3963 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3964 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3965 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3966 if (ret)
3967 {
3968 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3969 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3970 LocalFree(buf);
3971 }
3972 /* a CRL with an extension */
3973 entry.cExtension = 0;
3974 info.cExtension = 1;
3975 info.rgExtension = &criticalExt;
3976 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3977 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3978 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3979 if (ret)
3980 {
3981 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3982 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3983 LocalFree(buf);
3984 }
3985 /* a v2 CRL with an extension, this time non-critical */
3986 info.dwVersion = CRL_V2;
3987 info.rgExtension = &nonCriticalExt;
3988 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3989 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3990 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3991 if (ret)
3992 {
3993 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3994 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3995 LocalFree(buf);
3996 }
3997 }
3998
3999 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
4000 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
4001 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
4002 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
4003 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
4004 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
4005 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
4006 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
4007 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
4008 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
4009 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
4010 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
4011 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
4012 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
4013 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
4014 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
4015 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
4016 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
4017 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
4018 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
4019 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
4020 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
4021 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
4022 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
4023 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
4024 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4025 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4026 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4027 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4028 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4029 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4030 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4031 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4032 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4033 0xcd };
4034 static const BYTE verisignCRLWithLotsOfEntries[] = {
4035 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4036 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4037 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4038 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4039 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4040 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4041 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4042 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4043 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4044 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4045 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4046 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4047 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4048 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4049 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4050 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4051 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4052 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4053 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4054 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4055 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4056 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4057 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4058 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4059 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4060 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4061 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4062 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4063 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4064 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4065 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4066 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4067 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4068 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4069 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4070 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4071 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4072 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4073 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4074 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4075 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4076 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4077 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4078 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4079 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4080 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4081 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4082 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4083 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4084 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4085 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4086 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4087 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4088 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4089 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4090 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4091 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4092 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4093 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4094 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4095 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4096 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4097 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4098 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4099 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4100 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4101 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4102 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4103 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4104 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4105 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4106 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4107 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4108 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4109 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4110 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4111 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4112 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4113 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4114 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4115 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4116 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4117 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4118 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4119 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4120 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4121 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4122 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4123 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4124 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4125 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4126 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4127 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4128 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4129 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4130 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4131 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4132 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4133 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4134 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4135 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4136 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4137 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4138 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4139 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4140 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4141 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4142 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4143 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4144 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4145 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4146 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4147 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4148 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4149 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4150 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4151 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4152 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4153 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4154 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4155 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4156 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4157 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4158 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4159 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4160 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4161 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4162 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4163 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4164 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4165 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4166 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4167 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4168 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4169 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4170 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4171 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4172 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4173 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4174 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4175 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4176 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4177 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4178 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4179 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4180 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4181 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4182 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4183 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4184 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4185 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4186 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4187 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4188 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4189 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4190 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4191 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4192 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4193 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4194 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4195 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4196 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4197 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4198 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4199 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4200 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4201 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4202 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4203 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4204 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4205 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4206 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4207 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4208 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4209 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4210 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4211 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4212 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4213 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4214 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4215 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4216 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4217 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4218 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4219 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4220 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4221 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4222 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4223 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4224 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4225 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4226 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4227 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4228 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4229 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4230 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4231 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4232 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4233 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4234 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4235 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4236 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4237 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4238 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4239 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4240 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4241 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4242 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4243 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4244 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4245 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4246 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4247 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4248 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4249 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4250 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4251 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4252 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4253 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4254 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4255 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4256 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4257 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4258 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4259 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4260 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4261 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4262 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4263 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4264 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4265 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4266 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4267 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4268 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4269 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4270 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4271 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4272 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4273 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4274 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4275 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4276 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4277 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4278 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4279 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4280 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4281 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4282 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4283 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4284 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4285 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4286 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4287 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4288 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4289 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4290 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4291 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4292 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4293 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4294 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4295 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4296 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4297 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4298 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4299 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4300 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4301 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4302 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4303 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4304 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4305 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4306 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4307 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4308 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4309 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4310 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4311 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4312 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4313 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4314 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4315 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4316 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4317 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4318 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4319 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4320 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4321 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4322 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4323 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4324 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4325 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4326 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4327 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4328 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4329 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4330 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4331 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4332 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4333 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4334 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4335 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4336 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4337 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4338 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4339 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4340 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4341 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4342 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4343 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4344 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4345 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4346 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4347 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4348 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4349 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4350 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4351 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4352 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4353 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4354 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4355 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4356 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4357 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4358 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4359 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4360 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4361 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4362 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4363 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4364 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4365 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4366 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4367 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4368 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4369 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4370 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4371 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4372 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4373 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4374 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4375 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4376 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4377 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4378 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4379 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4380 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4381 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4382 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4383 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4384 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4385 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4386 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4387 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4388 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4389 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4390 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4391 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4392 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4393 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4394 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4395 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4396 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4397 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4398 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4399 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4400 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4401 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4402 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4403 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4404 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4405 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4406 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4407 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4408 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4409 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4410 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4411 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4412 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4413 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4414 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4415 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4416 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4417 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4418 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4419 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4420 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4421 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4422 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4423 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4424 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4425 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4426 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4427 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4428 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4429 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4430 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4431 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4432 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4433 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4434 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4435 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4436 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4437 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4438 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4439 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4440 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4441 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4442 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4443 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4444 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4445 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4446 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4447 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4448 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4449 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4450 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4451 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4452 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4453 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4454 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4455 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4456 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4457 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4458 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4459 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4460 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4461 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4462 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4463 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4464 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4465 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4466 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4467 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4468 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4469 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4470 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4471 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4472 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4473 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4474 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4475 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4476 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4477 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4478 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4479 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4480 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4481 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4482 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4483 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4484 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4485 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4486 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4487 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4488 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4489 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4490 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4491 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4492 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4493 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4494 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4495 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4496 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4497 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4498 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4499 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4500 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4501 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4502 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4503 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4504 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4505 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4506 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4507 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4508 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4509 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4510 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4511 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4512 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4513 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4514 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4515 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4516 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4517 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4518 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4519 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4520 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4521 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4522 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4523 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4524 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4525 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4526 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4527 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4528 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4529 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4530 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4531 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4532 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4533 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4534 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4535 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4536 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4537 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4538 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4539 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4540 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4541 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4542 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4543
4544 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4545 {
4546 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4547 BOOL ret;
4548 BYTE *buf = NULL;
4549 DWORD size = 0, i;
4550
4551 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4552 {
4553 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4554 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4555 &buf, &size);
4556 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4557 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4558 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4559 GetLastError());
4560 }
4561 /* at a minimum, a CRL must contain an issuer: */
4562 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4563 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4564 &buf, &size);
4565 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4566 if (ret)
4567 {
4568 CRL_INFO *info = (CRL_INFO *)buf;
4569
4570 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4571 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4572 info->cCRLEntry);
4573 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4574 "Wrong issuer size %d\n", info->Issuer.cbData);
4575 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4576 "Unexpected issuer\n");
4577 LocalFree(buf);
4578 }
4579 /* check decoding with an empty CRL entry */
4580 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4581 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4582 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4583 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4584 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4585 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4586 GetLastError());
4587 /* with a real CRL entry */
4588 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4589 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4590 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4591 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4592 if (ret)
4593 {
4594 CRL_INFO *info = (CRL_INFO *)buf;
4595 CRL_ENTRY *entry;
4596
4597 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4598 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4599 info->cCRLEntry);
4600 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4601 entry = info->rgCRLEntry;
4602 ok(entry->SerialNumber.cbData == 1,
4603 "Expected serial number size 1, got %d\n",
4604 entry->SerialNumber.cbData);
4605 ok(*entry->SerialNumber.pbData == *serialNum,
4606 "Expected serial number %d, got %d\n", *serialNum,
4607 *entry->SerialNumber.pbData);
4608 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4609 "Wrong issuer size %d\n", info->Issuer.cbData);
4610 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4611 "Unexpected issuer\n");
4612 LocalFree(buf);
4613 }
4614 /* a real CRL from verisign that has extensions */
4615 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4616 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4617 NULL, &buf, &size);
4618 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4619 if (ret)
4620 {
4621 CRL_INFO *info = (CRL_INFO *)buf;
4622
4623 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4624 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4625 info->cCRLEntry);
4626 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4627 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4628 info->cExtension);
4629 LocalFree(buf);
4630 }
4631 /* another real CRL from verisign that has lots of entries */
4632 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4633 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4634 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4635 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4636 if (ret)
4637 {
4638 CRL_INFO *info = (CRL_INFO *)buf;
4639
4640 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4641 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4642 info->cCRLEntry);
4643 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4644 info->cExtension);
4645 LocalFree(buf);
4646 }
4647 /* and finally, with an extension */
4648 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4649 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4650 NULL, &buf, &size);
4651 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4652 if (ret)
4653 {
4654 CRL_INFO *info = (CRL_INFO *)buf;
4655 CRL_ENTRY *entry;
4656
4657 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4658 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4659 info->cCRLEntry);
4660 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4661 entry = info->rgCRLEntry;
4662 ok(entry->SerialNumber.cbData == 1,
4663 "Expected serial number size 1, got %d\n",
4664 entry->SerialNumber.cbData);
4665 ok(*entry->SerialNumber.pbData == *serialNum,
4666 "Expected serial number %d, got %d\n", *serialNum,
4667 *entry->SerialNumber.pbData);
4668 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4669 "Wrong issuer size %d\n", info->Issuer.cbData);
4670 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4671 "Unexpected issuer\n");
4672 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4673 info->cExtension);
4674 LocalFree(buf);
4675 }
4676 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4677 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4678 NULL, &buf, &size);
4679 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4680 if (ret)
4681 {
4682 CRL_INFO *info = (CRL_INFO *)buf;
4683
4684 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4685 info->cExtension);
4686 LocalFree(buf);
4687 }
4688 }
4689
4690 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4691 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4692 static const BYTE encodedUsage[] = {
4693 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4694 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4695 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4696
4697 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4698 {
4699 BOOL ret;
4700 BYTE *buf = NULL;
4701 DWORD size = 0;
4702 CERT_ENHKEY_USAGE usage;
4703
4704 /* Test with empty usage */
4705 usage.cUsageIdentifier = 0;
4706 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4707 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4708 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4709 if (ret)
4710 {
4711 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4712 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4713 LocalFree(buf);
4714 }
4715 /* Test with a few usages */
4716 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4717 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4718 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4719 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4720 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4721 if (ret)
4722 {
4723 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4724 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4725 LocalFree(buf);
4726 }
4727 }
4728
4729 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4730 {
4731 BOOL ret;
4732 LPBYTE buf = NULL;
4733 DWORD size = 0;
4734
4735 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4736 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4737 &buf, &size);
4738 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4739 if (ret)
4740 {
4741 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4742
4743 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4744 "Wrong size %d\n", size);
4745 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4746 usage->cUsageIdentifier);
4747 LocalFree(buf);
4748 }
4749 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4750 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4751 &buf, &size);
4752 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4753 if (ret)
4754 {
4755 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4756 DWORD i;
4757
4758 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4759 "Wrong size %d\n", size);
4760 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4761 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4762 for (i = 0; i < usage->cUsageIdentifier; i++)
4763 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4764 "Expected OID %s, got %s\n", keyUsages[i],
4765 usage->rgpszUsageIdentifier[i]);
4766 LocalFree(buf);
4767 }
4768 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4769 encodedUsage, sizeof(encodedUsage), 0, NULL, NULL, &size);
4770 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4771 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
4772 if (buf)
4773 {
4774 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4775 encodedUsage, sizeof(encodedUsage), 0, NULL, buf, &size);
4776 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4777 HeapFree(GetProcessHeap(), 0, buf);
4778 }
4779 }
4780
4781 static BYTE keyId[] = { 1,2,3,4 };
4782 static const BYTE authorityKeyIdWithId[] = {
4783 0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4784 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4785 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4786 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4787 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4788
4789 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4790 {
4791 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4792 BOOL ret;
4793 BYTE *buf = NULL;
4794 DWORD size = 0;
4795
4796 /* Test with empty id */
4797 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4798 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4799 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4800 if (ret)
4801 {
4802 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4803 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4804 LocalFree(buf);
4805 }
4806 /* With just a key id */
4807 info.KeyId.cbData = sizeof(keyId);
4808 info.KeyId.pbData = keyId;
4809 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4810 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4811 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4812 if (ret)
4813 {
4814 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4815 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4816 LocalFree(buf);
4817 }
4818 /* With just an issuer */
4819 info.KeyId.cbData = 0;
4820 info.CertIssuer.cbData = sizeof(encodedCommonName);
4821 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4822 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4823 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4824 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4825 if (ret)
4826 {
4827 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4828 size);
4829 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4830 LocalFree(buf);
4831 }
4832 /* With just a serial number */
4833 info.CertIssuer.cbData = 0;
4834 info.CertSerialNumber.cbData = sizeof(serialNum);
4835 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4836 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4837 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4838 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4839 if (ret)
4840 {
4841 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4842 size);
4843 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4844 LocalFree(buf);
4845 }
4846 }
4847
4848 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4849 {
4850 BOOL ret;
4851 LPBYTE buf = NULL;
4852 DWORD size = 0;
4853
4854 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4855 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4856 &buf, &size);
4857 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4858 if (ret)
4859 {
4860 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4861
4862 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4863 size);
4864 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4865 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4866 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4867 LocalFree(buf);
4868 }
4869 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4870 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4871 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4872 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4873 if (ret)
4874 {
4875 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4876
4877 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4878 size);
4879 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4880 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4881 "Unexpected key id\n");
4882 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4883 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4884 LocalFree(buf);
4885 }
4886 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4887 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4888 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4889 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4890 if (ret)
4891 {
4892 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4893
4894 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4895 size);
4896 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4897 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4898 "Unexpected issuer len\n");
4899 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4900 sizeof(encodedCommonName)), "Unexpected issuer\n");
4901 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4902 LocalFree(buf);
4903 }
4904 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4905 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4906 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4907 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4908 if (ret)
4909 {
4910 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4911
4912 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4913 size);
4914 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4915 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4916 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4917 "Unexpected serial number len\n");
4918 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4919 "Unexpected serial number\n");
4920 LocalFree(buf);
4921 }
4922 }
4923
4924 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4925 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4926 0x6f,0x72,0x67 };
4927
4928 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4929 {
4930 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4931 CERT_ALT_NAME_ENTRY entry = { 0 };
4932 BOOL ret;
4933 BYTE *buf = NULL;
4934 DWORD size = 0;
4935
4936 /* Test with empty id */
4937 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4938 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4939 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4940 if (ret)
4941 {
4942 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4943 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4944 LocalFree(buf);
4945 }
4946 /* With just a key id */
4947 info.KeyId.cbData = sizeof(keyId);
4948 info.KeyId.pbData = keyId;
4949 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4950 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4951 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4952 if (ret)
4953 {
4954 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4955 size);
4956 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4957 LocalFree(buf);
4958 }
4959 /* With a bogus issuer name */
4960 info.KeyId.cbData = 0;
4961 info.AuthorityCertIssuer.cAltEntry = 1;
4962 info.AuthorityCertIssuer.rgAltEntry = &entry;
4963 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4964 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4965 ok(!ret && GetLastError() == E_INVALIDARG,
4966 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4967 /* With an issuer name */
4968 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4969 U(entry).pwszURL = (LPWSTR)url;
4970 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4971 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4972 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4973 if (ret)
4974 {
4975 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4976 size);
4977 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4978 "Unexpected value\n");
4979 LocalFree(buf);
4980 }
4981 /* With just a serial number */
4982 info.AuthorityCertIssuer.cAltEntry = 0;
4983 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4984 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4985 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4986 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4987 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4988 if (ret)
4989 {
4990 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4991 size);
4992 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4993 LocalFree(buf);
4994 }
4995 }
4996
4997 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4998 {
4999 BOOL ret;
5000 LPBYTE buf = NULL;
5001 DWORD size = 0;
5002
5003 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5004 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5005 &buf, &size);
5006 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5007 if (ret)
5008 {
5009 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5010
5011 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5012 size);
5013 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5014 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5015 "Expected no issuer name entries\n");
5016 ok(info->AuthorityCertSerialNumber.cbData == 0,
5017 "Expected no serial number\n");
5018 LocalFree(buf);
5019 }
5020 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5021 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
5022 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5023 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5024 if (ret)
5025 {
5026 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5027
5028 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5029 size);
5030 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
5031 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
5032 "Unexpected key id\n");
5033 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5034 "Expected no issuer name entries\n");
5035 ok(info->AuthorityCertSerialNumber.cbData == 0,
5036 "Expected no serial number\n");
5037 LocalFree(buf);
5038 }
5039 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5040 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5041 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5042 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5043 if (ret)
5044 {
5045 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5046
5047 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5048 size);
5049 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5050 ok(info->AuthorityCertIssuer.cAltEntry == 1,
5051 "Expected 1 issuer entry, got %d\n",
5052 info->AuthorityCertIssuer.cAltEntry);
5053 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5054 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5055 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5056 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5057 url), "Unexpected URL\n");
5058 ok(info->AuthorityCertSerialNumber.cbData == 0,
5059 "Expected no serial number\n");
5060 LocalFree(buf);
5061 }
5062 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5063 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5064 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5065 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5066 if (ret)
5067 {
5068 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5069
5070 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5071 size);
5072 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5073 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5074 "Expected no issuer name entries\n");
5075 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5076 "Unexpected serial number len\n");
5077 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5078 sizeof(serialNum)), "Unexpected serial number\n");
5079 LocalFree(buf);
5080 }
5081 }
5082
5083 static const BYTE authorityInfoAccessWithUrl[] = {
5084 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5085 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5086 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5087 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5088 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5089 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5090
5091 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5092 {
5093 static char oid1[] = "1.2.3";
5094 static char oid2[] = "1.5.6";
5095 BOOL ret;
5096 BYTE *buf = NULL;
5097 DWORD size = 0;
5098 CERT_ACCESS_DESCRIPTION accessDescription[2];
5099 CERT_AUTHORITY_INFO_ACCESS aia;
5100
5101 memset(accessDescription, 0, sizeof(accessDescription));
5102 aia.cAccDescr = 0;
5103 aia.rgAccDescr = NULL;
5104 /* Having no access descriptions is allowed */
5105 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5106 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5107 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5108 if (ret)
5109 {
5110 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5111 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5112 LocalFree(buf);
5113 buf = NULL;
5114 }
5115 /* It can't have an empty access method */
5116 aia.cAccDescr = 1;
5117 aia.rgAccDescr = accessDescription;
5118 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5119 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5120 ok(!ret && (GetLastError() == E_INVALIDARG ||
5121 GetLastError() == OSS_LIMITED /* Win9x */),
5122 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5123 /* It can't have an empty location */
5124 accessDescription[0].pszAccessMethod = oid1;
5125 SetLastError(0xdeadbeef);
5126 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5127 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5128 ok(!ret && GetLastError() == E_INVALIDARG,
5129 "expected E_INVALIDARG, got %08x\n", GetLastError());
5130 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5131 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5132 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5133 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5134 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5135 if (ret)
5136 {
5137 ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5138 size);
5139 ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5140 "unexpected value\n");
5141 LocalFree(buf);
5142 buf = NULL;
5143 }
5144 accessDescription[1].pszAccessMethod = oid2;
5145 accessDescription[1].AccessLocation.dwAltNameChoice =
5146 CERT_ALT_NAME_IP_ADDRESS;
5147 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5148 sizeof(encodedIPAddr);
5149 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5150 (LPBYTE)encodedIPAddr;
5151 aia.cAccDescr = 2;
5152 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5153 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5154 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5155 if (ret)
5156 {
5157 ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5158 "unexpected size %d\n", size);
5159 ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5160 "unexpected value\n");
5161 LocalFree(buf);
5162 buf = NULL;
5163 }
5164 }
5165
5166 static void compareAuthorityInfoAccess(LPCSTR header,
5167 const CERT_AUTHORITY_INFO_ACCESS *expected,
5168 const CERT_AUTHORITY_INFO_ACCESS *got)
5169 {
5170 DWORD i;
5171
5172 ok(expected->cAccDescr == got->cAccDescr,
5173 "%s: expected %d access descriptions, got %d\n", header,
5174 expected->cAccDescr, got->cAccDescr);
5175 for (i = 0; i < expected->cAccDescr; i++)
5176 {
5177 ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5178 got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5179 header, i, expected->rgAccDescr[i].pszAccessMethod,
5180 got->rgAccDescr[i].pszAccessMethod);
5181 compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5182 &got->rgAccDescr[i].AccessLocation);
5183 }
5184 }
5185
5186 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5187 {
5188 static char oid1[] = "1.2.3";
5189 static char oid2[] = "1.5.6";
5190 BOOL ret;
5191 LPBYTE buf = NULL;
5192 DWORD size = 0;
5193
5194 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5195 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5196 &buf, &size);
5197 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5198 if (ret)
5199 {
5200 CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5201
5202 compareAuthorityInfoAccess("empty AIA", &aia,
5203 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5204 LocalFree(buf);
5205 buf = NULL;
5206 }
5207 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5208 authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5209 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5210 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5211 if (ret)
5212 {
5213 CERT_ACCESS_DESCRIPTION accessDescription;
5214 CERT_AUTHORITY_INFO_ACCESS aia;
5215
5216 accessDescription.pszAccessMethod = oid1;
5217 accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5218 U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5219 aia.cAccDescr = 1;
5220 aia.rgAccDescr = &accessDescription;
5221 compareAuthorityInfoAccess("AIA with URL", &aia,
5222 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5223 LocalFree(buf);
5224 buf = NULL;
5225 }
5226 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5227 authorityInfoAccessWithUrlAndIPAddr,
5228 sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5229 NULL, &buf, &size);
5230 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5231 if (ret)
5232 {
5233 CERT_ACCESS_DESCRIPTION accessDescription[2];
5234 CERT_AUTHORITY_INFO_ACCESS aia;
5235
5236 accessDescription[0].pszAccessMethod = oid1;
5237 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5238 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5239 accessDescription[1].pszAccessMethod = oid2;
5240 accessDescription[1].AccessLocation.dwAltNameChoice =
5241 CERT_ALT_NAME_IP_ADDRESS;
5242 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5243 sizeof(encodedIPAddr);
5244 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5245 (LPBYTE)encodedIPAddr;
5246 aia.cAccDescr = 2;
5247 aia.rgAccDescr = accessDescription;
5248 compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5249 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5250 LocalFree(buf);
5251 buf = NULL;
5252 }
5253 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5254 authorityInfoAccessWithUrlAndIPAddr,
5255 sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, NULL, &size);
5256 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5257 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
5258 if (buf)
5259 {
5260 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5261 authorityInfoAccessWithUrlAndIPAddr,
5262 sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, buf, &size);
5263 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5264 HeapFree(GetProcessHeap(), 0, buf);
5265 }
5266 }
5267
5268 static const BYTE emptyCTL[] = {
5269 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5270 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5271 static const BYTE emptyCTLWithVersion1[] = {
5272 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5273 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5274 static const BYTE ctlWithUsageIdentifier[] = {
5275 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5276 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5277 static const BYTE ctlWithListIdentifier[] = {
5278 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5279 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5280 static const BYTE ctlWithSequenceNumber[] = {
5281 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5282 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5283 static const BYTE ctlWithThisUpdate[] = {
5284 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5285 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5286 static const BYTE ctlWithThisAndNextUpdate[] = {
5287 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5288 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5289 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5290 static const BYTE ctlWithAlgId[] = {
5291 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5292 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5293 static const BYTE ctlWithBogusEntry[] = {
5294 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5295 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5296 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5297 static const BYTE ctlWithOneEntry[] = {
5298 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5299 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5300 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5301 static const BYTE ctlWithTwoEntries[] = {
5302 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5303 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5304 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5305 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5306 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5307
5308 static void test_encodeCTL(DWORD dwEncoding)
5309 {
5310 static char oid1[] = "1.2.3";
5311 static char oid2[] = "1.5.6";
5312 char *pOid1 = oid1;
5313 BOOL ret;
5314 BYTE *buf = NULL;
5315 DWORD size = 0;
5316 CTL_INFO info;
5317 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5318 CTL_ENTRY ctlEntry[2];
5319 CRYPT_ATTRIBUTE attr1, attr2;
5320 CRYPT_ATTR_BLOB value1, value2;
5321
5322 memset(&info, 0, sizeof(info));
5323 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5324 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5325 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5326 if (ret)
5327 {
5328 ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5329 ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5330 LocalFree(buf);
5331 buf = NULL;
5332 }
5333 info.dwVersion = 1;
5334 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5335 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5336 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5337 if (ret)
5338 {
5339 ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5340 ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5341 LocalFree(buf);
5342 buf = NULL;
5343 }
5344 info.dwVersion = 0;
5345 info.SubjectUsage.cUsageIdentifier = 1;
5346 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5347 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5348 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5349 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5350 if (ret)
5351 {
5352 ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5353 size);
5354 ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5355 LocalFree(buf);
5356 buf = NULL;
5357 }
5358 info.SubjectUsage.cUsageIdentifier = 0;
5359 info.ListIdentifier.cbData = sizeof(serialNum);
5360 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5361 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5362 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5363 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5364 if (ret)
5365 {
5366 ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5367 ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5368 LocalFree(buf);
5369 buf = NULL;
5370 }
5371 info.ListIdentifier.cbData = 0;
5372 info.SequenceNumber.cbData = sizeof(serialNum);
5373 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5374 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5375 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5376 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5377 if (ret)
5378 {
5379 ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5380 size);
5381 ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5382 LocalFree(buf);
5383 buf = NULL;
5384 }
5385 info.SequenceNumber.cbData = 0;
5386 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5387 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5388 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5389 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5390 if (ret)
5391 {
5392 ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5393 ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5394 LocalFree(buf);
5395 buf = NULL;
5396 }
5397 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5398 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5399 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5400 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5401 if (ret)
5402 {
5403 ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5404 size);
5405 ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5406 LocalFree(buf);
5407 buf = NULL;
5408 }
5409 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5410 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5411 info.SubjectAlgorithm.pszObjId = oid2;
5412 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5413 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5414 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5415 if (ret)
5416 {
5417 ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5418 ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5419 LocalFree(buf);
5420 buf = NULL;
5421 }
5422 /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5423 * (see tests below) but it'll encode fine.
5424 */
5425 info.SubjectAlgorithm.pszObjId = NULL;
5426 value1.cbData = sizeof(serialNum);
5427 value1.pbData = (LPBYTE)serialNum;
5428 attr1.pszObjId = oid1;
5429 attr1.cValue = 1;
5430 attr1.rgValue = &value1;
5431 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5432 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5433 ctlEntry[0].cAttribute = 1;
5434 ctlEntry[0].rgAttribute = &attr1;
5435 info.cCTLEntry = 1;
5436 info.rgCTLEntry = ctlEntry;
5437 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5438 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5439 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5440 if (ret)
5441 {
5442 ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5443 ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5444 LocalFree(buf);
5445 buf = NULL;
5446 }
5447 value1.cbData = sizeof(emptySequence);
5448 value1.pbData = (LPBYTE)emptySequence;
5449 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5450 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5451 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5452 if (ret)
5453 {
5454 ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5455 ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5456 LocalFree(buf);
5457 buf = NULL;
5458 }
5459 value2.cbData = sizeof(encodedIPAddr);
5460 value2.pbData = (LPBYTE)encodedIPAddr;
5461 attr2.pszObjId = oid2;
5462 attr2.cValue = 1;
5463 attr2.rgValue = &value2;
5464 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5465 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5466 ctlEntry[1].cAttribute = 1;
5467 ctlEntry[1].rgAttribute = &attr2;
5468 info.cCTLEntry = 2;
5469 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5470 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5471 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5472 if (ret)
5473 {
5474 ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5475 ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5476 LocalFree(buf);
5477 buf = NULL;
5478 }
5479 }
5480
5481 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5482 const CTL_INFO *got)
5483 {
5484 DWORD i, j, k;
5485
5486 ok(expected->dwVersion == got->dwVersion,
5487 "%s: expected version %d, got %d\n", header, expected->dwVersion,
5488 got->dwVersion);
5489 ok(expected->SubjectUsage.cUsageIdentifier ==
5490 got->SubjectUsage.cUsageIdentifier,
5491 "%s: expected %d usage identifiers, got %d\n", header,
5492 expected->SubjectUsage.cUsageIdentifier,
5493 got->SubjectUsage.cUsageIdentifier);
5494 for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5495 ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5496 got->SubjectUsage.rgpszUsageIdentifier[i]),
5497 "%s[%d]: expected %s, got %s\n", header, i,
5498 expected->SubjectUsage.rgpszUsageIdentifier[i],
5499 got->SubjectUsage.rgpszUsageIdentifier[i]);
5500 ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5501 "%s: expected list identifier of %d bytes, got %d\n", header,
5502 expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5503 if (expected->ListIdentifier.cbData)
5504 ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5505 expected->ListIdentifier.cbData),
5506 "%s: unexpected list identifier value\n", header);
5507 ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5508 "%s: expected sequence number of %d bytes, got %d\n", header,
5509 expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5510 if (expected->SequenceNumber.cbData)
5511 ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5512 expected->SequenceNumber.cbData),
5513 "%s: unexpected sequence number value\n", header);
5514 ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5515 "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5516 expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5517 got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5518 ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5519 "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5520 expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5521 got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5522 if (expected->SubjectAlgorithm.pszObjId &&
5523 *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5524 ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5525 expected->SubjectAlgorithm.pszObjId);
5526 if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5527 ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5528 got->SubjectAlgorithm.pszObjId),
5529 "%s: expected subject algorithm %s, got %s\n", header,
5530 expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5531 ok(expected->SubjectAlgorithm.Parameters.cbData ==
5532 got->SubjectAlgorithm.Parameters.cbData,
5533 "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5534 expected->SubjectAlgorithm.Parameters.cbData,
5535 got->SubjectAlgorithm.Parameters.cbData);
5536 if (expected->SubjectAlgorithm.Parameters.cbData)
5537 ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5538 got->SubjectAlgorithm.Parameters.pbData,
5539 expected->SubjectAlgorithm.Parameters.cbData),
5540 "%s: unexpected subject algorithm parameter value\n", header);
5541 ok(expected->cCTLEntry == got->cCTLEntry,
5542 "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5543 got->cCTLEntry);
5544 for (i = 0; i < expected->cCTLEntry; i++)
5545 {
5546 ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5547 got->rgCTLEntry[i].SubjectIdentifier.cbData,
5548 "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5549 header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5550 got->rgCTLEntry[i].SubjectIdentifier.cbData);
5551 if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5552 ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5553 got->rgCTLEntry[i].SubjectIdentifier.pbData,
5554 expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5555 "%s[%d]: unexpected subject identifier value\n",
5556 header, i);
5557 for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5558 {
5559 ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5560 got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5561 "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5562 expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5563 got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5564 for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5565 {
5566 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5567 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5568 "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5569 header, i, j, k,
5570 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5571 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5572 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5573 ok(!memcmp(
5574 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5575 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5576 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5577 "%s[%d][%d][%d]: unexpected value\n",
5578 header, i, j, k);
5579 }
5580 }
5581 }
5582 ok(expected->cExtension == got->cExtension,
5583 "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5584 got->cExtension);
5585 for (i = 0; i < expected->cExtension; i++)
5586 {
5587 ok(!strcmp(expected->rgExtension[i].pszObjId,
5588 got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5589 header, i, expected->rgExtension[i].pszObjId,
5590 got->rgExtension[i].pszObjId);
5591 ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5592 "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5593 expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5594 ok(expected->rgExtension[i].Value.cbData ==
5595 got->rgExtension[i].Value.cbData,
5596 "%s[%d]: expected extension value to have %d bytes, got %d\n",
5597 header, i, expected->rgExtension[i].Value.cbData,
5598 got->rgExtension[i].Value.cbData);
5599 if (expected->rgExtension[i].Value.cbData)
5600 ok(!memcmp(expected->rgExtension[i].Value.pbData,
5601 got->rgExtension[i].Value.pbData,
5602 expected->rgExtension[i].Value.cbData),
5603 "%s[%d]: unexpected extension value\n", header, i);
5604 }
5605 }
5606
5607 static const BYTE signedCTL[] = {
5608 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5609 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5610 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5611 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5612 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5613 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5614 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5615 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5616 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5617 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5618 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5619 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5620 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5621 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5622 static const BYTE signedCTLWithCTLInnerContent[] = {
5623 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5624 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5625 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5626 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5627 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5628 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5629 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5630 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5631 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5632 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5633 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5634 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5635 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5636 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5637 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5638 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5639 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5640 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5641 0x57,0x6c,0x0b,0x47,0xb8 };
5642
5643 static void test_decodeCTL(DWORD dwEncoding)
5644 {
5645 static char oid1[] = "1.2.3";
5646 static char oid2[] = "1.5.6";
5647 static BYTE nullData[] = { 5,0 };
5648 char *pOid1 = oid1;
5649 BOOL ret;
5650 BYTE *buf = NULL;
5651 DWORD size = 0;
5652 CTL_INFO info;
5653 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5654 CTL_ENTRY ctlEntry[2];
5655 CRYPT_ATTRIBUTE attr1, attr2;
5656 CRYPT_ATTR_BLOB value1, value2;
5657
5658 memset(&info, 0, sizeof(info));
5659 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5660 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5661 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5662 if (ret)
5663 {
5664 compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5665 LocalFree(buf);
5666 buf = NULL;
5667 }
5668 info.dwVersion = 1;
5669 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5670 sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5671 &size);
5672 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5673 if (ret)
5674 {
5675 compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5676 LocalFree(buf);
5677 buf = NULL;
5678 }
5679 info.dwVersion = 0;
5680 info.SubjectUsage.cUsageIdentifier = 1;
5681 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5682 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5683 sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5684 &buf, &size);
5685 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5686 if (ret)
5687 {
5688 compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5689 LocalFree(buf);
5690 buf = NULL;
5691 }
5692 info.SubjectUsage.cUsageIdentifier = 0;
5693 info.ListIdentifier.cbData = sizeof(serialNum);
5694 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5695 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5696 sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5697 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5698 if (ret)
5699 {
5700 compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5701 LocalFree(buf);
5702 buf = NULL;
5703 }
5704 info.ListIdentifier.cbData = 0;
5705 info.SequenceNumber.cbData = sizeof(serialNum);
5706 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5707 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5708 sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5709 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5710 if (ret)
5711 {
5712 compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5713 LocalFree(buf);
5714 buf = NULL;
5715 }
5716 info.SequenceNumber.cbData = 0;
5717 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5718 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5719 sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5720 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5721 if (ret)
5722 {
5723 compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5724 LocalFree(buf);
5725 buf = NULL;
5726 }
5727 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5728 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5729 sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5730 &buf, &size);
5731 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5732 if (ret)
5733 {
5734 compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5735 LocalFree(buf);
5736 buf = NULL;
5737 }
5738 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5739 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5740 info.SubjectAlgorithm.pszObjId = oid2;
5741 info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5742 info.SubjectAlgorithm.Parameters.pbData = nullData;
5743 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5744 sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5745 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5746 if (ret)
5747 {
5748 compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5749 LocalFree(buf);
5750 buf = NULL;
5751 }
5752 SetLastError(0xdeadbeef);
5753 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5754 sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5755 ok(!ret &&
5756 (GetLastError() == CRYPT_E_ASN1_EOD ||
5757 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5758 GetLastError() == OSS_MORE_INPUT), /* Win9x */
5759 "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5760 GetLastError());
5761 info.SubjectAlgorithm.Parameters.cbData = 0;
5762 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5763 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5764 info.SubjectAlgorithm.pszObjId = oid2;
5765 info.SubjectAlgorithm.pszObjId = NULL;
5766 value1.cbData = sizeof(emptySequence);
5767 value1.pbData = (LPBYTE)emptySequence;
5768 attr1.pszObjId = oid1;
5769 attr1.cValue = 1;
5770 attr1.rgValue = &value1;
5771 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5772 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5773 ctlEntry[0].cAttribute = 1;
5774 ctlEntry[0].rgAttribute = &attr1;
5775 info.cCTLEntry = 1;
5776 info.rgCTLEntry = ctlEntry;
5777 SetLastError(0xdeadbeef);
5778 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5779 sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5780 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5781 if (ret)
5782 {
5783 compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5784 LocalFree(buf);
5785 buf = NULL;
5786 }
5787 value2.cbData = sizeof(encodedIPAddr);
5788 value2.pbData = (LPBYTE)encodedIPAddr;
5789 attr2.pszObjId = oid2;
5790 attr2.cValue = 1;
5791 attr2.rgValue = &value2;
5792 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5793 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5794 ctlEntry[1].cAttribute = 1;
5795 ctlEntry[1].rgAttribute = &attr2;
5796 info.cCTLEntry = 2;
5797 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5798 sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5799 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5800 if (ret)
5801 {
5802 compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5803 LocalFree(buf);
5804 buf = NULL;
5805 }
5806 /* A signed CTL isn't decodable, even if the inner content is a CTL */
5807 SetLastError(0xdeadbeef);
5808 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5809 sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5810 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5811 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5812 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5813 GetLastError());
5814 SetLastError(0xdeadbeef);
5815 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5816 signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5817 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5818 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5819 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5820 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5821 GetLastError());
5822 }
5823
5824 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5825 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5826 0x03,0,0,0,0,0,0 };
5827 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5828 0xa0,0x01,0x01 };
5829 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5830 0x03,0x02,0x01,0x01 };
5831 static BYTE bogusDER[] = { 1 };
5832
5833 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5834 {
5835 BOOL ret;
5836 BYTE *buf = NULL;
5837 DWORD size = 0;
5838 CRYPT_CONTENT_INFO info = { 0 };
5839 char oid1[] = "1.2.3";
5840
5841 if (0)
5842 {
5843 /* Crashes on win9x */
5844 SetLastError(0xdeadbeef);
5845 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5846 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5847 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5848 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5849 }
5850 SetLastError(0xdeadbeef);
5851 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5852 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5853 ok(!ret && (GetLastError() == E_INVALIDARG ||
5854 GetLastError() == OSS_LIMITED /* Win9x */),
5855 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5856 info.pszObjId = oid1;
5857 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5858 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5859 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5860 if (ret)
5861 {
5862 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5863 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5864 LocalFree(buf);
5865 }
5866 info.Content.pbData = bogusDER;
5867 info.Content.cbData = sizeof(bogusDER);
5868 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5869 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5870 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5871 if (ret)
5872 {
5873 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5874 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5875 LocalFree(buf);
5876 }
5877 info.Content.pbData = (BYTE *)ints[0].encoded;
5878 info.Content.cbData = ints[0].encoded[1] + 2;
5879 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5880 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5881 if (ret)
5882 {
5883 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5884 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5885 LocalFree(buf);
5886 }
5887 }
5888
5889 static const BYTE indefiniteSignedPKCSContent[] = {
5890 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5891 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5892 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5893 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5894 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5895 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5896 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5897 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5898 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5899 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5900 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5901 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5902 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5903 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5904 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5905 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5906 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5907 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5908 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5909 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5910 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5911 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5912 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5913 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5914 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5915 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5916 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5917 0x00,0x00,0x00,0x00,0x00,0x00 };
5918
5919 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5920 {
5921 BOOL ret;
5922 LPBYTE buf = NULL;
5923 DWORD size = 0;
5924 CRYPT_CONTENT_INFO *info;
5925
5926 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5927 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5928 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5929 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5930 if (ret)
5931 {
5932 info = (CRYPT_CONTENT_INFO *)buf;
5933
5934 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5935 info->pszObjId);
5936 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5937 info->Content.cbData);
5938 LocalFree(buf);
5939 }
5940 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5941 emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5942 0, NULL, NULL, &size);
5943 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5944 SetLastError(0xdeadbeef);
5945 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5946 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5947 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5948 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5949 * I doubt an app depends on that.
5950 */
5951 ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5952 GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5953 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5954 GetLastError());
5955 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5956 intPKCSContentInfo, sizeof(intPKCSContentInfo),
5957 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5958 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5959 if (ret)
5960 {
5961 info = (CRYPT_CONTENT_INFO *)buf;
5962
5963 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5964 info->pszObjId);
5965 ok(info->Content.cbData == ints[0].encoded[1] + 2,
5966 "Unexpected size %d\n", info->Content.cbData);
5967 ok(!memcmp(info->Content.pbData, ints[0].encoded,
5968 info->Content.cbData), "Unexpected value\n");
5969 LocalFree(buf);
5970 }
5971 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5972 indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5973 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5974 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5975 if (ret)
5976 {
5977 info = (CRYPT_CONTENT_INFO *)buf;
5978
5979 ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5980 "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5981 ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5982 info->Content.cbData);
5983 LocalFree(buf);
5984 }
5985 }
5986
5987 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5988 0x00 };
5989 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5990 0x01 };
5991 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5992 0x02,0x01,0x01 };
5993
5994 static void test_encodePKCSAttribute(DWORD dwEncoding)
5995 {
5996 CRYPT_ATTRIBUTE attr = { 0 };
5997 BOOL ret;
5998 LPBYTE buf = NULL;
5999 DWORD size = 0;
6000 CRYPT_ATTR_BLOB blob;
6001 char oid[] = "1.2.3";
6002
6003 if (0)
6004 {
6005 /* Crashes on win9x */
6006 SetLastError(0xdeadbeef);
6007 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
6008 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6009 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
6010 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
6011 }
6012 SetLastError(0xdeadbeef);
6013 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6014 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6015 ok(!ret && (GetLastError() == E_INVALIDARG ||
6016 GetLastError() == OSS_LIMITED /* Win9x */),
6017 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
6018 attr.pszObjId = oid;
6019 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6020 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6021 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6022 if (ret)
6023 {
6024 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
6025 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
6026 LocalFree(buf);
6027 }
6028 blob.cbData = sizeof(bogusDER);
6029 blob.pbData = bogusDER;
6030 attr.cValue = 1;
6031 attr.rgValue = &blob;
6032 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6033 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6034 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6035 if (ret)
6036 {
6037 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
6038 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
6039 LocalFree(buf);
6040 }
6041 blob.pbData = (BYTE *)ints[0].encoded;
6042 blob.cbData = ints[0].encoded[1] + 2;
6043 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
6044 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6045 if (ret)
6046 {
6047 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6048 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6049 LocalFree(buf);
6050 }
6051 }
6052
6053 static void test_decodePKCSAttribute(DWORD dwEncoding)
6054 {
6055 BOOL ret;
6056 LPBYTE buf = NULL;
6057 DWORD size = 0;
6058 CRYPT_ATTRIBUTE *attr;
6059
6060 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6061 emptyPKCSAttr, sizeof(emptyPKCSAttr),
6062 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6063 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6064 if (ret)
6065 {
6066 attr = (CRYPT_ATTRIBUTE *)buf;
6067
6068 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6069 attr->pszObjId);
6070 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6071 LocalFree(buf);
6072 }
6073 SetLastError(0xdeadbeef);
6074 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6075 bogusPKCSAttr, sizeof(bogusPKCSAttr),
6076 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6077 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6078 * I doubt an app depends on that.
6079 */
6080 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6081 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6082 GetLastError() == OSS_MORE_INPUT /* Win9x */),
6083 "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6084 GetLastError());
6085 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6086 intPKCSAttr, sizeof(intPKCSAttr),
6087 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6088 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6089 if (ret)
6090 {
6091 attr = (CRYPT_ATTRIBUTE *)buf;
6092
6093 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6094 attr->pszObjId);
6095 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6096 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6097 "Unexpected size %d\n", attr->rgValue[0].cbData);
6098 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6099 attr->rgValue[0].cbData), "Unexpected value\n");
6100 LocalFree(buf);
6101 }
6102 }
6103
6104 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6105 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6106 0x2a,0x03,0x31,0x00 };
6107 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6108 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6109
6110 static void test_encodePKCSAttributes(DWORD dwEncoding)
6111 {
6112 CRYPT_ATTRIBUTES attributes = { 0 };
6113 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6114 CRYPT_ATTR_BLOB blob;
6115 BOOL ret;
6116 LPBYTE buf = NULL;
6117 DWORD size = 0;
6118 char oid1[] = "1.2.3", oid2[] = "1.5.6";
6119
6120 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6121 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6122 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6123 if (ret)
6124 {
6125 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6126 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6127 LocalFree(buf);
6128 }
6129 attributes.cAttr = 1;
6130 attributes.rgAttr = attr;
6131 SetLastError(0xdeadbeef);
6132 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6133 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6134 ok(!ret && (GetLastError() == E_INVALIDARG ||
6135 GetLastError() == OSS_LIMITED /* Win9x */),
6136 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6137 attr[0].pszObjId = oid1;
6138 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6139 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6140 if (ret)
6141 {
6142 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6143 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6144 LocalFree(buf);
6145 }
6146 attr[1].pszObjId = oid2;
6147 attr[1].cValue = 1;
6148 attr[1].rgValue = &blob;
6149 blob.pbData = (BYTE *)ints[0].encoded;
6150 blob.cbData = ints[0].encoded[1] + 2;
6151 attributes.cAttr = 2;
6152 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6153 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6154 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6155 if (ret)
6156 {
6157 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6158 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6159 LocalFree(buf);
6160 }
6161 }
6162
6163 static void test_decodePKCSAttributes(DWORD dwEncoding)
6164 {
6165 BOOL ret;
6166 LPBYTE buf = NULL;
6167 DWORD size = 0;
6168 CRYPT_ATTRIBUTES *attributes;
6169
6170 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6171 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6172 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6173 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6174 if (ret)
6175 {
6176 attributes = (CRYPT_ATTRIBUTES *)buf;
6177 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6178 attributes->cAttr);
6179 LocalFree(buf);
6180 }
6181 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6182 singlePKCSAttributes, sizeof(singlePKCSAttributes),
6183 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6184 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6185 if (ret)
6186 {
6187 attributes = (CRYPT_ATTRIBUTES *)buf;
6188 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6189 attributes->cAttr);
6190 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6191 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6192 ok(attributes->rgAttr[0].cValue == 0,
6193 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6194 LocalFree(buf);
6195 }
6196 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6197 doublePKCSAttributes, sizeof(doublePKCSAttributes),
6198 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6199 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6200 if (ret)
6201 {
6202 attributes = (CRYPT_ATTRIBUTES *)buf;
6203 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6204 attributes->cAttr);
6205 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6206 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6207 ok(attributes->rgAttr[0].cValue == 0,
6208 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6209 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6210 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6211 ok(attributes->rgAttr[1].cValue == 1,
6212 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6213 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6214 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6215 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6216 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6217 LocalFree(buf);
6218 }
6219 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6220 doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, NULL, &size);
6221 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6222 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6223 if (buf)
6224 {
6225 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6226 doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, buf, &size);
6227 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6228 HeapFree(GetProcessHeap(), 0, buf);
6229 }
6230 }
6231
6232 static const BYTE singleCapability[] = {
6233 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6234 static const BYTE twoCapabilities[] = {
6235 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6236 static const BYTE singleCapabilitywithNULL[] = {
6237 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6238
6239 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6240 {
6241 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6242 BOOL ret;
6243 LPBYTE buf = NULL;
6244 DWORD size = 0;
6245 CRYPT_SMIME_CAPABILITY capability[2];
6246 CRYPT_SMIME_CAPABILITIES capabilities;
6247
6248 /* An empty capabilities is allowed */
6249 capabilities.cCapability = 0;
6250 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6251 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6252 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6253 if (ret)
6254 {
6255 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6256 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6257 LocalFree(buf);
6258 }
6259 /* A non-empty capabilities with an empty capability (lacking an OID) is
6260 * not allowed
6261 */
6262 capability[0].pszObjId = NULL;
6263 capability[0].Parameters.cbData = 0;
6264 capabilities.cCapability = 1;
6265 capabilities.rgCapability = capability;
6266 SetLastError(0xdeadbeef);
6267 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6268 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6269 ok(!ret && (GetLastError() == E_INVALIDARG ||
6270 GetLastError() == OSS_LIMITED /* Win9x */),
6271 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6272 capability[0].pszObjId = oid1;
6273 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6274 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6275 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6276 if (ret)
6277 {
6278 ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6279 ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6280 LocalFree(buf);
6281 }
6282 capability[1].pszObjId = oid2;
6283 capability[1].Parameters.cbData = 0;
6284 capabilities.cCapability = 2;
6285 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6286 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6287 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6288 if (ret)
6289 {
6290 ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6291 ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6292 LocalFree(buf);
6293 }
6294 }
6295
6296 static void compareSMimeCapabilities(LPCSTR header,
6297 const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6298 {
6299 DWORD i;
6300
6301 ok(got->cCapability == expected->cCapability,
6302 "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6303 got->cCapability);
6304 for (i = 0; i < expected->cCapability; i++)
6305 {
6306 ok(!strcmp(expected->rgCapability[i].pszObjId,
6307 got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6308 header, i, expected->rgCapability[i].pszObjId,
6309 got->rgCapability[i].pszObjId);
6310 ok(expected->rgCapability[i].Parameters.cbData ==
6311 got->rgCapability[i].Parameters.cbData,
6312 "%s[%d]: expected %d bytes, got %d\n", header, i,
6313 expected->rgCapability[i].Parameters.cbData,
6314 got->rgCapability[i].Parameters.cbData);
6315 if (expected->rgCapability[i].Parameters.cbData)
6316 ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6317 got->rgCapability[i].Parameters.pbData,
6318 expected->rgCapability[i].Parameters.cbData),
6319 "%s[%d]: unexpected value\n", header, i);
6320 }
6321 }
6322
6323 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6324 {
6325 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6326 BOOL ret;
6327 DWORD size = 0;
6328 CRYPT_SMIME_CAPABILITY capability[2];
6329 CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6330
6331 SetLastError(0xdeadbeef);
6332 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6333 emptySequence, sizeof(emptySequence),
6334 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6335 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6336 if (ret)
6337 {
6338 capabilities.cCapability = 0;
6339 compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6340 LocalFree(ptr);
6341 }
6342 SetLastError(0xdeadbeef);
6343 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6344 singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6345 &ptr, &size);
6346 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6347 if (ret)
6348 {
6349 capability[0].pszObjId = oid1;
6350 capability[0].Parameters.cbData = 0;
6351 capabilities.cCapability = 1;
6352 capabilities.rgCapability = capability;
6353 compareSMimeCapabilities("single capability", &capabilities, ptr);
6354 LocalFree(ptr);
6355 }
6356 SetLastError(0xdeadbeef);
6357 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6358 singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6359 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6360 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6361 if (ret)
6362 {
6363 BYTE NULLparam[] = {0x05, 0x00};
6364 capability[0].pszObjId = oid1;
6365 capability[0].Parameters.cbData = 2;
6366 capability[0].Parameters.pbData = NULLparam;
6367 capabilities.cCapability = 1;
6368 capabilities.rgCapability = capability;
6369 compareSMimeCapabilities("single capability with NULL", &capabilities,
6370 ptr);
6371 LocalFree(ptr);
6372 }
6373 SetLastError(0xdeadbeef);
6374 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6375 twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6376 &ptr, &size);
6377 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6378 if (ret)
6379 {
6380 capability[0].Parameters.cbData = 0;
6381 capability[1].pszObjId = oid2;
6382 capability[1].Parameters.cbData = 0;
6383 capabilities.cCapability = 2;
6384 compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6385 LocalFree(ptr);
6386 }
6387 SetLastError(0xdeadbeef);
6388 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6389 twoCapabilities, sizeof(twoCapabilities), 0, NULL, NULL, &size);
6390 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6391 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
6392 if (ptr)
6393 {
6394 SetLastError(0xdeadbeef);
6395 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6396 twoCapabilities, sizeof(twoCapabilities), 0, NULL, ptr, &size);
6397 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6398 HeapFree(GetProcessHeap(), 0, ptr);
6399 }
6400 }
6401
6402 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6403 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6404 0x67 };
6405 static const BYTE minimalPKCSSigner[] = {
6406 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6407 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6408 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6409 static const BYTE PKCSSignerWithSerial[] = {
6410 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6411 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6412 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6413 0x00 };
6414 static const BYTE PKCSSignerWithHashAlgo[] = {
6415 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6416 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6417 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6418 0x00,0x04,0x00 };
6419 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6420 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6421 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6422 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6423 0x06,0x05,0x00,0x04,0x00 };
6424 static const BYTE PKCSSignerWithHash[] = {
6425 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6426 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6427 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6428 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6429 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6430 static const BYTE PKCSSignerWithAuthAttr[] = {
6431 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6432 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6433 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6434 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6435 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6436 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6437 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6438
6439 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6440 {
6441 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6442 BOOL ret;
6443 LPBYTE buf = NULL;
6444 DWORD size = 0;
6445 CMSG_SIGNER_INFO info = { 0 };
6446 char oid_common_name[] = szOID_COMMON_NAME;
6447 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6448 (LPBYTE)encodedCommonName };
6449 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6450
6451 SetLastError(0xdeadbeef);
6452 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6453 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6454 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6455 {
6456 skip("no PKCS7_SIGNER_INFO encode support\n");
6457 return;
6458 }
6459 ok(!ret && (GetLastError() == E_INVALIDARG ||
6460 GetLastError() == OSS_LIMITED /* Win9x */),
6461 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6462 /* To be encoded, a signer must have an issuer at least, and the encoding
6463 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
6464 * see decoding tests.)
6465 */
6466 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6467 info.Issuer.pbData = encodedCommonNameNoNull;
6468 SetLastError(0xdeadbeef);
6469 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6470 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6471 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6472 ok(!ret && GetLastError() == E_INVALIDARG,
6473 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6474 else
6475 {
6476 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6477 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6478 if (ret)
6479 {
6480 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6481 if (size == sizeof(minimalPKCSSigner))
6482 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6483 else
6484 ok(0, "Unexpected value\n");
6485 LocalFree(buf);
6486 }
6487 }
6488 info.SerialNumber.cbData = sizeof(serialNum);
6489 info.SerialNumber.pbData = (BYTE *)serialNum;
6490 SetLastError(0xdeadbeef);
6491 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6492 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6493 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6494 ok(!ret && GetLastError() == E_INVALIDARG,
6495 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6496 else
6497 {
6498 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6499 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6500 if (ret)
6501 {
6502 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6503 size);
6504 if (size == sizeof(PKCSSignerWithSerial))
6505 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6506 "Unexpected value\n");
6507 else
6508 ok(0, "Unexpected value\n");
6509 LocalFree(buf);
6510 }
6511 }
6512 info.HashAlgorithm.pszObjId = oid1;
6513 SetLastError(0xdeadbeef);
6514 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6515 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6516 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6517 ok(!ret && GetLastError() == E_INVALIDARG,
6518 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6519 else
6520 {
6521 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6522 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6523 if (ret)
6524 {
6525 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6526 size);
6527 if (size == sizeof(PKCSSignerWithHashAlgo))
6528 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6529 "Unexpected value\n");
6530 else
6531 ok(0, "Unexpected value\n");
6532 LocalFree(buf);
6533 }
6534 }
6535 info.HashEncryptionAlgorithm.pszObjId = oid2;
6536 SetLastError(0xdeadbeef);
6537 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6538 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6539 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6540 ok(!ret && GetLastError() == E_INVALIDARG,
6541 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6542 else
6543 {
6544 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6545 if (ret)
6546 {
6547 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6548 "Unexpected size %d\n", size);
6549 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6550 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6551 "Unexpected value\n");
6552 else
6553 ok(0, "Unexpected value\n");
6554 LocalFree(buf);
6555 }
6556 }
6557 info.EncryptedHash.cbData = sizeof(hash);
6558 info.EncryptedHash.pbData = (BYTE *)hash;
6559 SetLastError(0xdeadbeef);
6560 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6561 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6562 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6563 ok(!ret && GetLastError() == E_INVALIDARG,
6564 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6565 else
6566 {
6567 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6568 if (ret)
6569 {
6570 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6571 size);
6572 if (size == sizeof(PKCSSignerWithHash))
6573 ok(!memcmp(buf, PKCSSignerWithHash, size),
6574 "Unexpected value\n");
6575 else
6576 ok(0, "Unexpected value\n");
6577 LocalFree(buf);
6578 }
6579 }
6580 info.AuthAttrs.cAttr = 1;
6581 info.AuthAttrs.rgAttr = &attr;
6582 SetLastError(0xdeadbeef);
6583 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6584 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6585 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6586 ok(!ret && GetLastError() == E_INVALIDARG,
6587 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6588 else
6589 {
6590 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6591 if (ret)
6592 {
6593 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6594 size);
6595 if (size == sizeof(PKCSSignerWithAuthAttr))
6596 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6597 "Unexpected value\n");
6598 else
6599 ok(0, "Unexpected value\n");
6600 LocalFree(buf);
6601 }
6602 }
6603 }
6604
6605 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6606 {
6607 BOOL ret;
6608 LPBYTE buf = NULL;
6609 DWORD size = 0;
6610 CMSG_SIGNER_INFO *info;
6611
6612 /* A PKCS signer can't be decoded without a serial number. */
6613 SetLastError(0xdeadbeef);
6614 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6615 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6616 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6617 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6618 GetLastError() == OSS_DATA_ERROR /* Win9x */),
6619 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6620 GetLastError());
6621 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6622 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6623 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6624 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6625 "CryptDecodeObjectEx failed: %x\n", GetLastError());
6626 if (ret)
6627 {
6628 info = (CMSG_SIGNER_INFO *)buf;
6629 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6630 info->dwVersion);
6631 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6632 "Unexpected size %d\n", info->Issuer.cbData);
6633 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6634 info->Issuer.cbData), "Unexpected value\n");
6635 ok(info->SerialNumber.cbData == sizeof(serialNum),
6636 "Unexpected size %d\n", info->SerialNumber.cbData);
6637 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6638 "Unexpected value\n");
6639 LocalFree(buf);
6640 }
6641 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6642 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6643 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6644 if (ret)
6645 {
6646 info = (CMSG_SIGNER_INFO *)buf;
6647 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6648 info->dwVersion);
6649 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6650 "Unexpected size %d\n", info->Issuer.cbData);
6651 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6652 info->Issuer.cbData), "Unexpected value\n");
6653 ok(info->SerialNumber.cbData == sizeof(serialNum),
6654 "Unexpected size %d\n", info->SerialNumber.cbData);
6655 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6656 "Unexpected value\n");
6657 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6658 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6659 LocalFree(buf);
6660 }
6661 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6662 PKCSSignerWithHashAndEncryptionAlgo,
6663 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6664 NULL, &buf, &size);
6665 if (ret)
6666 {
6667 info = (CMSG_SIGNER_INFO *)buf;
6668 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6669 info->dwVersion);
6670 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6671 "Unexpected size %d\n", info->Issuer.cbData);
6672 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6673 info->Issuer.cbData), "Unexpected value\n");
6674 ok(info->SerialNumber.cbData == sizeof(serialNum),
6675 "Unexpected size %d\n", info->SerialNumber.cbData);
6676 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6677 "Unexpected value\n");
6678 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6679 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6680 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6681 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6682 LocalFree(buf);
6683 }
6684 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6685 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6686 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6687 if (ret)
6688 {
6689 info = (CMSG_SIGNER_INFO *)buf;
6690 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6691 info->dwVersion);
6692 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6693 "Unexpected size %d\n", info->Issuer.cbData);
6694 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6695 info->Issuer.cbData), "Unexpected value\n");
6696 ok(info->SerialNumber.cbData == sizeof(serialNum),
6697 "Unexpected size %d\n", info->SerialNumber.cbData);
6698 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6699 "Unexpected value\n");
6700 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6701 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6702 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6703 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6704 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6705 info->EncryptedHash.cbData);
6706 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6707 "Unexpected value\n");
6708 LocalFree(buf);
6709 }
6710 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6711 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6712 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6713 if (ret)
6714 {
6715 info = (CMSG_SIGNER_INFO *)buf;
6716 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6717 info->AuthAttrs.cAttr);
6718 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6719 "Expected %s, got %s\n", szOID_COMMON_NAME,
6720 info->AuthAttrs.rgAttr[0].pszObjId);
6721 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6722 info->AuthAttrs.rgAttr[0].cValue);
6723 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6724 sizeof(encodedCommonName), "Unexpected size %d\n",
6725 info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6726 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6727 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6728 LocalFree(buf);
6729 }
6730 }
6731
6732 static const BYTE CMSSignerWithKeyId[] = {
6733 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6734 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6735
6736 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6737 {
6738 BOOL ret;
6739 LPBYTE buf = NULL;
6740 DWORD size = 0;
6741 CMSG_CMS_SIGNER_INFO info = { 0 };
6742 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6743
6744 SetLastError(0xdeadbeef);
6745 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6746 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6747 ok(!ret, "Expected failure, got %d\n", ret);
6748 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6749 {
6750 skip("no CMS_SIGNER_INFO encode support\n");
6751 return;
6752 }
6753 ok(GetLastError() == E_INVALIDARG,
6754 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6755 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6756 SetLastError(0xdeadbeef);
6757 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6758 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6759 ok(!ret, "Expected failure, got %d\n", ret);
6760 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6761 {
6762 skip("no CMS_SIGNER_INFO encode support\n");
6763 return;
6764 }
6765 ok(GetLastError() == E_INVALIDARG,
6766 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6767 /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6768 * be a key id or a issuer serial number with at least the issuer set, and
6769 * the encoding must include PKCS_7_ASN_ENCODING.
6770 * (That isn't enough to be decoded, see decoding tests.)
6771 */
6772 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6773 sizeof(encodedCommonNameNoNull);
6774 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6775 SetLastError(0xdeadbeef);
6776 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6777 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6778 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6779 ok(!ret && GetLastError() == E_INVALIDARG,
6780 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6781 else
6782 {
6783 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6784 if (ret)
6785 {
6786 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6787 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6788 LocalFree(buf);
6789 }
6790 }
6791 U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6792 U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6793 SetLastError(0xdeadbeef);
6794 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6795 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6796 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6797 ok(!ret && GetLastError() == E_INVALIDARG,
6798 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6799 else
6800 {
6801 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6802 if (ret)
6803 {
6804 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6805 size);
6806 ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6807 LocalFree(buf);
6808 }
6809 }
6810 info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6811 U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6812 U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6813 SetLastError(0xdeadbeef);
6814 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6815 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6816 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6817 ok(!ret && GetLastError() == E_INVALIDARG,
6818 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6819 else
6820 {
6821 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6822 if (ret)
6823 {
6824 ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6825 size);
6826 ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6827 LocalFree(buf);
6828 }
6829 }
6830 /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6831 * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6832 * (see RFC 3852, section 5.3.)
6833 */
6834 info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6835 U(info.SignerId).HashId.cbData = sizeof(hash);
6836 U(info.SignerId).HashId.pbData = (BYTE *)hash;
6837 SetLastError(0xdeadbeef);
6838 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6839 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6840 ok(!ret && GetLastError() == E_INVALIDARG,
6841 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6842 /* Now with a hash algo */
6843 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6844 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6845 sizeof(encodedCommonNameNoNull);
6846 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6847 info.HashAlgorithm.pszObjId = oid1;
6848 SetLastError(0xdeadbeef);
6849 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6850 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6851 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6852 ok(!ret && GetLastError() == E_INVALIDARG,
6853 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6854 else
6855 {
6856 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6857 if (ret)
6858 {
6859 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6860 size);
6861 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6862 "Unexpected value\n");
6863 LocalFree(buf);
6864 }
6865 }
6866 info.HashEncryptionAlgorithm.pszObjId = oid2;
6867 SetLastError(0xdeadbeef);
6868 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6869 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6870 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6871 ok(!ret && GetLastError() == E_INVALIDARG,
6872 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6873 else
6874 {
6875 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6876 if (ret)
6877 {
6878 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6879 "Unexpected size %d\n", size);
6880 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6881 "Unexpected value\n");
6882 LocalFree(buf);
6883 }
6884 }
6885 info.EncryptedHash.cbData = sizeof(hash);
6886 info.EncryptedHash.pbData = (BYTE *)hash;
6887 SetLastError(0xdeadbeef);
6888 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6889 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6890 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6891 ok(!ret && GetLastError() == E_INVALIDARG,
6892 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6893 else
6894 {
6895 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6896 if (ret)
6897 {
6898 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6899 size);
6900 ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6901 LocalFree(buf);
6902 }
6903 }
6904 }
6905
6906 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6907 {
6908 BOOL ret;
6909 LPBYTE buf = NULL;
6910 DWORD size = 0;
6911 CMSG_CMS_SIGNER_INFO *info;
6912 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6913
6914 /* A CMS signer can't be decoded without a serial number. */
6915 SetLastError(0xdeadbeef);
6916 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6917 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6918 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6919 ok(!ret, "expected failure\n");
6920 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6921 {
6922 skip("no CMS_SIGNER_INFO decode support\n");
6923 return;
6924 }
6925 ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6926 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6927 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6928 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6929 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6930 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6931 if (ret)
6932 {
6933 info = (CMSG_CMS_SIGNER_INFO *)buf;
6934 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6935 info->dwVersion);
6936 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6937 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6938 info->SignerId.dwIdChoice);
6939 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6940 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6941 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6942 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6943 encodedCommonNameNoNull,
6944 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6945 "Unexpected value\n");
6946 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6947 sizeof(serialNum), "Unexpected size %d\n",
6948 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6949 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6950 serialNum, sizeof(serialNum)), "Unexpected value\n");
6951 LocalFree(buf);
6952 }
6953 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6954 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6955 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6956 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6957 if (ret)
6958 {
6959 info = (CMSG_CMS_SIGNER_INFO *)buf;
6960 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6961 info->dwVersion);
6962 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6963 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6964 info->SignerId.dwIdChoice);
6965 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6966 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6967 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6968 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6969 encodedCommonNameNoNull,
6970 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6971 "Unexpected value\n");
6972 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6973 sizeof(serialNum), "Unexpected size %d\n",
6974 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6975 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6976 serialNum, sizeof(serialNum)), "Unexpected value\n");
6977 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6978 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6979 LocalFree(buf);
6980 }
6981 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6982 PKCSSignerWithHashAndEncryptionAlgo,
6983 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6984 NULL, &buf, &size);
6985 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6986 if (ret)
6987 {
6988 info = (CMSG_CMS_SIGNER_INFO *)buf;
6989 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6990 info->dwVersion);
6991 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6992 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6993 info->SignerId.dwIdChoice);
6994 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6995 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6996 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6997 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6998 encodedCommonNameNoNull,
6999 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7000 "Unexpected value\n");
7001 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7002 sizeof(serialNum), "Unexpected size %d\n",
7003 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7004 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7005 serialNum, sizeof(serialNum)), "Unexpected value\n");
7006 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7007 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7008 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7009 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7010 LocalFree(buf);
7011 }
7012 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7013 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
7014 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7015 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7016 if (ret)
7017 {
7018 info = (CMSG_CMS_SIGNER_INFO *)buf;
7019 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7020 info->dwVersion);
7021 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
7022 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
7023 info->SignerId.dwIdChoice);
7024 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
7025 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
7026 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
7027 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
7028 encodedCommonNameNoNull,
7029 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
7030 "Unexpected value\n");
7031 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
7032 sizeof(serialNum), "Unexpected size %d\n",
7033 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
7034 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
7035 serialNum, sizeof(serialNum)), "Unexpected value\n");
7036 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
7037 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
7038 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
7039 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
7040 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
7041 info->EncryptedHash.cbData);
7042 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
7043 "Unexpected value\n");
7044 LocalFree(buf);
7045 }
7046 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
7047 CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
7048 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
7049 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
7050 if (ret)
7051 {
7052 info = (CMSG_CMS_SIGNER_INFO *)buf;
7053 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
7054 info->dwVersion);
7055 ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
7056 "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
7057 info->SignerId.dwIdChoice);
7058 ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
7059 "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
7060 ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
7061 "Unexpected value\n");
7062 LocalFree(buf);
7063 }
7064 }
7065
7066 static BYTE emptyDNSPermittedConstraints[] = {
7067 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
7068 static BYTE emptyDNSExcludedConstraints[] = {
7069 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
7070 static BYTE DNSExcludedConstraints[] = {
7071 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7072 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7073 static BYTE permittedAndExcludedConstraints[] = {
7074 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7075 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7076 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7077 static BYTE permittedAndExcludedWithMinConstraints[] = {
7078 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7079 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7080 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7081 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7082 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7083 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7084 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7085
7086 static void test_encodeNameConstraints(DWORD dwEncoding)
7087 {
7088 BOOL ret;
7089 CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7090 CERT_GENERAL_SUBTREE permitted = { { 0 } };
7091 CERT_GENERAL_SUBTREE excluded = { { 0 } };
7092 LPBYTE buf;
7093 DWORD size;
7094
7095 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7096 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7097 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7098 {
7099 skip("no X509_NAME_CONSTRAINTS encode support\n");
7100 return;
7101 }
7102 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7103 if (ret)
7104 {
7105 ok(size == sizeof(emptySequence), "Unexpected size\n");
7106 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7107 LocalFree(buf);
7108 }
7109 constraints.cPermittedSubtree = 1;
7110 constraints.rgPermittedSubtree = &permitted;
7111 SetLastError(0xdeadbeef);
7112 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7113 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7114 ok(!ret && GetLastError() == E_INVALIDARG,
7115 "Expected E_INVALIDARG, got %08x\n", GetLastError());
7116 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7117 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7118 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7119 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7120 if (ret)
7121 {
7122 ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7123 ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7124 "Unexpected value\n");
7125 LocalFree(buf);
7126 }
7127 constraints.cPermittedSubtree = 0;
7128 constraints.cExcludedSubtree = 1;
7129 constraints.rgExcludedSubtree = &excluded;
7130 excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7131 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7132 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7133 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7134 if (ret)
7135 {
7136 ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7137 ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7138 "Unexpected value\n");
7139 LocalFree(buf);
7140 }
7141 U(excluded.Base).pwszURL = (LPWSTR)url;
7142 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7143 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7144 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7145 if (ret)
7146 {
7147 ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7148 ok(!memcmp(buf, DNSExcludedConstraints, size),
7149 "Unexpected value\n");
7150 LocalFree(buf);
7151 }
7152 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7153 U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7154 U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7155 constraints.cPermittedSubtree = 1;
7156 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7157 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7158 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7159 if (ret)
7160 {
7161 ok(size == sizeof(permittedAndExcludedConstraints),
7162 "Unexpected size\n");
7163 ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7164 "Unexpected value\n");
7165 LocalFree(buf);
7166 }
7167 permitted.dwMinimum = 5;
7168 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7169 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7170 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7171 if (ret)
7172 {
7173 ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7174 "Unexpected size\n");
7175 ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7176 "Unexpected value\n");
7177 LocalFree(buf);
7178 }
7179 permitted.fMaximum = TRUE;
7180 permitted.dwMaximum = 3;
7181 SetLastError(0xdeadbeef);
7182 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7183 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7184 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7185 if (ret)
7186 {
7187 ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7188 "Unexpected size\n");
7189 ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7190 "Unexpected value\n");
7191 LocalFree(buf);
7192 }
7193 }
7194
7195 struct EncodedNameConstraints
7196 {
7197 CRYPT_DATA_BLOB encoded;
7198 CERT_NAME_CONSTRAINTS_INFO constraints;
7199 };
7200
7201 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7202 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7203 static CERT_GENERAL_SUBTREE DNSSubtree = {
7204 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7205 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7206 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7207 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7208 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7209 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7210 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7211
7212 static const struct EncodedNameConstraints encodedNameConstraints[] = {
7213 { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7214 { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7215 { 1, &emptyDNSSubtree, 0, NULL } },
7216 { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7217 { 0, NULL, 1, &emptyDNSSubtree } },
7218 { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7219 { 0, NULL, 1, &DNSSubtree } },
7220 { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7221 { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7222 { { sizeof(permittedAndExcludedWithMinConstraints),
7223 permittedAndExcludedWithMinConstraints },
7224 { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7225 { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7226 permittedAndExcludedWithMinMaxConstraints },
7227 { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7228 };
7229
7230 static void test_decodeNameConstraints(DWORD dwEncoding)
7231 {
7232 BOOL ret;
7233 DWORD i;
7234 CERT_NAME_CONSTRAINTS_INFO *constraints;
7235
7236 U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7237 U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7238 U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7239 U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7240 U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7241 U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7242 U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7243 for (i = 0;
7244 i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7245 i++)
7246 {
7247 DWORD size;
7248
7249 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7250 encodedNameConstraints[i].encoded.pbData,
7251 encodedNameConstraints[i].encoded.cbData,
7252 CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7253 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7254 {
7255 skip("no X509_NAME_CONSTRAINTS decode support\n");
7256 return;
7257 }
7258 ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7259 if (ret)
7260 {
7261 DWORD j;
7262
7263 if (constraints->cPermittedSubtree !=
7264 encodedNameConstraints[i].constraints.cPermittedSubtree)
7265 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7266 encodedNameConstraints[i].constraints.cPermittedSubtree,
7267 constraints->cPermittedSubtree);
7268 if (constraints->cPermittedSubtree ==
7269 encodedNameConstraints[i].constraints.cPermittedSubtree)
7270 {
7271 for (j = 0; j < constraints->cPermittedSubtree; j++)
7272 {
7273 compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7274 &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7275 }
7276 }
7277 if (constraints->cExcludedSubtree !=
7278 encodedNameConstraints[i].constraints.cExcludedSubtree)
7279 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7280 encodedNameConstraints[i].constraints.cExcludedSubtree,
7281 constraints->cExcludedSubtree);
7282 if (constraints->cExcludedSubtree ==
7283 encodedNameConstraints[i].constraints.cExcludedSubtree)
7284 {
7285 for (j = 0; j < constraints->cExcludedSubtree; j++)
7286 {
7287 compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7288 &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7289 }
7290 }
7291 LocalFree(constraints);
7292 }
7293 }
7294 }
7295
7296 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7297 'n','o','t','i','c','e',0 };
7298 static const BYTE noticeWithDisplayText[] = {
7299 0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7300 0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7301 0x00,0x69,0x00,0x63,0x00,0x65
7302 };
7303 static char org[] = "Wine";
7304 static int noticeNumbers[] = { 2,3 };
7305 static BYTE noticeWithReference[] = {
7306 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7307 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7308 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7309 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7310 };
7311
7312 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7313 {
7314 BOOL ret;
7315 LPBYTE buf;
7316 DWORD size;
7317 CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7318 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7319
7320 memset(&notice, 0, sizeof(notice));
7321 ret = pCryptEncodeObjectEx(dwEncoding,
7322 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7323 NULL, &buf, &size);
7324 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7325 {
7326 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7327 return;
7328 }
7329 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7330 if (ret)
7331 {
7332 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7333 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7334 LocalFree(buf);
7335 }
7336 notice.pszDisplayText = noticeText;
7337 ret = pCryptEncodeObjectEx(dwEncoding,
7338 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7339 NULL, &buf, &size);
7340 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7341 if (ret)
7342 {
7343 ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7344 ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7345 LocalFree(buf);
7346 }
7347 reference.pszOrganization = org;
7348 reference.cNoticeNumbers = 2;
7349 reference.rgNoticeNumbers = noticeNumbers;
7350 notice.pNoticeReference = &reference;
7351 ret = pCryptEncodeObjectEx(dwEncoding,
7352 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7353 NULL, &buf, &size);
7354 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7355 if (ret)
7356 {
7357 ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7358 ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7359 LocalFree(buf);
7360 }
7361 }
7362
7363 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7364 {
7365 BOOL ret;
7366 CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7367 DWORD size;
7368
7369 ret = pCryptDecodeObjectEx(dwEncoding,
7370 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7371 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7372 &notice, &size);
7373 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7374 {
7375 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7376 return;
7377 }
7378 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7379 if (ret)
7380 {
7381 ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7382 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7383 LocalFree(notice);
7384 }
7385 ret = pCryptDecodeObjectEx(dwEncoding,
7386 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7387 noticeWithDisplayText, sizeof(noticeWithDisplayText),
7388 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7389 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7390 if (ret)
7391 {
7392 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7393 "unexpected display text\n");
7394 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7395 LocalFree(notice);
7396 }
7397 ret = pCryptDecodeObjectEx(dwEncoding,
7398 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7399 noticeWithReference, sizeof(noticeWithReference),
7400 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7401 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7402 if (ret)
7403 {
7404 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7405 "unexpected display text\n");
7406 ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7407 if (notice->pNoticeReference)
7408 {
7409 ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7410 "unexpected organization %s\n",
7411 notice->pNoticeReference->pszOrganization);
7412 ok(notice->pNoticeReference->cNoticeNumbers == 2,
7413 "expected 2 notice numbers, got %d\n",
7414 notice->pNoticeReference->cNoticeNumbers);
7415 ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7416 "unexpected notice number %d\n",
7417 notice->pNoticeReference->rgNoticeNumbers[0]);
7418 ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7419 "unexpected notice number %d\n",
7420 notice->pNoticeReference->rgNoticeNumbers[1]);
7421 }
7422 LocalFree(notice);
7423 }
7424 }
7425
7426 static char oid_any_policy[] = "2.5.29.32.0";
7427 static const BYTE policiesWithAnyPolicy[] = {
7428 0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7429 };
7430 static char oid1[] = "1.2.3";
7431 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7432 static const BYTE twoPolicies[] = {
7433 0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7434 0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7435 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7436 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7437 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7438 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7439 };
7440
7441 static void test_encodeCertPolicies(DWORD dwEncoding)
7442 {
7443 BOOL ret;
7444 CERT_POLICIES_INFO info;
7445 CERT_POLICY_INFO policy[2];
7446 CERT_POLICY_QUALIFIER_INFO qualifier;
7447 LPBYTE buf;
7448 DWORD size;
7449
7450 memset(&info, 0, sizeof(info));
7451 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7452 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7453 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7454 if (ret)
7455 {
7456 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7457 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7458 LocalFree(buf);
7459 }
7460 memset(policy, 0, sizeof(policy));
7461 info.cPolicyInfo = 1;
7462 info.rgPolicyInfo = policy;
7463 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7464 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7465 ok(!ret && (GetLastError() == E_INVALIDARG ||
7466 GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7467 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7468 policy[0].pszPolicyIdentifier = oid_any_policy;
7469 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7470 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7471 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7472 if (ret)
7473 {
7474 ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7475 ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7476 LocalFree(buf);
7477 }
7478 policy[1].pszPolicyIdentifier = oid1;
7479 memset(&qualifier, 0, sizeof(qualifier));
7480 qualifier.pszPolicyQualifierId = oid_user_notice;
7481 qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7482 qualifier.Qualifier.pbData = noticeWithReference;
7483 policy[1].cPolicyQualifier = 1;
7484 policy[1].rgPolicyQualifier = &qualifier;
7485 info.cPolicyInfo = 2;
7486 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7487 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7488 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7489 if (ret)
7490 {
7491 ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7492 ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7493 LocalFree(buf);
7494 }
7495 }
7496
7497 static void test_decodeCertPolicies(DWORD dwEncoding)
7498 {
7499 BOOL ret;
7500 CERT_POLICIES_INFO *info;
7501 DWORD size;
7502
7503 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7504 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7505 &info, &size);
7506 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7507 if (ret)
7508 {
7509 ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7510 info->cPolicyInfo);
7511 LocalFree(info);
7512 }
7513 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7514 policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7515 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7516 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7517 if (ret)
7518 {
7519 ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7520 info->cPolicyInfo);
7521 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7522 "unexpected policy id %s\n",
7523 info->rgPolicyInfo[0].pszPolicyIdentifier);
7524 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7525 "unexpected policy qualifier count %d\n",
7526 info->rgPolicyInfo[0].cPolicyQualifier);
7527 LocalFree(info);
7528 }
7529 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7530 twoPolicies, sizeof(twoPolicies),
7531 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7532 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7533 if (ret)
7534 {
7535 ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7536 info->cPolicyInfo);
7537 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7538 "unexpected policy id %s\n",
7539 info->rgPolicyInfo[0].pszPolicyIdentifier);
7540 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7541 "unexpected policy qualifier count %d\n",
7542 info->rgPolicyInfo[0].cPolicyQualifier);
7543 ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7544 "unexpected policy id %s\n",
7545 info->rgPolicyInfo[1].pszPolicyIdentifier);
7546 ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7547 "unexpected policy qualifier count %d\n",
7548 info->rgPolicyInfo[1].cPolicyQualifier);
7549 ok(!strcmp(
7550 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7551 oid_user_notice), "unexpected policy qualifier id %s\n",
7552 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7553 ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7554 sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7555 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7556 ok(!memcmp(
7557 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7558 noticeWithReference, sizeof(noticeWithReference)),
7559 "unexpected qualifier value\n");
7560 LocalFree(info);
7561 }
7562 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7563 twoPolicies, sizeof(twoPolicies), 0, NULL, NULL, &size);
7564 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7565 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7566 if (info)
7567 {
7568 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7569 twoPolicies, sizeof(twoPolicies), 0, NULL, info, &size);
7570 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7571 HeapFree(GetProcessHeap(), 0, info);
7572 }
7573 }
7574
7575 static const BYTE policyMappingWithOneMapping[] = {
7576 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7577 static const BYTE policyMappingWithTwoMappings[] = {
7578 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7579 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7580 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7581 szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7582
7583 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7584 {
7585 static char oid2[] = "2.3.4";
7586 static char oid3[] = "1.3.4";
7587 static char oid4[] = "2.5.6";
7588 BOOL ret;
7589 CERT_POLICY_MAPPINGS_INFO info = { 0 };
7590 CERT_POLICY_MAPPING mapping[2];
7591 LPBYTE buf;
7592 DWORD size, i;
7593
7594 /* Each of the mapping OIDs is equivalent, so check with all of them */
7595 for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7596 {
7597 memset(&info, 0, sizeof(info));
7598 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7599 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7600 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7601 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7602 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7603 {
7604 win_skip("no policy mappings support\n");
7605 return;
7606 }
7607 if (ret)
7608 {
7609 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7610 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7611 "unexpected value\n");
7612 LocalFree(buf);
7613 }
7614 mapping[0].pszIssuerDomainPolicy = NULL;
7615 mapping[0].pszSubjectDomainPolicy = NULL;
7616 info.cPolicyMapping = 1;
7617 info.rgPolicyMapping = mapping;
7618 SetLastError(0xdeadbeef);
7619 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7620 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7621 ok(!ret && GetLastError() == E_INVALIDARG,
7622 "expected E_INVALIDARG, got %08x\n", GetLastError());
7623 mapping[0].pszIssuerDomainPolicy = oid1;
7624 mapping[0].pszSubjectDomainPolicy = oid2;
7625 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7626 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7627 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7628 if (ret)
7629 {
7630 ok(size == sizeof(policyMappingWithOneMapping),
7631 "unexpected size %d\n", size);
7632 ok(!memcmp(buf, policyMappingWithOneMapping, size),
7633 "unexpected value\n");
7634 LocalFree(buf);
7635 }
7636 mapping[1].pszIssuerDomainPolicy = oid3;
7637 mapping[1].pszSubjectDomainPolicy = oid4;
7638 info.cPolicyMapping = 2;
7639 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7640 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7641 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7642 if (ret)
7643 {
7644 ok(size == sizeof(policyMappingWithTwoMappings),
7645 "unexpected size %d\n", size);
7646 ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7647 "unexpected value\n");
7648 LocalFree(buf);
7649 }
7650 }
7651 }
7652
7653 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7654 {
7655 DWORD size, i;
7656 CERT_POLICY_MAPPINGS_INFO *info;
7657 BOOL ret;
7658
7659 /* Each of the mapping OIDs is equivalent, so check with all of them */
7660 for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7661 {
7662 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7663 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7664 &info, &size);
7665 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7666 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7667 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7668 {
7669 win_skip("no policy mappings support\n");
7670 return;
7671 }
7672 if (ret)
7673 {
7674 ok(info->cPolicyMapping == 0,
7675 "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7676 LocalFree(info);
7677 }
7678 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7679 policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7680 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7681 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7682 if (ret)
7683 {
7684 ok(info->cPolicyMapping == 1,
7685 "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7686 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7687 "unexpected issuer policy %s\n",
7688 info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7689 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7690 "2.3.4"), "unexpected subject policy %s\n",
7691 info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7692 LocalFree(info);
7693 }
7694 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7695 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7696 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7697 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7698 if (ret)
7699 {
7700 ok(info->cPolicyMapping == 2,
7701 "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7702 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7703 "unexpected issuer policy %s\n",
7704 info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7705 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7706 "2.3.4"), "unexpected subject policy %s\n",
7707 info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7708 ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7709 "unexpected issuer policy %s\n",
7710 info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7711 ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7712 "2.5.6"), "unexpected subject policy %s\n",
7713 info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7714 LocalFree(info);
7715 }
7716 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7717 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7718 NULL, NULL, &size);
7719 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7720 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size);
7721 if (info)
7722 {
7723 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7724 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0,
7725 NULL, info, &size);
7726 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7727 HeapFree(GetProcessHeap(), 0, info);
7728 }
7729 }
7730 }
7731
7732 static const BYTE policyConstraintsWithRequireExplicit[] = {
7733 0x30,0x03,0x80,0x01,0x00 };
7734 static const BYTE policyConstraintsWithInhibitMapping[] = {
7735 0x30,0x03,0x81,0x01,0x01 };
7736 static const BYTE policyConstraintsWithBoth[] = {
7737 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7738
7739 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7740 {
7741 CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7742 LPBYTE buf;
7743 DWORD size;
7744 BOOL ret;
7745
7746 /* Even though RFC 5280 explicitly states CAs must not issue empty
7747 * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7748 */
7749 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7750 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7751 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7752 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7753 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7754 {
7755 win_skip("no policy constraints support\n");
7756 return;
7757 }
7758 if (ret)
7759 {
7760 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7761 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7762 "unexpected value\n");
7763 LocalFree(buf);
7764 }
7765 /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7766 * is not, then a skip of 0 is encoded.
7767 */
7768 info.fRequireExplicitPolicy = TRUE;
7769 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7770 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7771 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7772 if (ret)
7773 {
7774 ok(size == sizeof(policyConstraintsWithRequireExplicit),
7775 "unexpected size %d\n", size);
7776 ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7777 sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7778 LocalFree(buf);
7779 }
7780 /* With inhibit policy mapping */
7781 info.fRequireExplicitPolicy = FALSE;
7782 info.dwRequireExplicitPolicySkipCerts = 0;
7783 info.fInhibitPolicyMapping = TRUE;
7784 info.dwInhibitPolicyMappingSkipCerts = 1;
7785 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7786 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7787 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7788 if (ret)
7789 {
7790 ok(size == sizeof(policyConstraintsWithInhibitMapping),
7791 "unexpected size %d\n", size);
7792 ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7793 sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7794 LocalFree(buf);
7795 }
7796 /* And with both */
7797 info.fRequireExplicitPolicy = TRUE;
7798 info.dwRequireExplicitPolicySkipCerts = 1;
7799 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7800 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7801 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7802 if (ret)
7803 {
7804 ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7805 size);
7806 ok(!memcmp(buf, policyConstraintsWithBoth,
7807 sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7808 LocalFree(buf);
7809 }
7810 }
7811
7812 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7813 {
7814 CERT_POLICY_CONSTRAINTS_INFO *info;
7815 DWORD size;
7816 BOOL ret;
7817
7818 /* Again, even though CAs must not issue such constraints, they can be
7819 * decoded.
7820 */
7821 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7822 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7823 &info, &size);
7824 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7825 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7826 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7827 {
7828 win_skip("no policy mappings support\n");
7829 return;
7830 }
7831 if (ret)
7832 {
7833 ok(!info->fRequireExplicitPolicy,
7834 "expected require explicit = FALSE\n");
7835 ok(!info->fInhibitPolicyMapping,
7836 "expected implicit mapping = FALSE\n");
7837 LocalFree(info);
7838 }
7839 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7840 policyConstraintsWithRequireExplicit,
7841 sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7842 NULL, &info, &size);
7843 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7844 if (ret)
7845 {
7846 ok(info->fRequireExplicitPolicy,
7847 "expected require explicit = TRUE\n");
7848 ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7849 info->dwRequireExplicitPolicySkipCerts);
7850 ok(!info->fInhibitPolicyMapping,
7851 "expected implicit mapping = FALSE\n");
7852 LocalFree(info);
7853 }
7854 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7855 policyConstraintsWithInhibitMapping,
7856 sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7857 NULL, &info, &size);
7858 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7859 if (ret)
7860 {
7861 ok(!info->fRequireExplicitPolicy,
7862 "expected require explicit = FALSE\n");
7863 ok(info->fInhibitPolicyMapping,
7864 "expected implicit mapping = TRUE\n");
7865 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7866 info->dwInhibitPolicyMappingSkipCerts);
7867 LocalFree(info);
7868 }
7869 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7870 policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7871 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7872 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7873 if (ret)
7874 {
7875 ok(info->fRequireExplicitPolicy,
7876 "expected require explicit = TRUE\n");
7877 ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7878 info->dwRequireExplicitPolicySkipCerts);
7879 ok(info->fInhibitPolicyMapping,
7880 "expected implicit mapping = TRUE\n");
7881 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7882 info->dwInhibitPolicyMappingSkipCerts);
7883 LocalFree(info);
7884 }
7885 }
7886
7887 /* Free *pInfo with HeapFree */
7888 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7889 {
7890 BOOL ret;
7891 DWORD size = 0;
7892 HCRYPTKEY key;
7893
7894 /* This crashes
7895 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7896 */
7897 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7898 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7899 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7900 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7901 &size);
7902 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7903 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7904 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7905 NULL, &size);
7906 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7907 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7908 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7909 0, NULL, NULL, &size);
7910 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7911 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7912 /* Test with no key */
7913 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7914 0, NULL, NULL, &size);
7915 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7916 GetLastError());
7917 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7918 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7919 if (ret)
7920 {
7921 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7922 NULL, 0, NULL, NULL, &size);
7923 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7924 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7925 if (*pInfo)
7926 {
7927 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7928 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7929 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7930 GetLastError());
7931 if (ret)
7932 {
7933 /* By default (we passed NULL as the OID) the OID is
7934 * szOID_RSA_RSA.
7935 */
7936 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7937 "Expected %s, got %s\n", szOID_RSA_RSA,
7938 (*pInfo)->Algorithm.pszObjId);
7939 }
7940 }
7941 }
7942 CryptDestroyKey(key);
7943 }
7944
7945 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7946 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7947 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7948 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7949 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7950 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7951 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7952 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7953 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7954 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7955 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7956 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7957 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7958 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7959 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7960 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7961 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7962 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7963 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7964 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7965 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7966 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7967 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7968 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7969 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7970
7971 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7972 {
7973 BOOL ret;
7974 HCRYPTKEY key;
7975 PCCERT_CONTEXT context;
7976 DWORD dwSize;
7977 ALG_ID ai;
7978
7979 /* These crash
7980 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7981 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7982 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7983 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7984 NULL);
7985 */
7986 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7987 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7988 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7989 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7990 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7991 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7992 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7993 &key);
7994 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7995 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7996
7997 /* Export key with standard algorithm (CALG_RSA_KEYX) */
7998 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7999 &key);
8000 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8001
8002 dwSize = sizeof(ai);
8003 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8004 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8005 if(ret)
8006 {
8007 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8008 ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
8009 }
8010
8011 CryptDestroyKey(key);
8012
8013 /* Repeat with forced algorithm */
8014 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
8015 &key);
8016 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8017
8018 dwSize = sizeof(ai);
8019 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
8020 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
8021 if(ret)
8022 {
8023 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
8024 ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
8025 }
8026
8027 CryptDestroyKey(key);
8028
8029 /* Test importing a public key from a certificate context */
8030 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
8031 sizeof(expiredCert));
8032 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
8033 GetLastError());
8034 if (context)
8035 {
8036 ok(!strcmp(szOID_RSA_RSA,
8037 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
8038 "Expected %s, got %s\n", szOID_RSA_RSA,
8039 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
8040 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
8041 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
8042 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
8043 CryptDestroyKey(key);
8044 CertFreeCertificateContext(context);
8045 }
8046 }
8047
8048 static const char cspName[] = "WineCryptTemp";
8049
8050 static void testPortPublicKeyInfo(void)
8051 {
8052 HCRYPTPROV csp;
8053 BOOL ret;
8054 PCERT_PUBLIC_KEY_INFO info = NULL;
8055
8056 /* Just in case a previous run failed, delete this thing */
8057 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
8058 CRYPT_DELETEKEYSET);
8059 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
8060 CRYPT_NEWKEYSET);
8061 ok(ret,"CryptAcquireContextA failed\n");
8062
8063 testExportPublicKey(csp, &info);
8064 testImportPublicKey(csp, info);
8065
8066 HeapFree(GetProcessHeap(), 0, info);
8067 CryptReleaseContext(csp, 0);
8068 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
8069 CRYPT_DELETEKEYSET);
8070 ok(ret,"CryptAcquireContextA failed\n");
8071 }
8072
8073 START_TEST(encode)
8074 {
8075 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
8076 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
8077 HMODULE hCrypt32;
8078 DWORD i;
8079
8080 hCrypt32 = GetModuleHandleA("crypt32.dll");
8081 pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
8082 pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
8083 if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
8084 {
8085 win_skip("CryptDecodeObjectEx() is not available\n");
8086 return;
8087 }
8088
8089 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
8090 {
8091 test_encodeInt(encodings[i]);
8092 test_decodeInt(encodings[i]);
8093 test_encodeEnumerated(encodings[i]);
8094 test_decodeEnumerated(encodings[i]);
8095 test_encodeFiletime(encodings[i]);
8096 test_decodeFiletime(encodings[i]);
8097 test_encodeName(encodings[i]);
8098 test_decodeName(encodings[i]);
8099 test_encodeUnicodeName(encodings[i]);
8100 test_decodeUnicodeName(encodings[i]);
8101 test_encodeNameValue(encodings[i]);
8102 test_decodeNameValue(encodings[i]);
8103 test_encodeUnicodeNameValue(encodings[i]);
8104 test_decodeUnicodeNameValue(encodings[i]);
8105 test_encodeAltName(encodings[i]);
8106 test_decodeAltName(encodings[i]);
8107 test_encodeOctets(encodings[i]);
8108 test_decodeOctets(encodings[i]);
8109 test_encodeBits(encodings[i]);
8110 test_decodeBits(encodings[i]);
8111 test_encodeBasicConstraints(encodings[i]);
8112 test_decodeBasicConstraints(encodings[i]);
8113 test_encodeRsaPublicKey(encodings[i]);
8114 test_decodeRsaPublicKey(encodings[i]);
8115 test_encodeSequenceOfAny(encodings[i]);
8116 test_decodeSequenceOfAny(encodings[i]);
8117 test_encodeExtensions(encodings[i]);
8118 test_decodeExtensions(encodings[i]);
8119 test_encodePublicKeyInfo(encodings[i]);
8120 test_decodePublicKeyInfo(encodings[i]);
8121 test_encodeCertToBeSigned(encodings[i]);
8122 test_decodeCertToBeSigned(encodings[i]);
8123 test_encodeCert(encodings[i]);
8124 test_decodeCert(encodings[i]);
8125 test_encodeCRLDistPoints(encodings[i]);
8126 test_decodeCRLDistPoints(encodings[i]);
8127 test_encodeCRLIssuingDistPoint(encodings[i]);
8128 test_decodeCRLIssuingDistPoint(encodings[i]);
8129 test_encodeCRLToBeSigned(encodings[i]);
8130 test_decodeCRLToBeSigned(encodings[i]);
8131 test_encodeEnhancedKeyUsage(encodings[i]);
8132 test_decodeEnhancedKeyUsage(encodings[i]);
8133 test_encodeAuthorityKeyId(encodings[i]);
8134 test_decodeAuthorityKeyId(encodings[i]);
8135 test_encodeAuthorityKeyId2(encodings[i]);
8136 test_decodeAuthorityKeyId2(encodings[i]);
8137 test_encodeAuthorityInfoAccess(encodings[i]);
8138 test_decodeAuthorityInfoAccess(encodings[i]);
8139 test_encodeCTL(encodings[i]);
8140 test_decodeCTL(encodings[i]);
8141 test_encodePKCSContentInfo(encodings[i]);
8142 test_decodePKCSContentInfo(encodings[i]);
8143 test_encodePKCSAttribute(encodings[i]);
8144 test_decodePKCSAttribute(encodings[i]);
8145 test_encodePKCSAttributes(encodings[i]);
8146 test_decodePKCSAttributes(encodings[i]);
8147 test_encodePKCSSMimeCapabilities(encodings[i]);
8148 test_decodePKCSSMimeCapabilities(encodings[i]);
8149 test_encodePKCSSignerInfo(encodings[i]);
8150 test_decodePKCSSignerInfo(encodings[i]);
8151 test_encodeCMSSignerInfo(encodings[i]);
8152 test_decodeCMSSignerInfo(encodings[i]);
8153 test_encodeNameConstraints(encodings[i]);
8154 test_decodeNameConstraints(encodings[i]);
8155 test_encodePolicyQualifierUserNotice(encodings[i]);
8156 test_decodePolicyQualifierUserNotice(encodings[i]);
8157 test_encodeCertPolicies(encodings[i]);
8158 test_decodeCertPolicies(encodings[i]);
8159 test_encodeCertPolicyMappings(encodings[i]);
8160 test_decodeCertPolicyMappings(encodings[i]);
8161 test_encodeCertPolicyConstraints(encodings[i]);
8162 test_decodeCertPolicyConstraints(encodings[i]);
8163 }
8164 testPortPublicKeyInfo();
8165 }