[MSI]
[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 (buf)
125 {
126 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
127 buf[0]);
128 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
129 buf[1], ints[i].encoded[1]);
130 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
131 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
132 LocalFree(buf);
133 }
134 /* encode as multibyte integer */
135 blob.cbData = sizeof(ints[i].val);
136 blob.pbData = (BYTE *)&ints[i].val;
137 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
138 0, NULL, NULL, &bufSize);
139 ok(ret, "Expected success, got %d\n", GetLastError());
140 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
141 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
142 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
143 if (buf)
144 {
145 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
146 buf[0]);
147 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
148 buf[1], ints[i].encoded[1]);
149 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
150 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
151 LocalFree(buf);
152 }
153 }
154 /* encode a couple bigger ints, just to show it's little-endian and leading
155 * sign bytes are dropped
156 */
157 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
158 {
159 blob.cbData = strlen((const char*)bigInts[i].val);
160 blob.pbData = (BYTE *)bigInts[i].val;
161 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
162 0, NULL, NULL, &bufSize);
163 ok(ret, "Expected success, got %d\n", GetLastError());
164 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
165 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
166 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
167 if (buf)
168 {
169 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
170 buf[0]);
171 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
172 buf[1], bigInts[i].encoded[1]);
173 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
174 bigInts[i].encoded[1] + 1),
175 "Encoded value didn't match expected\n");
176 LocalFree(buf);
177 }
178 }
179 /* and, encode some uints */
180 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
181 {
182 blob.cbData = strlen((const char*)bigUInts[i].val);
183 blob.pbData = (BYTE*)bigUInts[i].val;
184 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
185 0, NULL, NULL, &bufSize);
186 ok(ret, "Expected success, got %d\n", GetLastError());
187 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
188 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
189 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError());
190 if (buf)
191 {
192 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
193 buf[0]);
194 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
195 buf[1], bigUInts[i].encoded[1]);
196 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
197 bigUInts[i].encoded[1] + 1),
198 "Encoded value didn't match expected\n");
199 LocalFree(buf);
200 }
201 }
202 }
203
204 static void test_decodeInt(DWORD dwEncoding)
205 {
206 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
207 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
208 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
209 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
210 static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 };
211 BYTE *buf = NULL;
212 DWORD bufSize = 0;
213 int i;
214 BOOL ret;
215
216 /* CryptDecodeObjectEx with NULL bufSize crashes..
217 ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
218 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
219 */
220 /* check bogus encoding */
221 ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
222 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
223 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
224 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError());
225 /* check with NULL integer buffer */
226 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
227 &bufSize);
228 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
229 GetLastError() == OSS_BAD_ARG /* Win9x */),
230 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
231 /* check with a valid, but too large, integer */
232 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
233 CRYPT_DECODE_ALLOC_FLAG, NULL, &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 (buf)
260 {
261 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
262 ints[i].val, *(int *)buf);
263 LocalFree(buf);
264 }
265 }
266 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
267 {
268 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
269 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
270 &bufSize);
271 ok(ret && GetLastError() == NOERROR,
272 "Expected success and NOERROR, got %d\n", GetLastError());
273 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
274 bigInts[i].encoded, bigInts[i].encoded[1] + 2,
275 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
276 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
277 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
278 ok(buf != NULL, "Expected allocated buffer\n");
279 if (buf)
280 {
281 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
282
283 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
284 "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded),
285 blob->cbData);
286 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
287 "Unexpected value\n");
288 LocalFree(buf);
289 }
290 }
291 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
292 {
293 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
294 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
295 &bufSize);
296 ok(ret && GetLastError() == NOERROR,
297 "Expected success and NOERROR, got %d\n", GetLastError());
298 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
299 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
300 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
301 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError());
302 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize);
303 ok(buf != NULL, "Expected allocated buffer\n");
304 if (buf)
305 {
306 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
307
308 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
309 "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val),
310 blob->cbData);
311 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
312 "Unexpected value\n");
313 LocalFree(buf);
314 }
315 }
316 /* Decode the value 1 with long-form length */
317 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
318 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
319 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
320 if (buf)
321 {
322 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
323 LocalFree(buf);
324 }
325 /* check with extra bytes at the end */
326 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes,
327 sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
328 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
329 if (buf)
330 {
331 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
332 LocalFree(buf);
333 }
334 /* Try to decode some bogus large items */
335 /* The buffer size is smaller than the encoded length, so this should fail
336 * with CRYPT_E_ASN1_EOD if it's being decoded.
337 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
338 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
339 * So this test unfortunately isn't useful.
340 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
341 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &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 (buf)
392 {
393 ok(buf[0] == 0xa,
394 "Got unexpected type %d for enumerated (expected 0xa)\n",
395 buf[0]);
396 ok(buf[1] == enums[j].encoded[1],
397 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
398 ok(!memcmp(buf + 1, enums[j].encoded + 1,
399 enums[j].encoded[1] + 1),
400 "Encoded value of 0x%08x didn't match expected\n",
401 enums[j].val);
402 LocalFree(buf);
403 }
404 }
405 }
406 }
407
408 static void test_decodeEnumerated(DWORD dwEncoding)
409 {
410 DWORD i, j;
411
412 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
413 {
414 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
415 {
416 BOOL ret;
417 DWORD bufSize = sizeof(int);
418 int val;
419
420 ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
421 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
422 &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 (buf)
460 {
461 ok(buf[0] == time->encodedTime[0],
462 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
463 buf[0]);
464 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n",
465 time->encodedTime[1], bufSize);
466 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
467 "Got unexpected value for time encoding\n");
468 LocalFree(buf);
469 }
470 }
471 else
472 ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) ||
473 broken(GetLastError() == ERROR_SUCCESS),
474 "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError());
475 }
476
477 static const char *printSystemTime(const SYSTEMTIME *st)
478 {
479 static char buf[25];
480
481 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay,
482 st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds);
483 return buf;
484 }
485
486 static const char *printFileTime(const FILETIME *ft)
487 {
488 static char buf[25];
489 SYSTEMTIME st;
490
491 FileTimeToSystemTime(ft, &st);
492 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay,
493 st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds);
494 return buf;
495 }
496
497 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got)
498 {
499 SYSTEMTIME st;
500
501 FileTimeToSystemTime(got, &st);
502 ok((expected->wYear == st.wYear &&
503 expected->wMonth == st.wMonth &&
504 expected->wDay == st.wDay &&
505 expected->wHour == st.wHour &&
506 expected->wMinute == st.wMinute &&
507 expected->wSecond == st.wSecond &&
508 abs(expected->wMilliseconds - st.wMilliseconds) <= 1) ||
509 /* Some Windows systems only seem to be accurate in their time decoding to
510 * within about an hour.
511 */
512 broken(expected->wYear == st.wYear &&
513 expected->wMonth == st.wMonth &&
514 expected->wDay == st.wDay &&
515 abs(expected->wHour - st.wHour) <= 1),
516 "Got unexpected value for time decoding:\nexpected %s, got %s\n",
517 printSystemTime(expected), printFileTime(got));
518 }
519
520 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
521 const struct encodedFiletime *time)
522 {
523 FILETIME ft = { 0 };
524 DWORD size = sizeof(ft);
525 BOOL ret;
526
527 ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
528 time->encodedTime[1] + 2, 0, NULL, &ft, &size);
529 /* years other than 1950-2050 are not allowed for encodings other than
530 * X509_CHOICE_OF_TIME.
531 */
532 if (structType == X509_CHOICE_OF_TIME ||
533 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
534 {
535 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
536 "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(),
537 GetLastError());
538 if (ret)
539 compareTime(&time->sysTime, &ft);
540 }
541 else
542 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
543 GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ),
544 "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n",
545 GetLastError());
546 }
547
548 static const BYTE bin20[] = {
549 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
550 static const BYTE bin21[] = {
551 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
552 static const BYTE bin22[] = {
553 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
554
555 static const struct encodedFiletime times[] = {
556 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
557 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
558 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
559 };
560
561 static void test_encodeFiletime(DWORD dwEncoding)
562 {
563 DWORD i;
564
565 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
566 {
567 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
568 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
569 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
570 }
571 }
572
573 static const BYTE bin23[] = {
574 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
575 static const BYTE bin24[] = {
576 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
577 static const BYTE bin25[] = {
578 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
579 static const BYTE bin26[] = {
580 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
581 static const BYTE bin27[] = {
582 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
583 static const BYTE bin28[] = {
584 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
585 static const BYTE bin29[] = {
586 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
587 static const BYTE bin30[] = {
588 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
589 static const BYTE bin31[] = {
590 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
591 static const BYTE bin32[] = {
592 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
593 static const BYTE bin33[] = {
594 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
595 static const BYTE bin34[] = {
596 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
597 static const BYTE bin35[] = {
598 0x17,0x08, '4','5','0','6','0','6','1','6'};
599 static const BYTE bin36[] = {
600 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
601 static const BYTE bin37[] = {
602 0x18,0x04, '2','1','4','5'};
603 static const BYTE bin38[] = {
604 0x18,0x08, '2','1','4','5','0','6','0','6'};
605
606 static void test_decodeFiletime(DWORD dwEncoding)
607 {
608 static const struct encodedFiletime otherTimes[] = {
609 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
610 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
611 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
612 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
613 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
614 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
615 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
616 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
617 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
618 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
619 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
620 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
621 };
622 /* An oddball case that succeeds in Windows, but doesn't seem correct
623 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
624 */
625 static const unsigned char *bogusTimes[] = {
626 /* oddly, this succeeds on Windows, with year 2765
627 "\x18" "\x0f" "21r50606161000Z",
628 */
629 bin35,
630 bin36,
631 bin37,
632 bin38,
633 };
634 DWORD i, size;
635 FILETIME ft1 = { 0 }, ft2 = { 0 };
636 BOOL ret;
637
638 /* Check bogus length with non-NULL buffer */
639 ret = SystemTimeToFileTime(&times[0].sysTime, &ft1);
640 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError());
641 size = 1;
642 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
643 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
644 ok(!ret && GetLastError() == ERROR_MORE_DATA,
645 "Expected ERROR_MORE_DATA, got %d\n", GetLastError());
646 /* Normal tests */
647 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
648 {
649 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &times[i]);
650 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &times[i]);
651 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &times[i]);
652 }
653 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
654 {
655 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
656 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
657 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
658 }
659 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
660 {
661 size = sizeof(ft1);
662 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
663 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
664 ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
665 GetLastError() == OSS_DATA_ERROR /* Win9x */)) ||
666 broken(ret), /* Win9x and NT4 for bin38 */
667 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
668 GetLastError());
669 }
670 }
671
672 static const char commonName[] = "Juan Lang";
673 static const char surName[] = "Lang";
674
675 static const BYTE emptySequence[] = { 0x30, 0 };
676 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
677 static const BYTE twoRDNs[] = {
678 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
679 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
680 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
681 static const BYTE encodedTwoRDNs[] = {
682 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21,
683 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,
684 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
685 0x6e,0x67,0x00,
686 };
687
688 static const BYTE us[] = { 0x55, 0x53 };
689 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
690 0x74, 0x61 };
691 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
692 0x6f, 0x6c, 0x69, 0x73 };
693 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
694 0x76, 0x65, 0x72, 0x73 };
695 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
696 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
697 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
698 0x73, 0x74 };
699 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
700 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
701
702 #define RDNA(arr) oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr }
703 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING, { sizeof(arr), (LPBYTE)arr }
704
705 static CHAR oid_us[] = "2.5.4.6",
706 oid_minnesota[] = "2.5.4.8",
707 oid_minneapolis[] = "2.5.4.7",
708 oid_codeweavers[] = "2.5.4.10",
709 oid_wine[] = "2.5.4.11",
710 oid_localhostAttr[] = "2.5.4.3",
711 oid_aric[] = "1.2.840.113549.1.9.1";
712 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) },
713 { RDNA(minnesota) },
714 { RDNA(minneapolis) },
715 { RDNA(codeweavers) },
716 { RDNA(wine) },
717 { RDNA(localhostAttr) },
718 { RDNIA5(aric) } };
719 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) },
720 { RDNA(localhostAttr) },
721 { RDNA(minnesota) },
722 { RDNA(minneapolis) },
723 { RDNA(codeweavers) },
724 { RDNA(wine) },
725 { RDNIA5(aric) } };
726
727 #undef RDNIA5
728 #undef RDNA
729
730 static const BYTE encodedRDNAttrs[] = {
731 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
732 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
733 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
734 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
735 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
736 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
737 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
738 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
739 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
740 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
741 };
742
743 static void test_encodeName(DWORD dwEncoding)
744 {
745 CERT_RDN_ATTR attrs[2];
746 CERT_RDN rdn;
747 CERT_NAME_INFO info;
748 static CHAR oid_common_name[] = szOID_COMMON_NAME,
749 oid_sur_name[] = szOID_SUR_NAME;
750 BYTE *buf = NULL;
751 DWORD size = 0;
752 BOOL ret;
753
754 if (0)
755 {
756 /* Test with NULL pvStructInfo (crashes on win9x) */
757 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
758 CRYPT_ENCODE_ALLOC_FLAG, NULL, &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 (buf)
769 {
770 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
771 "Got unexpected encoding for empty name\n");
772 LocalFree(buf);
773 }
774 if (0)
775 {
776 /* Test with bogus CERT_RDN (crashes on win9x) */
777 info.cRDN = 1;
778 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
779 CRYPT_ENCODE_ALLOC_FLAG, NULL, &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 (buf)
792 {
793 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
794 "Got unexpected encoding for empty RDN array\n");
795 LocalFree(buf);
796 }
797 if (0)
798 {
799 /* Test with bogus attr array (crashes on win9x) */
800 rdn.cRDNAttr = 1;
801 rdn.rgRDNAttr = NULL;
802 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
803 CRYPT_ENCODE_ALLOC_FLAG, NULL, &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 (buf)
835 {
836 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
837 "Got unexpected encoding for two RDN array\n");
838 LocalFree(buf);
839 }
840 /* A name can be "encoded" with previously encoded RDN attrs. */
841 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
842 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
843 attrs[0].Value.cbData = sizeof(twoRDNs);
844 rdn.cRDNAttr = 1;
845 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
846 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
847 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
848 if (buf)
849 {
850 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
851 ok(!memcmp(buf, encodedTwoRDNs, size),
852 "Unexpected value for re-endoded two RDN array\n");
853 LocalFree(buf);
854 }
855 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
856 rdn.cRDNAttr = 1;
857 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
858 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
859 CRYPT_ENCODE_ALLOC_FLAG, NULL, &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 (buf)
919 {
920 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
921 "Got unexpected encoding for empty name\n");
922 LocalFree(buf);
923 }
924 /* Check with one CERT_RDN_ATTR, that has an invalid character for the
925 * encoding (the NULL).
926 */
927 attrs[0].pszObjId = oid_common_name;
928 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
929 attrs[0].Value.cbData = sizeof(commonNameW);
930 attrs[0].Value.pbData = (BYTE *)commonNameW;
931 rdn.cRDNAttr = 1;
932 rdn.rgRDNAttr = attrs;
933 info.cRDN = 1;
934 info.rgRDN = &rdn;
935 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
936 CRYPT_ENCODE_ALLOC_FLAG, NULL, &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 (buf)
959 {
960 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)),
961 "Got unexpected encoding for two RDN array\n");
962 LocalFree(buf);
963 }
964 /* A name can be "encoded" with previously encoded RDN attrs. */
965 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB;
966 attrs[0].Value.pbData = (LPBYTE)twoRDNs;
967 attrs[0].Value.cbData = sizeof(twoRDNs);
968 rdn.cRDNAttr = 1;
969 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
970 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
971 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
972 if (buf)
973 {
974 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size);
975 ok(!memcmp(buf, encodedTwoRDNs, size),
976 "Unexpected value for re-endoded two RDN array\n");
977 LocalFree(buf);
978 }
979 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */
980 rdn.cRDNAttr = 1;
981 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
982 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info,
983 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
984 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
985 if (buf)
986 {
987 ok(size == sizeof(anyType), "Unexpected size %d\n", size);
988 ok(!memcmp(buf, anyType, size), "Unexpected value\n");
989 LocalFree(buf);
990 }
991 }
992
993 static void compareNameValues(const CERT_NAME_VALUE *expected,
994 const CERT_NAME_VALUE *got)
995 {
996 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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 (buf)
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 }
2714 }
2715
2716 /* MS encodes public key info with a NULL if the algorithm identifier's
2717 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
2718 * it encodes them by omitting the algorithm parameters. It accepts either
2719 * form for decoding.
2720 */
2721 struct encodedPublicKey
2722 {
2723 CERT_PUBLIC_KEY_INFO info;
2724 const BYTE *encoded;
2725 const BYTE *encodedNoNull;
2726 CERT_PUBLIC_KEY_INFO decoded;
2727 };
2728
2729 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2730 0xe, 0xf };
2731 static const BYTE params[] = { 0x02, 0x01, 0x01 };
2732
2733 static const unsigned char bin64[] = {
2734 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
2735 static const unsigned char bin65[] = {
2736 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
2737 static const unsigned char bin66[] = {
2738 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
2739 static const unsigned char bin67[] = {
2740 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
2741 static const unsigned char bin68[] = {
2742 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
2743 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2744 static const unsigned char bin69[] = {
2745 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2746 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2747 static const unsigned char bin70[] = {
2748 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2749 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2750 0x0f};
2751 static const unsigned char bin71[] = {
2752 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2753 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2754 0x0f};
2755 static unsigned char bin72[] = { 0x05,0x00};
2756
2757 static CHAR oid_bogus[] = "1.2.3",
2758 oid_rsa[] = szOID_RSA;
2759
2760 static const struct encodedPublicKey pubKeys[] = {
2761 /* with a bogus OID */
2762 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } },
2763 bin64, bin65,
2764 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } },
2765 /* some normal keys */
2766 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} },
2767 bin66, bin67,
2768 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } },
2769 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2770 bin68, bin69,
2771 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2772 /* with add'l parameters--note they must be DER-encoded */
2773 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2774 (BYTE *)aKey, 0 } },
2775 bin70, bin71,
2776 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2777 (BYTE *)aKey, 0 } } },
2778 };
2779
2780 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2781 {
2782 DWORD i;
2783
2784 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2785 {
2786 BOOL ret;
2787 BYTE *buf = NULL;
2788 DWORD bufSize = 0;
2789
2790 ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2791 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf,
2792 &bufSize);
2793 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
2794 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
2795 if (buf)
2796 {
2797 ok(bufSize == pubKeys[i].encoded[1] + 2,
2798 "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize);
2799 if (bufSize == pubKeys[i].encoded[1] + 2)
2800 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2801 "Unexpected value\n");
2802 LocalFree(buf);
2803 }
2804 }
2805 }
2806
2807 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2808 const CERT_PUBLIC_KEY_INFO *got)
2809 {
2810 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2811 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2812 got->Algorithm.pszObjId);
2813 ok(expected->Algorithm.Parameters.cbData ==
2814 got->Algorithm.Parameters.cbData,
2815 "Expected parameters of %d bytes, got %d\n",
2816 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2817 if (expected->Algorithm.Parameters.cbData)
2818 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2819 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2820 "Unexpected algorithm parameters\n");
2821 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2822 "Expected public key of %d bytes, got %d\n",
2823 expected->PublicKey.cbData, got->PublicKey.cbData);
2824 if (expected->PublicKey.cbData)
2825 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2826 got->PublicKey.cbData), "Unexpected public key value\n");
2827 }
2828
2829 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2830 {
2831 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2832 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2833 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2834 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2835 DWORD i;
2836 BOOL ret;
2837 BYTE *buf = NULL;
2838 DWORD bufSize = 0;
2839
2840 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2841 {
2842 /* The NULL form decodes to the decoded member */
2843 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2844 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2845 NULL, &buf, &bufSize);
2846 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2847 if (buf)
2848 {
2849 comparePublicKeyInfo(&pubKeys[i].decoded,
2850 (CERT_PUBLIC_KEY_INFO *)buf);
2851 LocalFree(buf);
2852 }
2853 /* The non-NULL form decodes to the original */
2854 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2855 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2856 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
2857 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
2858 if (buf)
2859 {
2860 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2861 LocalFree(buf);
2862 }
2863 }
2864 /* Test with bogus (not valid DER) parameters */
2865 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2866 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2867 NULL, &buf, &bufSize);
2868 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
2869 GetLastError() == OSS_DATA_ERROR /* Win9x */),
2870 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
2871 GetLastError());
2872 }
2873
2874 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2875 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2876 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2877 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2878 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2879 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2880 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2881 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2882 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2883 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2884 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2885 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2886 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2887 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2888 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2889 static const BYTE v4Cert[] = {
2890 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22,
2891 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
2892 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,
2893 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 };
2894 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2895 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2896 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2897 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2898 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2899 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2900 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2901 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2902 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2903 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2904 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2905 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2906 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2907 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2908 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2909 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2910 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2911 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2912 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2913 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2914 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2915 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2916 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2917 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2918 static const BYTE v1CertWithPubKey[] = {
2919 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2920 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2921 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2922 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2923 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2924 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2925 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2926 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2927 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,
2928 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,
2929 0x01,0x01 };
2930 static const BYTE v1CertWithPubKeyNoNull[] = {
2931 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2932 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2933 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2934 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2935 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2936 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2937 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2938 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2939 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,
2940 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
2941 static const BYTE v1CertWithSubjectKeyId[] = {
2942 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
2943 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2944 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
2945 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
2946 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
2947 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
2948 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30,
2949 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,
2950 0x4c,0x61,0x6e,0x67,0x00 };
2951 static const BYTE v1CertWithIssuerUniqueId[] = {
2952 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,
2953 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,
2954 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
2955 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 };
2956 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = {
2957 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2958 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2959 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2960 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2961 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2962 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2963 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2964 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
2965 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,
2966 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,
2967 0x01,0x01,0xff,0x02,0x01,0x01 };
2968 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = {
2969 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,
2970 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,
2971 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,
2972 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
2973 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,
2974 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
2975 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,
2976 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
2977 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,
2978 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,
2979 0xff,0x02,0x01,0x01 };
2980
2981 static const BYTE serialNum[] = { 0x01 };
2982
2983 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2984 {
2985 BOOL ret;
2986 BYTE *buf = NULL;
2987 DWORD size = 0;
2988 CERT_INFO info = { 0 };
2989 static char oid_rsa_rsa[] = szOID_RSA_RSA;
2990 static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER;
2991 CERT_EXTENSION ext;
2992
2993 if (0)
2994 {
2995 /* Test with NULL pvStructInfo (crashes on win9x) */
2996 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2997 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
2998 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2999 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3000 }
3001 /* Test with a V1 cert */
3002 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3003 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3004 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3005 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3006 if (buf)
3007 {
3008 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n",
3009 v1Cert[1] + 2, size);
3010 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
3011 LocalFree(buf);
3012 }
3013 /* Test v2 cert */
3014 info.dwVersion = CERT_V2;
3015 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3016 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3017 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3018 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3019 if (buf)
3020 {
3021 ok(size == sizeof(v2Cert), "Wrong size %d\n", size);
3022 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
3023 LocalFree(buf);
3024 }
3025 /* Test v3 cert */
3026 info.dwVersion = CERT_V3;
3027 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3028 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3029 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3030 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3031 if (buf)
3032 {
3033 ok(size == sizeof(v3Cert), "Wrong size %d\n", size);
3034 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
3035 LocalFree(buf);
3036 }
3037 /* A v4 cert? */
3038 info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */
3039 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3040 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3041 if (buf)
3042 {
3043 ok(size == sizeof(v4Cert), "Wrong size %d\n", size);
3044 ok(!memcmp(buf, v4Cert, size), "Unexpected value\n");
3045 LocalFree(buf);
3046 }
3047 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
3048 * API doesn't prevent it)
3049 */
3050 info.dwVersion = CERT_V1;
3051 info.cExtension = 1;
3052 info.rgExtension = &criticalExt;
3053 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3054 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3055 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */,
3056 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3057 if (buf)
3058 {
3059 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size);
3060 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
3061 LocalFree(buf);
3062 }
3063 /* test v1 cert with a serial number */
3064 info.SerialNumber.cbData = sizeof(serialNum);
3065 info.SerialNumber.pbData = (BYTE *)serialNum;
3066 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3067 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3068 if (buf)
3069 {
3070 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size);
3071 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
3072 LocalFree(buf);
3073 }
3074 /* Test v1 cert with an issuer name, serial number, and issuer unique id */
3075 info.dwVersion = CERT_V1;
3076 info.cExtension = 0;
3077 info.IssuerUniqueId.cbData = sizeof(serialNum);
3078 info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3079 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3080 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3081 ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */),
3082 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3083 if (buf)
3084 {
3085 ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size);
3086 ok(!memcmp(buf, v1CertWithIssuerUniqueId, size),
3087 "Got unexpected value\n");
3088 LocalFree(buf);
3089 }
3090 /* Test v1 cert with an issuer name, a subject name, and a serial number */
3091 info.IssuerUniqueId.cbData = 0;
3092 info.IssuerUniqueId.pbData = NULL;
3093 info.cExtension = 1;
3094 info.rgExtension = &criticalExt;
3095 info.Issuer.cbData = sizeof(encodedCommonName);
3096 info.Issuer.pbData = (BYTE *)encodedCommonName;
3097 info.Subject.cbData = sizeof(encodedCommonName);
3098 info.Subject.pbData = (BYTE *)encodedCommonName;
3099 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3100 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3101 if (buf)
3102 {
3103 ok(size == sizeof(bigCert), "Wrong size %d\n", size);
3104 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
3105 LocalFree(buf);
3106 }
3107 /* Add a public key */
3108 info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa;
3109 info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey);
3110 info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey;
3111 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3112 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3113 if (buf)
3114 {
3115 ok(size == sizeof(v1CertWithPubKey) ||
3116 size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size);
3117 if (size == sizeof(v1CertWithPubKey))
3118 ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n");
3119 else if (size == sizeof(v1CertWithPubKeyNoNull))
3120 ok(!memcmp(buf, v1CertWithPubKeyNoNull, size),
3121 "Got unexpected value\n");
3122 LocalFree(buf);
3123 }
3124 /* Again add an issuer unique id */
3125 info.IssuerUniqueId.cbData = sizeof(serialNum);
3126 info.IssuerUniqueId.pbData = (BYTE *)serialNum;
3127 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3128 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3129 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3130 if (buf)
3131 {
3132 ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) ||
3133 size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull),
3134 "Wrong size %d\n", size);
3135 if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId))
3136 ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3137 size), "unexpected value\n");
3138 else if (size ==
3139 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull))
3140 ok(!memcmp(buf,
3141 v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size),
3142 "unexpected value\n");
3143 LocalFree(buf);
3144 }
3145 /* Remove the public key, and add a subject key identifier extension */
3146 info.IssuerUniqueId.cbData = 0;
3147 info.IssuerUniqueId.pbData = NULL;
3148 info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL;
3149 info.SubjectPublicKeyInfo.PublicKey.cbData = 0;
3150 info.SubjectPublicKeyInfo.PublicKey.pbData = NULL;
3151 ext.pszObjId = oid_subject_key_identifier;
3152 ext.fCritical = FALSE;
3153 ext.Value.cbData = sizeof(octetCommonNameValue);
3154 ext.Value.pbData = octetCommonNameValue;
3155 info.cExtension = 1;
3156 info.rgExtension = &ext;
3157 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
3158 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3159 if (buf)
3160 {
3161 ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size);
3162 ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n");
3163 LocalFree(buf);
3164 }
3165 }
3166
3167 static void test_decodeCertToBeSigned(DWORD dwEncoding)
3168 {
3169 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert,
3170 v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId };
3171 BOOL ret;
3172 BYTE *buf = NULL;
3173 DWORD size = 0, i;
3174
3175 /* Test with NULL pbEncoded */
3176 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
3177 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3178 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
3179 GetLastError() == OSS_BAD_ARG /* Win9x */),
3180 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError());
3181 if (0)
3182 {
3183 /* Crashes on win9x */
3184 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
3185 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3186 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3187 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3188 }
3189 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or
3190 * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero
3191 * serial number, an issuer, a subject, and a public key.
3192 */
3193 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
3194 {
3195 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3196 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3197 &buf, &size);
3198 ok(!ret, "Expected failure\n");
3199 }
3200 /* The following succeeds, even though v1 certs are not allowed to have
3201 * extensions.
3202 */
3203 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3204 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId),
3205 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3206 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3207 if (ret)
3208 {
3209 CERT_INFO *info = (CERT_INFO *)buf;
3210
3211 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3212 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3213 info->dwVersion);
3214 ok(info->cExtension == 1, "expected 1 extension, got %d\n",
3215 info->cExtension);
3216 LocalFree(buf);
3217 }
3218 /* The following also succeeds, even though V1 certs are not allowed to
3219 * have issuer unique ids.
3220 */
3221 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3222 v1CertWithSubjectIssuerSerialAndIssuerUniqueId,
3223 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId),
3224 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3225 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3226 if (ret)
3227 {
3228 CERT_INFO *info = (CERT_INFO *)buf;
3229
3230 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3231 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n",
3232 info->dwVersion);
3233 ok(info->IssuerUniqueId.cbData == sizeof(serialNum),
3234 "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData);
3235 ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)),
3236 "unexpected issuer unique id value\n");
3237 LocalFree(buf);
3238 }
3239 /* Now check with serial number, subject and issuer specified */
3240 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
3241 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3242 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3243 if (buf)
3244 {
3245 CERT_INFO *info = (CERT_INFO *)buf;
3246
3247 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3248 ok(info->SerialNumber.cbData == 1,
3249 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3250 ok(*info->SerialNumber.pbData == *serialNum,
3251 "Expected serial number %d, got %d\n", *serialNum,
3252 *info->SerialNumber.pbData);
3253 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3254 "Wrong size %d\n", info->Issuer.cbData);
3255 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3256 "Unexpected issuer\n");
3257 ok(info->Subject.cbData == sizeof(encodedCommonName),
3258 "Wrong size %d\n", info->Subject.cbData);
3259 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3260 info->Subject.cbData), "Unexpected subject\n");
3261 LocalFree(buf);
3262 }
3263 /* Check again with pub key specified */
3264 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
3265 v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL,
3266 &buf, &size);
3267 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3268 if (buf)
3269 {
3270 CERT_INFO *info = (CERT_INFO *)buf;
3271
3272 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3273 ok(info->SerialNumber.cbData == 1,
3274 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3275 ok(*info->SerialNumber.pbData == *serialNum,
3276 "Expected serial number %d, got %d\n", *serialNum,
3277 *info->SerialNumber.pbData);
3278 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3279 "Wrong size %d\n", info->Issuer.cbData);
3280 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3281 "Unexpected issuer\n");
3282 ok(info->Subject.cbData == sizeof(encodedCommonName),
3283 "Wrong size %d\n", info->Subject.cbData);
3284 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3285 info->Subject.cbData), "Unexpected subject\n");
3286 ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId,
3287 szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n",
3288 info->SubjectPublicKeyInfo.Algorithm.pszObjId);
3289 ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey),
3290 "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData);
3291 ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey,
3292 sizeof(aKey)), "Unexpected public key\n");
3293 LocalFree(buf);
3294 }
3295 }
3296
3297 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
3298 0xe, 0xf };
3299
3300 static const BYTE signedBigCert[] = {
3301 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
3302 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
3303 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
3304 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3305 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
3306 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
3307 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
3308 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
3309 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
3310 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3311 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
3312 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
3313
3314 static void test_encodeCert(DWORD dwEncoding)
3315 {
3316 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
3317 * also that bigCert is a NULL-terminated string, so don't count its
3318 * last byte (otherwise the signed cert won't decode.)
3319 */
3320 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
3321 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
3322 BOOL ret;
3323 BYTE *buf = NULL;
3324 DWORD bufSize = 0;
3325
3326 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
3327 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
3328 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3329 if (buf)
3330 {
3331 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize);
3332 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
3333 LocalFree(buf);
3334 }
3335 }
3336
3337 static void test_decodeCert(DWORD dwEncoding)
3338 {
3339 BOOL ret;
3340 BYTE *buf = NULL;
3341 DWORD size = 0;
3342
3343 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
3344 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3345 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3346 if (buf)
3347 {
3348 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
3349
3350 ok(info->ToBeSigned.cbData == sizeof(bigCert),
3351 "Wrong cert size %d\n", info->ToBeSigned.cbData);
3352 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
3353 "Unexpected cert\n");
3354 ok(info->Signature.cbData == sizeof(hash),
3355 "Wrong signature size %d\n", info->Signature.cbData);
3356 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
3357 "Unexpected signature\n");
3358 LocalFree(buf);
3359 }
3360 /* A signed cert decodes as a CERT_INFO too */
3361 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert,
3362 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3363 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3364 if (buf)
3365 {
3366 CERT_INFO *info = (CERT_INFO *)buf;
3367
3368 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size);
3369 ok(info->SerialNumber.cbData == 1,
3370 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData);
3371 ok(*info->SerialNumber.pbData == *serialNum,
3372 "Expected serial number %d, got %d\n", *serialNum,
3373 *info->SerialNumber.pbData);
3374 ok(info->Issuer.cbData == sizeof(encodedCommonName),
3375 "Wrong size %d\n", info->Issuer.cbData);
3376 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
3377 "Unexpected issuer\n");
3378 ok(info->Subject.cbData == sizeof(encodedCommonName),
3379 "Wrong size %d\n", info->Subject.cbData);
3380 ok(!memcmp(info->Subject.pbData, encodedCommonName,
3381 info->Subject.cbData), "Unexpected subject\n");
3382 LocalFree(buf);
3383 }
3384 }
3385
3386 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
3387 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
3388 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
3389 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3390 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
3391 0x00, 0x03 };
3392 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
3393 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
3394 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
3395 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
3396 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
3397 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
3398 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
3399 0x2e, 0x6f, 0x72, 0x67 };
3400 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
3401 CRL_REASON_AFFILIATION_CHANGED;
3402
3403 static void test_encodeCRLDistPoints(DWORD dwEncoding)
3404 {
3405 CRL_DIST_POINTS_INFO info = { 0 };
3406 CRL_DIST_POINT point = { { 0 } };
3407 CERT_ALT_NAME_ENTRY entry = { 0 };
3408 BOOL ret;
3409 BYTE *buf = NULL;
3410 DWORD size = 0;
3411
3412 /* Test with an empty info */
3413 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3414 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3415 ok(!ret && GetLastError() == E_INVALIDARG,
3416 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3417 /* Test with one empty dist point */
3418 info.cDistPoint = 1;
3419 info.rgDistPoint = &point;
3420 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3421 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3422 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3423 if (buf)
3424 {
3425 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size);
3426 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
3427 LocalFree(buf);
3428 }
3429 /* A dist point with an invalid name */
3430 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3431 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3432 U(entry).pwszURL = (LPWSTR)nihongoURL;
3433 U(point.DistPointName).FullName.cAltEntry = 1;
3434 U(point.DistPointName).FullName.rgAltEntry = &entry;
3435 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3436 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3437 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
3438 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError());
3439 /* The first invalid character is at index 7 */
3440 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
3441 "Expected invalid char at index 7, got %d\n",
3442 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
3443 /* A dist point with (just) a valid name */
3444 U(entry).pwszURL = (LPWSTR)url;
3445 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3446 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3447 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3448 if (buf)
3449 {
3450 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size);
3451 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
3452 LocalFree(buf);
3453 }
3454 /* A dist point with (just) reason flags */
3455 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
3456 point.ReasonFlags.cbData = sizeof(crlReason);
3457 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
3458 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3459 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3460 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3461 if (buf)
3462 {
3463 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size);
3464 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
3465 LocalFree(buf);
3466 }
3467 /* A dist point with just an issuer */
3468 point.ReasonFlags.cbData = 0;
3469 point.CRLIssuer.cAltEntry = 1;
3470 point.CRLIssuer.rgAltEntry = &entry;
3471 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
3472 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3473 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3474 if (buf)
3475 {
3476 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size);
3477 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
3478 LocalFree(buf);
3479 }
3480 /* A dist point with both a name and an issuer */
3481 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
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 (buf)
3486 {
3487 ok(size == sizeof(distPointWithUrlAndIssuer),
3488 "Wrong size %d\n", size);
3489 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
3490 LocalFree(buf);
3491 }
3492 }
3493
3494 static void test_decodeCRLDistPoints(DWORD dwEncoding)
3495 {
3496 BOOL ret;
3497 BYTE *buf = NULL;
3498 DWORD size = 0;
3499 PCRL_DIST_POINTS_INFO info;
3500 PCRL_DIST_POINT point;
3501 PCERT_ALT_NAME_ENTRY entry;
3502
3503 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3504 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3505 &buf, &size);
3506 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3507 if (ret)
3508 {
3509 info = (PCRL_DIST_POINTS_INFO)buf;
3510 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3511 "Wrong size %d\n", size);
3512 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3513 info->cDistPoint);
3514 point = info->rgDistPoint;
3515 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
3516 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3517 point->DistPointName.dwDistPointNameChoice);
3518 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3519 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3520 LocalFree(buf);
3521 }
3522 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3523 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3524 &buf, &size);
3525 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3526 if (ret)
3527 {
3528 info = (PCRL_DIST_POINTS_INFO)buf;
3529 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3530 "Wrong size %d\n", size);
3531 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3532 info->cDistPoint);
3533 point = info->rgDistPoint;
3534 ok(point->DistPointName.dwDistPointNameChoice ==
3535 CRL_DIST_POINT_FULL_NAME,
3536 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3537 point->DistPointName.dwDistPointNameChoice);
3538 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3539 "Expected 1 name entry, got %d\n",
3540 U(point->DistPointName).FullName.cAltEntry);
3541 entry = U(point->DistPointName).FullName.rgAltEntry;
3542 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3543 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3544 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3545 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3546 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3547 LocalFree(buf);
3548 }
3549 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3550 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
3551 NULL, &buf, &size);
3552 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3553 if (ret)
3554 {
3555 info = (PCRL_DIST_POINTS_INFO)buf;
3556 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3557 "Wrong size %d\n", size);
3558 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3559 info->cDistPoint);
3560 point = info->rgDistPoint;
3561 ok(point->DistPointName.dwDistPointNameChoice ==
3562 CRL_DIST_POINT_NO_NAME,
3563 "Expected CRL_DIST_POINT_NO_NAME, got %d\n",
3564 point->DistPointName.dwDistPointNameChoice);
3565 ok(point->ReasonFlags.cbData == sizeof(crlReason),
3566 "Expected reason length\n");
3567 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
3568 "Unexpected reason\n");
3569 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
3570 LocalFree(buf);
3571 }
3572 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
3573 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
3574 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3575 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3576 if (ret)
3577 {
3578 info = (PCRL_DIST_POINTS_INFO)buf;
3579 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
3580 "Wrong size %d\n", size);
3581 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n",
3582 info->cDistPoint);
3583 point = info->rgDistPoint;
3584 ok(point->DistPointName.dwDistPointNameChoice ==
3585 CRL_DIST_POINT_FULL_NAME,
3586 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n",
3587 point->DistPointName.dwDistPointNameChoice);
3588 ok(U(point->DistPointName).FullName.cAltEntry == 1,
3589 "Expected 1 name entry, got %d\n",
3590 U(point->DistPointName).FullName.cAltEntry);
3591 entry = U(point->DistPointName).FullName.rgAltEntry;
3592 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3593 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3594 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3595 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
3596 ok(point->CRLIssuer.cAltEntry == 1,
3597 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry);
3598 entry = point->CRLIssuer.rgAltEntry;
3599 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
3600 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice);
3601 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
3602 LocalFree(buf);
3603 }
3604 }
3605
3606 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff };
3607 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 };
3608 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68,
3609 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,
3610 0x67 };
3611
3612 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding)
3613 {
3614 BOOL ret;
3615 BYTE *buf = NULL;
3616 DWORD size = 0;
3617 CRL_ISSUING_DIST_POINT point = { { 0 } };
3618 CERT_ALT_NAME_ENTRY entry;
3619
3620 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL,
3621 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3622 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3623 {
3624 skip("no X509_ISSUING_DIST_POINT encode support\n");
3625 return;
3626 }
3627 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3628 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3629 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3630 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3631 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3632 if (buf)
3633 {
3634 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
3635 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
3636 LocalFree(buf);
3637 }
3638 /* nonsensical flags */
3639 point.fOnlyContainsUserCerts = TRUE;
3640 point.fOnlyContainsCACerts = TRUE;
3641 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3642 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3643 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3644 if (buf)
3645 {
3646 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size);
3647 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n");
3648 LocalFree(buf);
3649 }
3650 /* unimplemented name type */
3651 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3652 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME;
3653 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3654 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3655 ok(!ret && GetLastError() == E_INVALIDARG,
3656 "Expected E_INVALIDARG, got %08x\n", GetLastError());
3657 /* empty name */
3658 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3659 U(point.DistPointName).FullName.cAltEntry = 0;
3660 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3661 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3662 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3663 if (buf)
3664 {
3665 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size);
3666 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n");
3667 LocalFree(buf);
3668 }
3669 /* name with URL entry */
3670 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3671 U(entry).pwszURL = (LPWSTR)url;
3672 U(point.DistPointName).FullName.cAltEntry = 1;
3673 U(point.DistPointName).FullName.rgAltEntry = &entry;
3674 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point,
3675 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3676 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3677 if (buf)
3678 {
3679 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size);
3680 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n");
3681 LocalFree(buf);
3682 }
3683 }
3684
3685 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected,
3686 const CERT_ALT_NAME_ENTRY *got)
3687 {
3688 ok(expected->dwAltNameChoice == got->dwAltNameChoice,
3689 "Expected name choice %d, got %d\n", expected->dwAltNameChoice,
3690 got->dwAltNameChoice);
3691 if (expected->dwAltNameChoice == got->dwAltNameChoice)
3692 {
3693 switch (got->dwAltNameChoice)
3694 {
3695 case CERT_ALT_NAME_RFC822_NAME:
3696 case CERT_ALT_NAME_DNS_NAME:
3697 case CERT_ALT_NAME_EDI_PARTY_NAME:
3698 case CERT_ALT_NAME_URL:
3699 case CERT_ALT_NAME_REGISTERED_ID:
3700 ok((!U(*expected).pwszURL && !U(*got).pwszURL) ||
3701 (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) ||
3702 (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) ||
3703 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL),
3704 "Unexpected name\n");
3705 break;
3706 case CERT_ALT_NAME_X400_ADDRESS:
3707 case CERT_ALT_NAME_DIRECTORY_NAME:
3708 case CERT_ALT_NAME_IP_ADDRESS:
3709 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData,
3710 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData);
3711 ok(!memcmp(U(*got).IPAddress.pbData, U(*got).IPAddress.pbData,
3712 U(*got).IPAddress.cbData), "Unexpected value\n");
3713 break;
3714 }
3715 }
3716 }
3717
3718 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected,
3719 const CERT_ALT_NAME_INFO *got)
3720 {
3721 DWORD i;
3722
3723 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n",
3724 expected->cAltEntry, got->cAltEntry);
3725 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++)
3726 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]);
3727 }
3728
3729 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected,
3730 const CRL_DIST_POINT_NAME *got)
3731 {
3732 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice,
3733 "Unexpected name choice %d\n", got->dwDistPointNameChoice);
3734 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME)
3735 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName));
3736 }
3737
3738 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected,
3739 const CRL_ISSUING_DIST_POINT *got)
3740 {
3741 compareDistPointName(&expected->DistPointName, &got->DistPointName);
3742 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts,
3743 "Unexpected fOnlyContainsUserCerts\n");
3744 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts,
3745 "Unexpected fOnlyContainsCACerts\n");
3746 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData,
3747 "Unexpected reason flags\n");
3748 ok(got->fIndirectCRL == expected->fIndirectCRL,
3749 "Unexpected fIndirectCRL\n");
3750 }
3751
3752 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding)
3753 {
3754 BOOL ret;
3755 BYTE *buf = NULL;
3756 DWORD size = 0;
3757 CRL_ISSUING_DIST_POINT point = { { 0 } };
3758
3759 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3760 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3761 &buf, &size);
3762 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
3763 {
3764 skip("no X509_ISSUING_DIST_POINT decode support\n");
3765 return;
3766 }
3767 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3768 if (ret)
3769 {
3770 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3771 LocalFree(buf);
3772 }
3773 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3774 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3775 &buf, &size);
3776 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3777 if (ret)
3778 {
3779 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE;
3780 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3781 LocalFree(buf);
3782 }
3783 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3784 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
3785 &buf, &size);
3786 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3787 if (ret)
3788 {
3789 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE;
3790 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
3791 U(point.DistPointName).FullName.cAltEntry = 0;
3792 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3793 LocalFree(buf);
3794 }
3795 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT,
3796 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
3797 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
3798 if (ret)
3799 {
3800 CERT_ALT_NAME_ENTRY entry;
3801
3802 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
3803 U(entry).pwszURL = (LPWSTR)url;
3804 U(point.DistPointName).FullName.cAltEntry = 1;
3805 U(point.DistPointName).FullName.rgAltEntry = &entry;
3806 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf);
3807 LocalFree(buf);
3808 }
3809 }
3810
3811 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
3812 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3813 0x30, 0x5a };
3814 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
3815 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
3816 0x30, 0x30, 0x30, 0x30, 0x5a };
3817 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
3818 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
3819 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
3820 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
3821 0x5a };
3822 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
3823 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
3824 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
3825 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
3826 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
3827 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3828 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
3829 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
3830 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
3831 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
3832 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
3833 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
3834 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30,
3835 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,
3836 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
3837 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01,
3838 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,
3839 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,
3840 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3841 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15,
3842 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
3843 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
3844 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01,
3845 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
3846 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
3847 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3848 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06,
3849 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,
3850 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,
3851 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,
3852 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,
3853 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,
3854 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
3855
3856 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
3857 {
3858 BOOL ret;
3859 BYTE *buf = NULL;
3860 DWORD size = 0;
3861 CRL_INFO info = { 0 };
3862 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
3863
3864 /* Test with a V1 CRL */
3865 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3866 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3867 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3868 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3869 if (buf)
3870 {
3871 ok(size == sizeof(v1CRL), "Wrong size %d\n", size);
3872 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
3873 LocalFree(buf);
3874 }
3875 /* Test v2 CRL */
3876 info.dwVersion = CRL_V2;
3877 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3878 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3879 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */),
3880 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3881 if (buf)
3882 {
3883 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n",
3884 v2CRL[1] + 2, size);
3885 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
3886 LocalFree(buf);
3887 }
3888 /* v1 CRL with a name */
3889 info.dwVersion = CRL_V1;
3890 info.Issuer.cbData = sizeof(encodedCommonName);
3891 info.Issuer.pbData = (BYTE *)encodedCommonName;
3892 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3893 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3894 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3895 if (buf)
3896 {
3897 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size);
3898 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
3899 LocalFree(buf);
3900 }
3901 if (0)
3902 {
3903 /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */
3904 info.cCRLEntry = 1;
3905 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3906 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3907 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
3908 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError());
3909 }
3910 /* now set an empty entry */
3911 info.cCRLEntry = 1;
3912 info.rgCRLEntry = &entry;
3913 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3914 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3915 if (buf)
3916 {
3917 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
3918 "Wrong size %d\n", size);
3919 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
3920 "Got unexpected value\n");
3921 LocalFree(buf);
3922 }
3923 /* an entry with a serial number */
3924 entry.SerialNumber.cbData = sizeof(serialNum);
3925 entry.SerialNumber.pbData = (BYTE *)serialNum;
3926 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3927 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3928 if (buf)
3929 {
3930 ok(size == sizeof(v1CRLWithIssuerAndEntry),
3931 "Wrong size %d\n", size);
3932 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
3933 "Got unexpected value\n");
3934 LocalFree(buf);
3935 }
3936 /* an entry with an extension */
3937 entry.cExtension = 1;
3938 entry.rgExtension = &criticalExt;
3939 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3940 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3941 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3942 if (buf)
3943 {
3944 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size);
3945 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n");
3946 LocalFree(buf);
3947 }
3948 /* a CRL with an extension */
3949 entry.cExtension = 0;
3950 info.cExtension = 1;
3951 info.rgExtension = &criticalExt;
3952 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3953 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3954 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3955 if (buf)
3956 {
3957 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size);
3958 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
3959 LocalFree(buf);
3960 }
3961 /* a v2 CRL with an extension, this time non-critical */
3962 info.dwVersion = CRL_V2;
3963 info.rgExtension = &nonCriticalExt;
3964 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
3965 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
3966 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
3967 if (buf)
3968 {
3969 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size);
3970 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n");
3971 LocalFree(buf);
3972 }
3973 }
3974
3975 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01,
3976 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
3977 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06,
3978 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65,
3979 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56,
3980 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e,
3981 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65,
3982 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72,
3983 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65,
3984 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43,
3985 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30,
3986 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33,
3987 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51,
3988 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99,
3989 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31,
3990 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0,
3991 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30,
3992 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30,
3993 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75,
3994 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33,
3995 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30,
3996 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06,
3997 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06,
3998 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03,
3999 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88,
4000 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd,
4001 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf,
4002 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46,
4003 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f,
4004 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75,
4005 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f,
4006 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82,
4007 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07,
4008 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c,
4009 0xcd };
4010 static const BYTE verisignCRLWithLotsOfEntries[] = {
4011 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,
4012 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06,
4013 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31,
4014 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53,
4015 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03,
4016 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43,
4017 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77,
4018 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20,
4019 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30,
4020 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35,
4021 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3,
4022 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32,
4023 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,
4024 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13,
4025 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38,
4026 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16,
4027 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4028 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94,
4029 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32,
4030 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4031 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67,
4032 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30,
4033 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87,
4034 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30,
4035 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f,
4036 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32,
4037 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,
4038 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac,
4039 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31,
4040 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee,
4041 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31,
4042 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37,
4043 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32,
4044 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4045 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c,
4046 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34,
4047 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11,
4048 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,
4049 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5,
4050 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32,
4051 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,
4052 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d,
4053 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39,
4054 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70,
4055 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30,
4056 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5,
4057 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33,
4058 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,
4059 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39,
4060 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30,
4061 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98,
4062 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,
4063 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4,
4064 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32,
4065 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4066 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1,
4067 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32,
4068 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05,
4069 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,
4070 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32,
4071 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32,
4072 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,
4073 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7,
4074 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31,
4075 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79,
4076 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30,
4077 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4,
4078 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32,
4079 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,
4080 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a,
4081 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35,
4082 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d,
4083 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31,
4084 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b,
4085 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32,
4086 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10,
4087 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40,
4088 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37,
4089 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6,
4090 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31,
4091 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28,
4092 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32,
4093 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,
4094 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65,
4095 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39,
4096 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2,
4097 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32,
4098 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f,
4099 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32,
4100 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,
4101 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21,
4102 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36,
4103 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33,
4104 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30,
4105 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2,
4106 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32,
4107 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,
4108 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc,
4109 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33,
4110 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8,
4111 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31,
4112 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48,
4113 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32,
4114 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,
4115 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40,
4116 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34,
4117 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54,
4118 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30,
4119 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6,
4120 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32,
4121 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,
4122 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd,
4123 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32,
4124 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9,
4125 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31,
4126 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd,
4127 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32,
4128 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,
4129 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5,
4130 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31,
4131 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb,
4132 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,
4133 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5,
4134 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32,
4135 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10,
4136 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45,
4137 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32,
4138 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf,
4139 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35,
4140 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88,
4141 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30,
4142 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20,
4143 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92,
4144 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a,
4145 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45,
4146 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33,
4147 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9,
4148 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30,
4149 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22,
4150 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a,
4151 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a,
4152 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e,
4153 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30,
4154 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f,
4155 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30,
4156 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25,
4157 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0,
4158 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a,
4159 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84,
4160 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31,
4161 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec,
4162 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30,
4163 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27,
4164 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16,
4165 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a,
4166 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81,
4167 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31,
4168 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e,
4169 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30,
4170 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29,
4171 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59,
4172 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a,
4173 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9,
4174 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38,
4175 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3,
4176 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30,
4177 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a,
4178 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1,
4179 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a,
4180 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f,
4181 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30,
4182 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71,
4183 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30,
4184 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,
4185 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85,
4186 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a,
4187 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b,
4188 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33,
4189 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92,
4190 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30,
4191 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,
4192 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e,
4193 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a,
4194 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13,
4195 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37,
4196 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01,
4197 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30,
4198 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e,
4199 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3,
4200 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a,
4201 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70,
4202 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31,
4203 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20,
4204 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30,
4205 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f,
4206 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c,
4207 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a,
4208 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f,
4209 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33,
4210 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3,
4211 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30,
4212 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30,
4213 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b,
4214 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a,
4215 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0,
4216 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37,
4217 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63,
4218 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30,
4219 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32,
4220 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09,
4221 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a,
4222 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b,
4223 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37,
4224 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61,
4225 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30,
4226 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34,
4227 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe,
4228 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a,
4229 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30,
4230 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31,
4231 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85,
4232 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30,
4233 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,
4234 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4,
4235 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a,
4236 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55,
4237 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30,
4238 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36,
4239 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30,
4240 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a,
4241 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d,
4242 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a,
4243 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f,
4244 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33,
4245 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97,
4246 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30,
4247 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b,
4248 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4,
4249 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a,
4250 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76,
4251 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,
4252 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a,
4253 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30,
4254 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c,
4255 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd,
4256 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a,
4257 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae,
4258 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39,
4259 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39,
4260 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31,
4261 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d,
4262 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80,
4263 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a,
4264 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b,
4265 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31,
4266 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd,
4267 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30,
4268 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41,
4269 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e,
4270 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a,
4271 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93,
4272 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32,
4273 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28,
4274 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30,
4275 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42,
4276 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c,
4277 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a,
4278 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74,
4279 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36,
4280 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c,
4281 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30,
4282 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45,
4283 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83,
4284 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a,
4285 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12,
4286 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36,
4287 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98,
4288 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30,
4289 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47,
4290 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75,
4291 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a,
4292 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b,
4293 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34,
4294 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81,
4295 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30,
4296 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49,
4297 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51,
4298 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a,
4299 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53,
4300 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31,
4301 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5,
4302 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30,
4303 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c,
4304 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd,
4305 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a,
4306 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37,
4307 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39,
4308 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9,
4309 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30,
4310 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d,
4311 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32,
4312 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a,
4313 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1,
4314 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30,
4315 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86,
4316 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30,
4317 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50,
4318 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82,
4319 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a,
4320 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03,
4321 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30,
4322 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b,
4323 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30,
4324 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52,
4325 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f,
4326 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a,
4327 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69,
4328 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31,
4329 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c,
4330 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30,
4331 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,
4332 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a,
4333 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a,
4334 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68,
4335 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34,
4336 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62,
4337 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30,
4338 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58,
4339 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d,
4340 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a,
4341 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25,
4342 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37,
4343 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3,
4344 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30,
4345 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59,
4346 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd,
4347 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a,
4348 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb,
4349 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30,
4350 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9,
4351 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30,
4352 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a,
4353 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d,
4354 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a,
4355 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58,
4356 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37,
4357 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3,
4358 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30,
4359 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b,
4360 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e,
4361 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a,
4362 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd,
4363 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35,
4364 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1,
4365 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31,
4366 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e,
4367 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca,
4368 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a,
4369 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a,
4370 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35,
4371 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd,
4372 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30,
4373 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,
4374 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2,
4375 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a,
4376 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5,
4377 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36,
4378 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5,
4379 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30,
4380 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60,
4381 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4,
4382 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a,
4383 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09,
4384 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37,
4385 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83,
4386 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30,
4387 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60,
4388 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2,
4389 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a,
4390 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70,
4391 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39,
4392 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17,
4393 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30,
4394 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61,
4395 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97,
4396 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a,
4397 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd,
4398 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38,
4399 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82,
4400 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30,
4401 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62,
4402 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2,
4403 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a,
4404 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee,
4405 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36,
4406 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d,
4407 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30,
4408 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63,
4409 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86,
4410 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a,
4411 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3,
4412 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31,
4413 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22,
4414 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31,
4415 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65,
4416 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7,
4417 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a,
4418 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e,
4419 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37,
4420 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7,
4421 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30,
4422 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67,
4423 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0,
4424 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a,
4425 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0,
4426 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31,
4427 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04,
4428 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30,
4429 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69,
4430 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16,
4431 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a,
4432 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6,
4433 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39,
4434 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9,
4435 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31,
4436 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b,
4437 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53,
4438 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a,
4439 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e,
4440 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34,
4441 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a,
4442 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30,
4443 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d,
4444 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c,
4445 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a,
4446 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16,
4447 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32,
4448 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae,
4449 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30,
4450 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f,
4451 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1,
4452 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a,
4453 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c,
4454 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30,
4455 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5,
4456 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30,
4457 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70,
4458 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48,
4459 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a,
4460 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8,
4461 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39,
4462 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b,
4463 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30,
4464 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72,
4465 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39,
4466 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a,
4467 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39,
4468 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33,
4469 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17,
4470 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30,
4471 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75,
4472 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd,
4473 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,
4474 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd,
4475 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38,
4476 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde,
4477 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30,
4478 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76,
4479 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03,
4480 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a,
4481 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d,
4482 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31,
4483 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93,
4484 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30,
4485 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78,
4486 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51,
4487 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a,
4488 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10,
4489 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38,
4490 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f,
4491 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30,
4492 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78,
4493 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67,
4494 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a,
4495 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79,
4496 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36,
4497 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02,
4498 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30,
4499 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b,
4500 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea,
4501 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a,
4502 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc,
4503 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30,
4504 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5,
4505 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30,
4506 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f,
4507 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b,
4508 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a,
4509 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,
4510 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2,
4511 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08,
4512 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84,
4513 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68,
4514 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c,
4515 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f,
4516 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43,
4517 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c,
4518 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 };
4519
4520 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
4521 {
4522 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
4523 BOOL ret;
4524 BYTE *buf = NULL;
4525 DWORD size = 0, i;
4526
4527 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
4528 {
4529 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4530 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4531 &buf, &size);
4532 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4533 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4534 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4535 GetLastError());
4536 }
4537 /* at a minimum, a CRL must contain an issuer: */
4538 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4539 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
4540 &buf, &size);
4541 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4542 if (buf)
4543 {
4544 CRL_INFO *info = (CRL_INFO *)buf;
4545
4546 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4547 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n",
4548 info->cCRLEntry);
4549 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4550 "Wrong issuer size %d\n", info->Issuer.cbData);
4551 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4552 "Unexpected issuer\n");
4553 LocalFree(buf);
4554 }
4555 /* check decoding with an empty CRL entry */
4556 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4557 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
4558 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4559 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
4560 GetLastError() == OSS_DATA_ERROR /* Win9x */),
4561 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n",
4562 GetLastError());
4563 /* with a real CRL entry */
4564 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4565 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
4566 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4567 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4568 if (buf)
4569 {
4570 CRL_INFO *info = (CRL_INFO *)buf;
4571 CRL_ENTRY *entry;
4572
4573 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4574 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4575 info->cCRLEntry);
4576 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4577 entry = info->rgCRLEntry;
4578 ok(entry->SerialNumber.cbData == 1,
4579 "Expected serial number size 1, got %d\n",
4580 entry->SerialNumber.cbData);
4581 ok(*entry->SerialNumber.pbData == *serialNum,
4582 "Expected serial number %d, got %d\n", *serialNum,
4583 *entry->SerialNumber.pbData);
4584 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4585 "Wrong issuer size %d\n", info->Issuer.cbData);
4586 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4587 "Unexpected issuer\n");
4588 LocalFree(buf);
4589 }
4590 /* a real CRL from verisign that has extensions */
4591 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4592 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG,
4593 NULL, &buf, &size);
4594 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4595 if (buf)
4596 {
4597 CRL_INFO *info = (CRL_INFO *)buf;
4598
4599 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4600 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n",
4601 info->cCRLEntry);
4602 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4603 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n",
4604 info->cExtension);
4605 LocalFree(buf);
4606 }
4607 /* another real CRL from verisign that has lots of entries */
4608 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4609 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries),
4610 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4611 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4612 if (buf)
4613 {
4614 CRL_INFO *info = (CRL_INFO *)buf;
4615
4616 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size);
4617 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n",
4618 info->cCRLEntry);
4619 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n",
4620 info->cExtension);
4621 LocalFree(buf);
4622 }
4623 /* and finally, with an extension */
4624 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4625 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4626 NULL, &buf, &size);
4627 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4628 if (buf)
4629 {
4630 CRL_INFO *info = (CRL_INFO *)buf;
4631 CRL_ENTRY *entry;
4632
4633 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size);
4634 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n",
4635 info->cCRLEntry);
4636 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
4637 entry = info->rgCRLEntry;
4638 ok(entry->SerialNumber.cbData == 1,
4639 "Expected serial number size 1, got %d\n",
4640 entry->SerialNumber.cbData);
4641 ok(*entry->SerialNumber.pbData == *serialNum,
4642 "Expected serial number %d, got %d\n", *serialNum,
4643 *entry->SerialNumber.pbData);
4644 ok(info->Issuer.cbData == sizeof(encodedCommonName),
4645 "Wrong issuer size %d\n", info->Issuer.cbData);
4646 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
4647 "Unexpected issuer\n");
4648 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4649 info->cExtension);
4650 LocalFree(buf);
4651 }
4652 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
4653 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
4654 NULL, &buf, &size);
4655 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4656 if (buf)
4657 {
4658 CRL_INFO *info = (CRL_INFO *)buf;
4659
4660 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n",
4661 info->cExtension);
4662 LocalFree(buf);
4663 }
4664 }
4665
4666 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
4667 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
4668 static const BYTE encodedUsage[] = {
4669 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
4670 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
4671 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
4672
4673 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
4674 {
4675 BOOL ret;
4676 BYTE *buf = NULL;
4677 DWORD size = 0;
4678 CERT_ENHKEY_USAGE usage;
4679
4680 /* Test with empty usage */
4681 usage.cUsageIdentifier = 0;
4682 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4683 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4684 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4685 if (buf)
4686 {
4687 ok(size == sizeof(emptySequence), "Wrong size %d\n", size);
4688 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
4689 LocalFree(buf);
4690 }
4691 /* Test with a few usages */
4692 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
4693 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
4694 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
4695 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4696 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4697 if (buf)
4698 {
4699 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size);
4700 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
4701 LocalFree(buf);
4702 }
4703 }
4704
4705 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
4706 {
4707 BOOL ret;
4708 LPBYTE buf = NULL;
4709 DWORD size = 0;
4710
4711 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4712 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4713 &buf, &size);
4714 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4715 if (buf)
4716 {
4717 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4718
4719 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4720 "Wrong size %d\n", size);
4721 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n",
4722 usage->cUsageIdentifier);
4723 LocalFree(buf);
4724 }
4725 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
4726 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
4727 &buf, &size);
4728 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4729 if (buf)
4730 {
4731 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
4732 DWORD i;
4733
4734 ok(size >= sizeof(CERT_ENHKEY_USAGE),
4735 "Wrong size %d\n", size);
4736 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
4737 "Wrong CRL entries count %d\n", usage->cUsageIdentifier);
4738 for (i = 0; i < usage->cUsageIdentifier; i++)
4739 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
4740 "Expected OID %s, got %s\n", keyUsages[i],
4741 usage->rgpszUsageIdentifier[i]);
4742 LocalFree(buf);
4743 }
4744 }
4745
4746 static BYTE keyId[] = { 1,2,3,4 };
4747 static const BYTE authorityKeyIdWithId[] = {
4748 0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 };
4749 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15,
4750 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,
4751 0x20,0x4c,0x61,0x6e,0x67,0x00 };
4752 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 };
4753
4754 static void test_encodeAuthorityKeyId(DWORD dwEncoding)
4755 {
4756 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } };
4757 BOOL ret;
4758 BYTE *buf = NULL;
4759 DWORD size = 0;
4760
4761 /* Test with empty id */
4762 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4763 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4764 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4765 if (buf)
4766 {
4767 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4768 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4769 LocalFree(buf);
4770 }
4771 /* With just a key id */
4772 info.KeyId.cbData = sizeof(keyId);
4773 info.KeyId.pbData = keyId;
4774 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4775 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4776 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4777 if (buf)
4778 {
4779 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size);
4780 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4781 LocalFree(buf);
4782 }
4783 /* With just an issuer */
4784 info.KeyId.cbData = 0;
4785 info.CertIssuer.cbData = sizeof(encodedCommonName);
4786 info.CertIssuer.pbData = (BYTE *)encodedCommonName;
4787 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4788 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4789 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4790 if (buf)
4791 {
4792 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n",
4793 size);
4794 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n");
4795 LocalFree(buf);
4796 }
4797 /* With just a serial number */
4798 info.CertIssuer.cbData = 0;
4799 info.CertSerialNumber.cbData = sizeof(serialNum);
4800 info.CertSerialNumber.pbData = (BYTE *)serialNum;
4801 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info,
4802 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4803 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4804 if (buf)
4805 {
4806 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4807 size);
4808 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4809 LocalFree(buf);
4810 }
4811 }
4812
4813 static void test_decodeAuthorityKeyId(DWORD dwEncoding)
4814 {
4815 BOOL ret;
4816 LPBYTE buf = NULL;
4817 DWORD size = 0;
4818
4819 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4820 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4821 &buf, &size);
4822 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4823 if (buf)
4824 {
4825 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4826
4827 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4828 size);
4829 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4830 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4831 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4832 LocalFree(buf);
4833 }
4834 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4835 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4836 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4837 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4838 if (buf)
4839 {
4840 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4841
4842 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4843 size);
4844 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4845 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4846 "Unexpected key id\n");
4847 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4848 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n");
4849 LocalFree(buf);
4850 }
4851 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID,
4852 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer),
4853 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4854 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4855 if (buf)
4856 {
4857 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf;
4858
4859 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n",
4860 size);
4861 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4862 ok(info->CertIssuer.cbData == sizeof(encodedCommonName),
4863 "Unexpected issuer len\n");
4864 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName,
4865 sizeof(encodedCommonName)), "Unexpected issuer\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 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
4871 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4872 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4873 if (buf)
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 == 0, "Expected no key id\n");
4880 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n");
4881 ok(info->CertSerialNumber.cbData == sizeof(serialNum),
4882 "Unexpected serial number len\n");
4883 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)),
4884 "Unexpected serial number\n");
4885 LocalFree(buf);
4886 }
4887 }
4888
4889 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86,
4890 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,
4891 0x6f,0x72,0x67 };
4892
4893 static void test_encodeAuthorityKeyId2(DWORD dwEncoding)
4894 {
4895 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } };
4896 CERT_ALT_NAME_ENTRY entry = { 0 };
4897 BOOL ret;
4898 BYTE *buf = NULL;
4899 DWORD size = 0;
4900
4901 /* Test with empty id */
4902 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4903 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4904 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4905 if (buf)
4906 {
4907 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size);
4908 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
4909 LocalFree(buf);
4910 }
4911 /* With just a key id */
4912 info.KeyId.cbData = sizeof(keyId);
4913 info.KeyId.pbData = keyId;
4914 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4915 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4916 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4917 if (buf)
4918 {
4919 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n",
4920 size);
4921 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n");
4922 LocalFree(buf);
4923 }
4924 /* With a bogus issuer name */
4925 info.KeyId.cbData = 0;
4926 info.AuthorityCertIssuer.cAltEntry = 1;
4927 info.AuthorityCertIssuer.rgAltEntry = &entry;
4928 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4929 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4930 ok(!ret && GetLastError() == E_INVALIDARG,
4931 "Expected E_INVALIDARG, got %08x\n", GetLastError());
4932 /* With an issuer name */
4933 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
4934 U(entry).pwszURL = (LPWSTR)url;
4935 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4936 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4937 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4938 if (buf)
4939 {
4940 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n",
4941 size);
4942 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size),
4943 "Unexpected value\n");
4944 LocalFree(buf);
4945 }
4946 /* With just a serial number */
4947 info.AuthorityCertIssuer.cAltEntry = 0;
4948 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum);
4949 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum;
4950 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info,
4951 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
4952 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
4953 if (buf)
4954 {
4955 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n",
4956 size);
4957 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n");
4958 LocalFree(buf);
4959 }
4960 }
4961
4962 static void test_decodeAuthorityKeyId2(DWORD dwEncoding)
4963 {
4964 BOOL ret;
4965 LPBYTE buf = NULL;
4966 DWORD size = 0;
4967
4968 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4969 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
4970 &buf, &size);
4971 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4972 if (buf)
4973 {
4974 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4975
4976 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4977 size);
4978 ok(info->KeyId.cbData == 0, "Expected no key id\n");
4979 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4980 "Expected no issuer name entries\n");
4981 ok(info->AuthorityCertSerialNumber.cbData == 0,
4982 "Expected no serial number\n");
4983 LocalFree(buf);
4984 }
4985 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
4986 authorityKeyIdWithId, sizeof(authorityKeyIdWithId),
4987 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
4988 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
4989 if (buf)
4990 {
4991 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
4992
4993 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
4994 size);
4995 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n");
4996 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)),
4997 "Unexpected key id\n");
4998 ok(info->AuthorityCertIssuer.cAltEntry == 0,
4999 "Expected no issuer name entries\n");
5000 ok(info->AuthorityCertSerialNumber.cbData == 0,
5001 "Expected no serial number\n");
5002 LocalFree(buf);
5003 }
5004 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5005 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl),
5006 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5007 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5008 if (buf)
5009 {
5010 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5011
5012 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5013 size);
5014 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5015 ok(info->AuthorityCertIssuer.cAltEntry == 1,
5016 "Expected 1 issuer entry, got %d\n",
5017 info->AuthorityCertIssuer.cAltEntry);
5018 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice ==
5019 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n",
5020 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice);
5021 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL,
5022 url), "Unexpected URL\n");
5023 ok(info->AuthorityCertSerialNumber.cbData == 0,
5024 "Expected no serial number\n");
5025 LocalFree(buf);
5026 }
5027 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2,
5028 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial),
5029 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5030 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5031 if (buf)
5032 {
5033 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf;
5034
5035 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n",
5036 size);
5037 ok(info->KeyId.cbData == 0, "Expected no key id\n");
5038 ok(info->AuthorityCertIssuer.cAltEntry == 0,
5039 "Expected no issuer name entries\n");
5040 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum),
5041 "Unexpected serial number len\n");
5042 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum,
5043 sizeof(serialNum)), "Unexpected serial number\n");
5044 LocalFree(buf);
5045 }
5046 }
5047
5048 static const BYTE authorityInfoAccessWithUrl[] = {
5049 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5050 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
5051 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = {
5052 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a,
5053 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06,
5054 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5055
5056 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding)
5057 {
5058 static char oid1[] = "1.2.3";
5059 static char oid2[] = "1.5.6";
5060 BOOL ret;
5061 BYTE *buf = NULL;
5062 DWORD size = 0;
5063 CERT_ACCESS_DESCRIPTION accessDescription[2];
5064 CERT_AUTHORITY_INFO_ACCESS aia;
5065
5066 memset(accessDescription, 0, sizeof(accessDescription));
5067 aia.cAccDescr = 0;
5068 aia.rgAccDescr = NULL;
5069 /* Having no access descriptions is allowed */
5070 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5071 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5072 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5073 if (buf)
5074 {
5075 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
5076 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
5077 LocalFree(buf);
5078 buf = NULL;
5079 }
5080 /* It can't have an empty access method */
5081 aia.cAccDescr = 1;
5082 aia.rgAccDescr = accessDescription;
5083 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5084 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5085 ok(!ret && (GetLastError() == E_INVALIDARG ||
5086 GetLastError() == OSS_LIMITED /* Win9x */),
5087 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
5088 /* It can't have an empty location */
5089 accessDescription[0].pszAccessMethod = oid1;
5090 SetLastError(0xdeadbeef);
5091 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5092 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5093 ok(!ret && GetLastError() == E_INVALIDARG,
5094 "expected E_INVALIDARG, got %08x\n", GetLastError());
5095 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5096 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5097 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5098 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5099 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5100 if (buf)
5101 {
5102 ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n",
5103 size);
5104 ok(!memcmp(buf, authorityInfoAccessWithUrl, size),
5105 "unexpected value\n");
5106 LocalFree(buf);
5107 buf = NULL;
5108 }
5109 accessDescription[1].pszAccessMethod = oid2;
5110 accessDescription[1].AccessLocation.dwAltNameChoice =
5111 CERT_ALT_NAME_IP_ADDRESS;
5112 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5113 sizeof(encodedIPAddr);
5114 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5115 (LPBYTE)encodedIPAddr;
5116 aia.cAccDescr = 2;
5117 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia,
5118 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5119 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5120 if (buf)
5121 {
5122 ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr),
5123 "unexpected size %d\n", size);
5124 ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size),
5125 "unexpected value\n");
5126 LocalFree(buf);
5127 buf = NULL;
5128 }
5129 }
5130
5131 static void compareAuthorityInfoAccess(LPCSTR header,
5132 const CERT_AUTHORITY_INFO_ACCESS *expected,
5133 const CERT_AUTHORITY_INFO_ACCESS *got)
5134 {
5135 DWORD i;
5136
5137 ok(expected->cAccDescr == got->cAccDescr,
5138 "%s: expected %d access descriptions, got %d\n", header,
5139 expected->cAccDescr, got->cAccDescr);
5140 for (i = 0; i < expected->cAccDescr; i++)
5141 {
5142 ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod,
5143 got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n",
5144 header, i, expected->rgAccDescr[i].pszAccessMethod,
5145 got->rgAccDescr[i].pszAccessMethod);
5146 compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation,
5147 &got->rgAccDescr[i].AccessLocation);
5148 }
5149 }
5150
5151 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding)
5152 {
5153 static char oid1[] = "1.2.3";
5154 static char oid2[] = "1.5.6";
5155 BOOL ret;
5156 LPBYTE buf = NULL;
5157 DWORD size = 0;
5158
5159 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5160 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
5161 &buf, &size);
5162 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5163 if (buf)
5164 {
5165 CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL };
5166
5167 compareAuthorityInfoAccess("empty AIA", &aia,
5168 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5169 LocalFree(buf);
5170 buf = NULL;
5171 }
5172 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5173 authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl),
5174 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5175 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5176 if (buf)
5177 {
5178 CERT_ACCESS_DESCRIPTION accessDescription;
5179 CERT_AUTHORITY_INFO_ACCESS aia;
5180
5181 accessDescription.pszAccessMethod = oid1;
5182 accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5183 U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url;
5184 aia.cAccDescr = 1;
5185 aia.rgAccDescr = &accessDescription;
5186 compareAuthorityInfoAccess("AIA with URL", &aia,
5187 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5188 LocalFree(buf);
5189 buf = NULL;
5190 }
5191 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS,
5192 authorityInfoAccessWithUrlAndIPAddr,
5193 sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG,
5194 NULL, &buf, &size);
5195 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5196 if (buf)
5197 {
5198 CERT_ACCESS_DESCRIPTION accessDescription[2];
5199 CERT_AUTHORITY_INFO_ACCESS aia;
5200
5201 accessDescription[0].pszAccessMethod = oid1;
5202 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL;
5203 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url;
5204 accessDescription[1].pszAccessMethod = oid2;
5205 accessDescription[1].AccessLocation.dwAltNameChoice =
5206 CERT_ALT_NAME_IP_ADDRESS;
5207 U(accessDescription[1].AccessLocation).IPAddress.cbData =
5208 sizeof(encodedIPAddr);
5209 U(accessDescription[1].AccessLocation).IPAddress.pbData =
5210 (LPBYTE)encodedIPAddr;
5211 aia.cAccDescr = 2;
5212 aia.rgAccDescr = accessDescription;
5213 compareAuthorityInfoAccess("AIA with URL and IP addr", &aia,
5214 (CERT_AUTHORITY_INFO_ACCESS *)buf);
5215 LocalFree(buf);
5216 buf = NULL;
5217 }
5218 }
5219
5220 static const BYTE emptyCTL[] = {
5221 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5222 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5223 static const BYTE emptyCTLWithVersion1[] = {
5224 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5225 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5226 static const BYTE ctlWithUsageIdentifier[] = {
5227 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,
5228 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5229 static const BYTE ctlWithListIdentifier[] = {
5230 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5231 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5232 static const BYTE ctlWithSequenceNumber[] = {
5233 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,
5234 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5235 static const BYTE ctlWithThisUpdate[] = {
5236 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5237 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5238 static const BYTE ctlWithThisAndNextUpdate[] = {
5239 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5240 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31,
5241 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 };
5242 static const BYTE ctlWithAlgId[] = {
5243 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5244 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
5245 static const BYTE ctlWithBogusEntry[] = {
5246 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5247 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04,
5248 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 };
5249 static const BYTE ctlWithOneEntry[] = {
5250 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5251 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04,
5252 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 };
5253 static const BYTE ctlWithTwoEntries[] = {
5254 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5255 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04,
5256 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30,
5257 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30,
5258 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 };
5259
5260 static void test_encodeCTL(DWORD dwEncoding)
5261 {
5262 static char oid1[] = "1.2.3";
5263 static char oid2[] = "1.5.6";
5264 char *pOid1 = oid1;
5265 BOOL ret;
5266 BYTE *buf = NULL;
5267 DWORD size = 0;
5268 CTL_INFO info;
5269 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5270 CTL_ENTRY ctlEntry[2];
5271 CRYPT_ATTRIBUTE attr1, attr2;
5272 CRYPT_ATTR_BLOB value1, value2;
5273
5274 memset(&info, 0, sizeof(info));
5275 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5276 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5277 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5278 if (buf)
5279 {
5280 ok(size == sizeof(emptyCTL), "unexpected size %d\n", size);
5281 ok(!memcmp(buf, emptyCTL, size), "unexpected value\n");
5282 LocalFree(buf);
5283 buf = NULL;
5284 }
5285 info.dwVersion = 1;
5286 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5287 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5288 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5289 if (buf)
5290 {
5291 ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size);
5292 ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n");
5293 LocalFree(buf);
5294 buf = NULL;
5295 }
5296 info.dwVersion = 0;
5297 info.SubjectUsage.cUsageIdentifier = 1;
5298 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5299 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5300 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5301 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5302 if (buf)
5303 {
5304 ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n",
5305 size);
5306 ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n");
5307 LocalFree(buf);
5308 buf = NULL;
5309 }
5310 info.SubjectUsage.cUsageIdentifier = 0;
5311 info.ListIdentifier.cbData = sizeof(serialNum);
5312 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5313 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5314 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5315 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5316 if (buf)
5317 {
5318 ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size);
5319 ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n");
5320 LocalFree(buf);
5321 buf = NULL;
5322 }
5323 info.ListIdentifier.cbData = 0;
5324 info.SequenceNumber.cbData = sizeof(serialNum);
5325 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5326 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5327 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5328 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5329 if (buf)
5330 {
5331 ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n",
5332 size);
5333 ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n");
5334 LocalFree(buf);
5335 buf = NULL;
5336 }
5337 info.SequenceNumber.cbData = 0;
5338 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5339 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5340 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5341 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5342 if (buf)
5343 {
5344 ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size);
5345 ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n");
5346 LocalFree(buf);
5347 buf = NULL;
5348 }
5349 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5350 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5351 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5352 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5353 if (buf)
5354 {
5355 ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n",
5356 size);
5357 ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n");
5358 LocalFree(buf);
5359 buf = NULL;
5360 }
5361 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5362 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5363 info.SubjectAlgorithm.pszObjId = oid2;
5364 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5365 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5366 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5367 if (buf)
5368 {
5369 ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size);
5370 ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n");
5371 LocalFree(buf);
5372 buf = NULL;
5373 }
5374 /* The value is supposed to be asn.1 encoded, so this'll fail to decode
5375 * (see tests below) but it'll encode fine.
5376 */
5377 info.SubjectAlgorithm.pszObjId = NULL;
5378 value1.cbData = sizeof(serialNum);
5379 value1.pbData = (LPBYTE)serialNum;
5380 attr1.pszObjId = oid1;
5381 attr1.cValue = 1;
5382 attr1.rgValue = &value1;
5383 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5384 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5385 ctlEntry[0].cAttribute = 1;
5386 ctlEntry[0].rgAttribute = &attr1;
5387 info.cCTLEntry = 1;
5388 info.rgCTLEntry = ctlEntry;
5389 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5390 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5391 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5392 if (buf)
5393 {
5394 ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size);
5395 ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n");
5396 LocalFree(buf);
5397 buf = NULL;
5398 }
5399 value1.cbData = sizeof(emptySequence);
5400 value1.pbData = (LPBYTE)emptySequence;
5401 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5402 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5403 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5404 if (buf)
5405 {
5406 ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size);
5407 ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n");
5408 LocalFree(buf);
5409 buf = NULL;
5410 }
5411 value2.cbData = sizeof(encodedIPAddr);
5412 value2.pbData = (LPBYTE)encodedIPAddr;
5413 attr2.pszObjId = oid2;
5414 attr2.cValue = 1;
5415 attr2.rgValue = &value2;
5416 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5417 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5418 ctlEntry[1].cAttribute = 1;
5419 ctlEntry[1].rgAttribute = &attr2;
5420 info.cCTLEntry = 2;
5421 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info,
5422 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5423 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
5424 if (buf)
5425 {
5426 ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size);
5427 ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n");
5428 LocalFree(buf);
5429 buf = NULL;
5430 }
5431 }
5432
5433 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected,
5434 const CTL_INFO *got)
5435 {
5436 DWORD i, j, k;
5437
5438 ok(expected->dwVersion == got->dwVersion,
5439 "%s: expected version %d, got %d\n", header, expected->dwVersion,
5440 got->dwVersion);
5441 ok(expected->SubjectUsage.cUsageIdentifier ==
5442 got->SubjectUsage.cUsageIdentifier,
5443 "%s: expected %d usage identifiers, got %d\n", header,
5444 expected->SubjectUsage.cUsageIdentifier,
5445 got->SubjectUsage.cUsageIdentifier);
5446 for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++)
5447 ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i],
5448 got->SubjectUsage.rgpszUsageIdentifier[i]),
5449 "%s[%d]: expected %s, got %s\n", header, i,
5450 expected->SubjectUsage.rgpszUsageIdentifier[i],
5451 got->SubjectUsage.rgpszUsageIdentifier[i]);
5452 ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData,
5453 "%s: expected list identifier of %d bytes, got %d\n", header,
5454 expected->ListIdentifier.cbData, got->ListIdentifier.cbData);
5455 if (expected->ListIdentifier.cbData)
5456 ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData,
5457 expected->ListIdentifier.cbData),
5458 "%s: unexpected list identifier value\n", header);
5459 ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData,
5460 "%s: expected sequence number of %d bytes, got %d\n", header,
5461 expected->SequenceNumber.cbData, got->SequenceNumber.cbData);
5462 if (expected->SequenceNumber.cbData)
5463 ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData,
5464 expected->SequenceNumber.cbData),
5465 "%s: unexpected sequence number value\n", header);
5466 ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)),
5467 "%s: expected this update = (%d, %d), got (%d, %d)\n", header,
5468 expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime,
5469 got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime);
5470 ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)),
5471 "%s: expected next update = (%d, %d), got (%d, %d)\n", header,
5472 expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime,
5473 got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime);
5474 if (expected->SubjectAlgorithm.pszObjId &&
5475 *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId)
5476 ok(0, "%s: expected subject algorithm %s, got NULL\n", header,
5477 expected->SubjectAlgorithm.pszObjId);
5478 if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId)
5479 ok(!strcmp(expected->SubjectAlgorithm.pszObjId,
5480 got->SubjectAlgorithm.pszObjId),
5481 "%s: expected subject algorithm %s, got %s\n", header,
5482 expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId);
5483 ok(expected->SubjectAlgorithm.Parameters.cbData ==
5484 got->SubjectAlgorithm.Parameters.cbData,
5485 "%s: expected subject algorithm parameters of %d bytes, got %d\n", header,
5486 expected->SubjectAlgorithm.Parameters.cbData,
5487 got->SubjectAlgorithm.Parameters.cbData);
5488 if (expected->SubjectAlgorithm.Parameters.cbData)
5489 ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData,
5490 got->SubjectAlgorithm.Parameters.pbData,
5491 expected->SubjectAlgorithm.Parameters.cbData),
5492 "%s: unexpected subject algorithm parameter value\n", header);
5493 ok(expected->cCTLEntry == got->cCTLEntry,
5494 "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry,
5495 got->cCTLEntry);
5496 for (i = 0; i < expected->cCTLEntry; i++)
5497 {
5498 ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData ==
5499 got->rgCTLEntry[i].SubjectIdentifier.cbData,
5500 "%s[%d]: expected subject identifier of %d bytes, got %d\n",
5501 header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData,
5502 got->rgCTLEntry[i].SubjectIdentifier.cbData);
5503 if (expected->rgCTLEntry[i].SubjectIdentifier.cbData)
5504 ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData,
5505 got->rgCTLEntry[i].SubjectIdentifier.pbData,
5506 expected->rgCTLEntry[i].SubjectIdentifier.cbData),
5507 "%s[%d]: unexpected subject identifier value\n",
5508 header, i);
5509 for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++)
5510 {
5511 ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5512 got->rgCTLEntry[i].rgAttribute[j].pszObjId),
5513 "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j,
5514 expected->rgCTLEntry[i].rgAttribute[j].pszObjId,
5515 got->rgCTLEntry[i].rgAttribute[j].pszObjId);
5516 for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++)
5517 {
5518 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData ==
5519 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5520 "%s[%d][%d][%d]: expected value of %d bytes, got %d\n",
5521 header, i, j, k,
5522 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData,
5523 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData);
5524 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData)
5525 ok(!memcmp(
5526 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5527 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData,
5528 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData),
5529 "%s[%d][%d][%d]: unexpected value\n",
5530 header, i, j, k);
5531 }
5532 }
5533 }
5534 ok(expected->cExtension == got->cExtension,
5535 "%s: expected %d extensions, got %d\n", header, expected->cExtension,
5536 got->cExtension);
5537 for (i = 0; i < expected->cExtension; i++)
5538 {
5539 ok(!strcmp(expected->rgExtension[i].pszObjId,
5540 got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n",
5541 header, i, expected->rgExtension[i].pszObjId,
5542 got->rgExtension[i].pszObjId);
5543 ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical,
5544 "%s[%d]: expected fCritical = %d, got %d\n", header, i,
5545 expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical);
5546 ok(expected->rgExtension[i].Value.cbData ==
5547 got->rgExtension[i].Value.cbData,
5548 "%s[%d]: expected extension value to have %d bytes, got %d\n",
5549 header, i, expected->rgExtension[i].Value.cbData,
5550 got->rgExtension[i].Value.cbData);
5551 if (expected->rgExtension[i].Value.cbData)
5552 ok(!memcmp(expected->rgExtension[i].Value.pbData,
5553 got->rgExtension[i].Value.pbData,
5554 expected->rgExtension[i].Value.cbData),
5555 "%s[%d]: unexpected extension value\n", header, i);
5556 }
5557 }
5558
5559 static const BYTE signedCTL[] = {
5560 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,
5561 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,
5562 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86,
5563 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00,
5564 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5565 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,
5566 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,
5567 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,
5568 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
5569 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d,
5570 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39,
5571 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26,
5572 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9,
5573 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 };
5574 static const BYTE signedCTLWithCTLInnerContent[] = {
5575 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,
5576 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,
5577 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09,
5578 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00,
5579 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,
5580 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,
5581 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,
5582 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,
5583 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,
5584 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86,
5585 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04,
5586 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
5587 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9,
5588 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
5589 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf,
5590 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1,
5591 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f,
5592 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23,
5593 0x57,0x6c,0x0b,0x47,0xb8 };
5594
5595 static void test_decodeCTL(DWORD dwEncoding)
5596 {
5597 static char oid1[] = "1.2.3";
5598 static char oid2[] = "1.5.6";
5599 static BYTE nullData[] = { 5,0 };
5600 char *pOid1 = oid1;
5601 BOOL ret;
5602 BYTE *buf = NULL;
5603 DWORD size = 0;
5604 CTL_INFO info;
5605 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 };
5606 CTL_ENTRY ctlEntry[2];
5607 CRYPT_ATTRIBUTE attr1, attr2;
5608 CRYPT_ATTR_BLOB value1, value2;
5609
5610 memset(&info, 0, sizeof(info));
5611 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL),
5612 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5613 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5614 if (buf)
5615 {
5616 compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf);
5617 LocalFree(buf);
5618 buf = NULL;
5619 }
5620 info.dwVersion = 1;
5621 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1,
5622 sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf,
5623 &size);
5624 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5625 if (buf)
5626 {
5627 compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf);
5628 LocalFree(buf);
5629 buf = NULL;
5630 }
5631 info.dwVersion = 0;
5632 info.SubjectUsage.cUsageIdentifier = 1;
5633 info.SubjectUsage.rgpszUsageIdentifier = &pOid1;
5634 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier,
5635 sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL,
5636 &buf, &size);
5637 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5638 if (buf)
5639 {
5640 compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf);
5641 LocalFree(buf);
5642 buf = NULL;
5643 }
5644 info.SubjectUsage.cUsageIdentifier = 0;
5645 info.ListIdentifier.cbData = sizeof(serialNum);
5646 info.ListIdentifier.pbData = (LPBYTE)serialNum;
5647 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier,
5648 sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5649 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5650 if (buf)
5651 {
5652 compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf);
5653 LocalFree(buf);
5654 buf = NULL;
5655 }
5656 info.ListIdentifier.cbData = 0;
5657 info.SequenceNumber.cbData = sizeof(serialNum);
5658 info.SequenceNumber.pbData = (LPBYTE)serialNum;
5659 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber,
5660 sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5661 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5662 if (buf)
5663 {
5664 compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf);
5665 LocalFree(buf);
5666 buf = NULL;
5667 }
5668 info.SequenceNumber.cbData = 0;
5669 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate);
5670 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate,
5671 sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5672 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5673 if (buf)
5674 {
5675 compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf);
5676 LocalFree(buf);
5677 buf = NULL;
5678 }
5679 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate);
5680 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate,
5681 sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL,
5682 &buf, &size);
5683 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5684 if (buf)
5685 {
5686 compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf);
5687 LocalFree(buf);
5688 buf = NULL;
5689 }
5690 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5691 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5692 info.SubjectAlgorithm.pszObjId = oid2;
5693 info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData);
5694 info.SubjectAlgorithm.Parameters.pbData = nullData;
5695 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId,
5696 sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5697 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5698 if (buf)
5699 {
5700 compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf);
5701 LocalFree(buf);
5702 buf = NULL;
5703 }
5704 SetLastError(0xdeadbeef);
5705 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry,
5706 sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5707 ok(!ret &&
5708 (GetLastError() == CRYPT_E_ASN1_EOD ||
5709 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
5710 GetLastError() == OSS_MORE_INPUT), /* Win9x */
5711 "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n",
5712 GetLastError());
5713 info.SubjectAlgorithm.Parameters.cbData = 0;
5714 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0;
5715 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0;
5716 info.SubjectAlgorithm.pszObjId = oid2;
5717 info.SubjectAlgorithm.pszObjId = NULL;
5718 value1.cbData = sizeof(emptySequence);
5719 value1.pbData = (LPBYTE)emptySequence;
5720 attr1.pszObjId = oid1;
5721 attr1.cValue = 1;
5722 attr1.rgValue = &value1;
5723 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum);
5724 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5725 ctlEntry[0].cAttribute = 1;
5726 ctlEntry[0].rgAttribute = &attr1;
5727 info.cCTLEntry = 1;
5728 info.rgCTLEntry = ctlEntry;
5729 SetLastError(0xdeadbeef);
5730 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry,
5731 sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5732 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5733 if (buf)
5734 {
5735 compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf);
5736 LocalFree(buf);
5737 buf = NULL;
5738 }
5739 value2.cbData = sizeof(encodedIPAddr);
5740 value2.pbData = (LPBYTE)encodedIPAddr;
5741 attr2.pszObjId = oid2;
5742 attr2.cValue = 1;
5743 attr2.rgValue = &value2;
5744 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum);
5745 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum;
5746 ctlEntry[1].cAttribute = 1;
5747 ctlEntry[1].rgAttribute = &attr2;
5748 info.cCTLEntry = 2;
5749 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries,
5750 sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5751 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
5752 if (buf)
5753 {
5754 compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf);
5755 LocalFree(buf);
5756 buf = NULL;
5757 }
5758 /* A signed CTL isn't decodable, even if the inner content is a CTL */
5759 SetLastError(0xdeadbeef);
5760 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL,
5761 sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5762 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5763 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5764 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5765 GetLastError());
5766 SetLastError(0xdeadbeef);
5767 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL,
5768 signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent),
5769 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5770 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG ||
5771 GetLastError() == OSS_DATA_ERROR /* Win9x */),
5772 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n",
5773 GetLastError());
5774 }
5775
5776 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 };
5777 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a,
5778 0x03,0,0,0,0,0,0 };
5779 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,
5780 0xa0,0x01,0x01 };
5781 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0,
5782 0x03,0x02,0x01,0x01 };
5783 static BYTE bogusDER[] = { 1 };
5784
5785 static void test_encodePKCSContentInfo(DWORD dwEncoding)
5786 {
5787 BOOL ret;
5788 BYTE *buf = NULL;
5789 DWORD size = 0;
5790 CRYPT_CONTENT_INFO info = { 0 };
5791 char oid1[] = "1.2.3";
5792
5793 if (0)
5794 {
5795 /* Crashes on win9x */
5796 SetLastError(0xdeadbeef);
5797 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL,
5798 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5799 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5800 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5801 }
5802 SetLastError(0xdeadbeef);
5803 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5804 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5805 ok(!ret && (GetLastError() == E_INVALIDARG ||
5806 GetLastError() == OSS_LIMITED /* Win9x */),
5807 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5808 info.pszObjId = oid1;
5809 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5810 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5811 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5812 if (buf)
5813 {
5814 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size);
5815 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n");
5816 LocalFree(buf);
5817 }
5818 info.Content.pbData = bogusDER;
5819 info.Content.cbData = sizeof(bogusDER);
5820 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5821 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5822 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError());
5823 if (buf)
5824 {
5825 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size);
5826 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n");
5827 LocalFree(buf);
5828 }
5829 info.Content.pbData = (BYTE *)ints[0].encoded;
5830 info.Content.cbData = ints[0].encoded[1] + 2;
5831 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info,
5832 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5833 if (buf)
5834 {
5835 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size);
5836 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n");
5837 LocalFree(buf);
5838 }
5839 }
5840
5841 static const BYTE indefiniteSignedPKCSContent[] = {
5842 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80,
5843 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,
5844 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,
5845 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04,
5846 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30,
5847 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11,
5848 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
5849 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,
5850 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,
5851 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5852 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5853 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,
5854 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7,
5855 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21,
5856 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3,
5857 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21,
5858 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79,
5859 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,
5860 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31,
5861 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06,
5862 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,
5863 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,
5864 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad,
5865 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8,
5866 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3,
5867 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d,
5868 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61,
5869 0x00,0x00,0x00,0x00,0x00,0x00 };
5870
5871 static void test_decodePKCSContentInfo(DWORD dwEncoding)
5872 {
5873 BOOL ret;
5874 LPBYTE buf = NULL;
5875 DWORD size = 0;
5876 CRYPT_CONTENT_INFO *info;
5877
5878 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5879 emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo),
5880 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5881 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5882 if (buf)
5883 {
5884 info = (CRYPT_CONTENT_INFO *)buf;
5885
5886 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5887 info->pszObjId);
5888 ok(info->Content.cbData == 0, "Expected no data, got %d\n",
5889 info->Content.cbData);
5890 LocalFree(buf);
5891 }
5892 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5893 emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes),
5894 0, NULL, NULL, &size);
5895 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5896 SetLastError(0xdeadbeef);
5897 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5898 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo),
5899 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5900 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
5901 * I doubt an app depends on that.
5902 */
5903 ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
5904 GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret),
5905 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n",
5906 GetLastError());
5907 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5908 intPKCSContentInfo, sizeof(intPKCSContentInfo),
5909 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5910 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5911 if (buf)
5912 {
5913 info = (CRYPT_CONTENT_INFO *)buf;
5914
5915 ok(!strcmp(info->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
5916 info->pszObjId);
5917 ok(info->Content.cbData == ints[0].encoded[1] + 2,
5918 "Unexpected size %d\n", info->Content.cbData);
5919 ok(!memcmp(info->Content.pbData, ints[0].encoded,
5920 info->Content.cbData), "Unexpected value\n");
5921 LocalFree(buf);
5922 }
5923 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO,
5924 indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent),
5925 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
5926 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
5927 if (buf)
5928 {
5929 info = (CRYPT_CONTENT_INFO *)buf;
5930
5931 ok(!strcmp(info->pszObjId, szOID_RSA_signedData),
5932 "Expected %s, got %s\n", szOID_RSA_signedData, info->pszObjId);
5933 ok(info->Content.cbData == 392, "Expected 392, got %d\n",
5934 info->Content.cbData);
5935 LocalFree(buf);
5936 }
5937 }
5938
5939 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31,
5940 0x00 };
5941 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,
5942 0x01 };
5943 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03,
5944 0x02,0x01,0x01 };
5945
5946 static void test_encodePKCSAttribute(DWORD dwEncoding)
5947 {
5948 CRYPT_ATTRIBUTE attr = { 0 };
5949 BOOL ret;
5950 LPBYTE buf = NULL;
5951 DWORD size = 0;
5952 CRYPT_ATTR_BLOB blob;
5953 char oid[] = "1.2.3";
5954
5955 if (0)
5956 {
5957 /* Crashes on win9x */
5958 SetLastError(0xdeadbeef);
5959 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL,
5960 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5961 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
5962 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError());
5963 }
5964 SetLastError(0xdeadbeef);
5965 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5966 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5967 ok(!ret && (GetLastError() == E_INVALIDARG ||
5968 GetLastError() == OSS_LIMITED /* Win9x */),
5969 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError());
5970 attr.pszObjId = oid;
5971 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5972 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5973 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5974 if (buf)
5975 {
5976 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size);
5977 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n");
5978 LocalFree(buf);
5979 }
5980 blob.cbData = sizeof(bogusDER);
5981 blob.pbData = bogusDER;
5982 attr.cValue = 1;
5983 attr.rgValue = &blob;
5984 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5985 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5986 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
5987 if (buf)
5988 {
5989 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size);
5990 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n");
5991 LocalFree(buf);
5992 }
5993 blob.pbData = (BYTE *)ints[0].encoded;
5994 blob.cbData = ints[0].encoded[1] + 2;
5995 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr,
5996 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
5997 if (buf)
5998 {
5999 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size);
6000 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n");
6001 LocalFree(buf);
6002 }
6003 }
6004
6005 static void test_decodePKCSAttribute(DWORD dwEncoding)
6006 {
6007 BOOL ret;
6008 LPBYTE buf = NULL;
6009 DWORD size = 0;
6010 CRYPT_ATTRIBUTE *attr;
6011
6012 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6013 emptyPKCSAttr, sizeof(emptyPKCSAttr),
6014 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6015 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6016 if (buf)
6017 {
6018 attr = (CRYPT_ATTRIBUTE *)buf;
6019
6020 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6021 attr->pszObjId);
6022 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue);
6023 LocalFree(buf);
6024 }
6025 SetLastError(0xdeadbeef);
6026 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6027 bogusPKCSAttr, sizeof(bogusPKCSAttr),
6028 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6029 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as
6030 * I doubt an app depends on that.
6031 */
6032 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD ||
6033 GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6034 GetLastError() == OSS_MORE_INPUT /* Win9x */),
6035 "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n",
6036 GetLastError());
6037 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE,
6038 intPKCSAttr, sizeof(intPKCSAttr),
6039 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6040 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6041 if (buf)
6042 {
6043 attr = (CRYPT_ATTRIBUTE *)buf;
6044
6045 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n",
6046 attr->pszObjId);
6047 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue);
6048 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2,
6049 "Unexpected size %d\n", attr->rgValue[0].cbData);
6050 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded,
6051 attr->rgValue[0].cbData), "Unexpected value\n");
6052 LocalFree(buf);
6053 }
6054 }
6055
6056 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 };
6057 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02,
6058 0x2a,0x03,0x31,0x00 };
6059 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02,
6060 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 };
6061
6062 static void test_encodePKCSAttributes(DWORD dwEncoding)
6063 {
6064 CRYPT_ATTRIBUTES attributes = { 0 };
6065 CRYPT_ATTRIBUTE attr[2] = { { 0 } };
6066 CRYPT_ATTR_BLOB blob;
6067 BOOL ret;
6068 LPBYTE buf = NULL;
6069 DWORD size = 0;
6070 char oid1[] = "1.2.3", oid2[] = "1.5.6";
6071
6072 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6073 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6074 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6075 if (buf)
6076 {
6077 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size);
6078 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n");
6079 LocalFree(buf);
6080 }
6081 attributes.cAttr = 1;
6082 attributes.rgAttr = attr;
6083 SetLastError(0xdeadbeef);
6084 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6085 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6086 ok(!ret && (GetLastError() == E_INVALIDARG ||
6087 GetLastError() == OSS_LIMITED /* Win9x */),
6088 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6089 attr[0].pszObjId = oid1;
6090 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6091 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6092 if (buf)
6093 {
6094 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size);
6095 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n");
6096 LocalFree(buf);
6097 }
6098 attr[1].pszObjId = oid2;
6099 attr[1].cValue = 1;
6100 attr[1].rgValue = &blob;
6101 blob.pbData = (BYTE *)ints[0].encoded;
6102 blob.cbData = ints[0].encoded[1] + 2;
6103 attributes.cAttr = 2;
6104 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes,
6105 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6106 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6107 if (buf)
6108 {
6109 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size);
6110 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n");
6111 LocalFree(buf);
6112 }
6113 }
6114
6115 static void test_decodePKCSAttributes(DWORD dwEncoding)
6116 {
6117 BOOL ret;
6118 LPBYTE buf = NULL;
6119 DWORD size = 0;
6120 CRYPT_ATTRIBUTES *attributes;
6121
6122 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6123 emptyPKCSAttributes, sizeof(emptyPKCSAttributes),
6124 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6125 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6126 if (buf)
6127 {
6128 attributes = (CRYPT_ATTRIBUTES *)buf;
6129 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n",
6130 attributes->cAttr);
6131 LocalFree(buf);
6132 }
6133 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6134 singlePKCSAttributes, sizeof(singlePKCSAttributes),
6135 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6136 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6137 if (buf)
6138 {
6139 attributes = (CRYPT_ATTRIBUTES *)buf;
6140 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n",
6141 attributes->cAttr);
6142 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6143 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6144 ok(attributes->rgAttr[0].cValue == 0,
6145 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6146 LocalFree(buf);
6147 }
6148 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES,
6149 doublePKCSAttributes, sizeof(doublePKCSAttributes),
6150 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6151 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6152 if (buf)
6153 {
6154 attributes = (CRYPT_ATTRIBUTES *)buf;
6155 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n",
6156 attributes->cAttr);
6157 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"),
6158 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId);
6159 ok(attributes->rgAttr[0].cValue == 0,
6160 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue);
6161 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"),
6162 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId);
6163 ok(attributes->rgAttr[1].cValue == 1,
6164 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue);
6165 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2,
6166 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData);
6167 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded,
6168 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n");
6169 LocalFree(buf);
6170 }
6171 }
6172
6173 static const BYTE singleCapability[] = {
6174 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 };
6175 static const BYTE twoCapabilities[] = {
6176 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 };
6177 static const BYTE singleCapabilitywithNULL[] = {
6178 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 };
6179
6180 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding)
6181 {
6182 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6183 BOOL ret;
6184 LPBYTE buf = NULL;
6185 DWORD size = 0;
6186 CRYPT_SMIME_CAPABILITY capability[2];
6187 CRYPT_SMIME_CAPABILITIES capabilities;
6188
6189 /* An empty capabilities is allowed */
6190 capabilities.cCapability = 0;
6191 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6192 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6193 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6194 if (buf)
6195 {
6196 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
6197 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
6198 LocalFree(buf);
6199 }
6200 /* A non-empty capabilities with an empty capability (lacking an OID) is
6201 * not allowed
6202 */
6203 capability[0].pszObjId = NULL;
6204 capability[0].Parameters.cbData = 0;
6205 capabilities.cCapability = 1;
6206 capabilities.rgCapability = capability;
6207 SetLastError(0xdeadbeef);
6208 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6209 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6210 ok(!ret && (GetLastError() == E_INVALIDARG ||
6211 GetLastError() == OSS_LIMITED /* Win9x */),
6212 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6213 capability[0].pszObjId = oid1;
6214 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6215 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6216 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6217 if (buf)
6218 {
6219 ok(size == sizeof(singleCapability), "unexpected size %d\n", size);
6220 ok(!memcmp(buf, singleCapability, size), "unexpected value\n");
6221 LocalFree(buf);
6222 }
6223 capability[1].pszObjId = oid2;
6224 capability[1].Parameters.cbData = 0;
6225 capabilities.cCapability = 2;
6226 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6227 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6228 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
6229 if (buf)
6230 {
6231 ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size);
6232 ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n");
6233 LocalFree(buf);
6234 }
6235 }
6236
6237 static void compareSMimeCapabilities(LPCSTR header,
6238 const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got)
6239 {
6240 DWORD i;
6241
6242 ok(got->cCapability == expected->cCapability,
6243 "%s: expected %d capabilities, got %d\n", header, expected->cCapability,
6244 got->cCapability);
6245 for (i = 0; i < expected->cCapability; i++)
6246 {
6247 ok(!strcmp(expected->rgCapability[i].pszObjId,
6248 got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n",
6249 header, i, expected->rgCapability[i].pszObjId,
6250 got->rgCapability[i].pszObjId);
6251 ok(expected->rgCapability[i].Parameters.cbData ==
6252 got->rgCapability[i].Parameters.cbData,
6253 "%s[%d]: expected %d bytes, got %d\n", header, i,
6254 expected->rgCapability[i].Parameters.cbData,
6255 got->rgCapability[i].Parameters.cbData);
6256 if (expected->rgCapability[i].Parameters.cbData)
6257 ok(!memcmp(expected->rgCapability[i].Parameters.pbData,
6258 got->rgCapability[i].Parameters.pbData,
6259 expected->rgCapability[i].Parameters.cbData),
6260 "%s[%d]: unexpected value\n", header, i);
6261 }
6262 }
6263
6264 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding)
6265 {
6266 static char oid1[] = "1.5.6", oid2[] = "1.2.3";
6267 BOOL ret;
6268 DWORD size = 0;
6269 CRYPT_SMIME_CAPABILITY capability[2];
6270 CRYPT_SMIME_CAPABILITIES capabilities, *ptr;
6271
6272 SetLastError(0xdeadbeef);
6273 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6274 emptySequence, sizeof(emptySequence),
6275 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6276 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6277 if (ret)
6278 {
6279 capabilities.cCapability = 0;
6280 compareSMimeCapabilities("empty capabilities", &capabilities, ptr);
6281 LocalFree(ptr);
6282 }
6283 SetLastError(0xdeadbeef);
6284 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6285 singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL,
6286 &ptr, &size);
6287 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6288 if (ret)
6289 {
6290 capability[0].pszObjId = oid1;
6291 capability[0].Parameters.cbData = 0;
6292 capabilities.cCapability = 1;
6293 capabilities.rgCapability = capability;
6294 compareSMimeCapabilities("single capability", &capabilities, ptr);
6295 LocalFree(ptr);
6296 }
6297 SetLastError(0xdeadbeef);
6298 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6299 singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL),
6300 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size);
6301 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6302 if (ret)
6303 {
6304 BYTE NULLparam[] = {0x05, 0x00};
6305 capability[0].pszObjId = oid1;
6306 capability[0].Parameters.cbData = 2;
6307 capability[0].Parameters.pbData = NULLparam;
6308 capabilities.cCapability = 1;
6309 capabilities.rgCapability = capability;
6310 compareSMimeCapabilities("single capability with NULL", &capabilities,
6311 ptr);
6312 LocalFree(ptr);
6313 }
6314 SetLastError(0xdeadbeef);
6315 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES,
6316 twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL,
6317 &ptr, &size);
6318 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
6319 if (ret)
6320 {
6321 capability[0].Parameters.cbData = 0;
6322 capability[1].pszObjId = oid2;
6323 capability[1].Parameters.cbData = 0;
6324 capabilities.cCapability = 2;
6325 compareSMimeCapabilities("two capabilities", &capabilities, ptr);
6326 LocalFree(ptr);
6327 }
6328 }
6329
6330 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10,
6331 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,
6332 0x67 };
6333 static const BYTE minimalPKCSSigner[] = {
6334 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6335 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6336 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6337 static const BYTE PKCSSignerWithSerial[] = {
6338 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6339 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6340 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,
6341 0x00 };
6342 static const BYTE PKCSSignerWithHashAlgo[] = {
6343 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6344 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6345 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05,
6346 0x00,0x04,0x00 };
6347 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = {
6348 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6349 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6350 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6351 0x06,0x05,0x00,0x04,0x00 };
6352 static const BYTE PKCSSignerWithHash[] = {
6353 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6354 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6355 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d,
6356 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,
6357 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6358 static const BYTE PKCSSignerWithAuthAttr[] = {
6359 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03,
6360 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02,
6361 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06,
6362 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,
6363 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30,
6364 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,
6365 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f };
6366
6367 static void test_encodePKCSSignerInfo(DWORD dwEncoding)
6368 {
6369 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6370 BOOL ret;
6371 LPBYTE buf = NULL;
6372 DWORD size = 0;
6373 CMSG_SIGNER_INFO info = { 0 };
6374 char oid_common_name[] = szOID_COMMON_NAME;
6375 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName),
6376 (LPBYTE)encodedCommonName };
6377 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName };
6378
6379 SetLastError(0xdeadbeef);
6380 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6381 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6382 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6383 {
6384 skip("no PKCS7_SIGNER_INFO encode support\n");
6385 return;
6386 }
6387 ok(!ret && (GetLastError() == E_INVALIDARG ||
6388 GetLastError() == OSS_LIMITED /* Win9x */),
6389 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
6390 /* To be encoded, a signer must have an issuer at least, and the encoding
6391 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded,
6392 * see decoding tests.)
6393 */
6394 info.Issuer.cbData = sizeof(encodedCommonNameNoNull);
6395 info.Issuer.pbData = encodedCommonNameNoNull;
6396 SetLastError(0xdeadbeef);
6397 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6398 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6399 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6400 ok(!ret && GetLastError() == E_INVALIDARG,
6401 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6402 else
6403 {
6404 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6405 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6406 if (buf)
6407 {
6408 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6409 if (size == sizeof(minimalPKCSSigner))
6410 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6411 else
6412 ok(0, "Unexpected value\n");
6413 LocalFree(buf);
6414 }
6415 }
6416 info.SerialNumber.cbData = sizeof(serialNum);
6417 info.SerialNumber.pbData = (BYTE *)serialNum;
6418 SetLastError(0xdeadbeef);
6419 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6420 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6421 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6422 ok(!ret && GetLastError() == E_INVALIDARG,
6423 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6424 else
6425 {
6426 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6427 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6428 if (buf)
6429 {
6430 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6431 size);
6432 if (size == sizeof(PKCSSignerWithSerial))
6433 ok(!memcmp(buf, PKCSSignerWithSerial, size),
6434 "Unexpected value\n");
6435 else
6436 ok(0, "Unexpected value\n");
6437 LocalFree(buf);
6438 }
6439 }
6440 info.HashAlgorithm.pszObjId = oid1;
6441 SetLastError(0xdeadbeef);
6442 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6443 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6444 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6445 ok(!ret && GetLastError() == E_INVALIDARG,
6446 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6447 else
6448 {
6449 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */),
6450 "CryptEncodeObjectEx failed: %x\n", GetLastError());
6451 if (buf)
6452 {
6453 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6454 size);
6455 if (size == sizeof(PKCSSignerWithHashAlgo))
6456 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6457 "Unexpected value\n");
6458 else
6459 ok(0, "Unexpected value\n");
6460 LocalFree(buf);
6461 }
6462 }
6463 info.HashEncryptionAlgorithm.pszObjId = oid2;
6464 SetLastError(0xdeadbeef);
6465 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6466 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6467 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6468 ok(!ret && GetLastError() == E_INVALIDARG,
6469 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6470 else
6471 {
6472 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6473 if (buf)
6474 {
6475 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6476 "Unexpected size %d\n", size);
6477 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo))
6478 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6479 "Unexpected value\n");
6480 else
6481 ok(0, "Unexpected value\n");
6482 LocalFree(buf);
6483 }
6484 }
6485 info.EncryptedHash.cbData = sizeof(hash);
6486 info.EncryptedHash.pbData = (BYTE *)hash;
6487 SetLastError(0xdeadbeef);
6488 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6489 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6490 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6491 ok(!ret && GetLastError() == E_INVALIDARG,
6492 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6493 else
6494 {
6495 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6496 if (buf)
6497 {
6498 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6499 size);
6500 if (size == sizeof(PKCSSignerWithHash))
6501 ok(!memcmp(buf, PKCSSignerWithHash, size),
6502 "Unexpected value\n");
6503 else
6504 ok(0, "Unexpected value\n");
6505 LocalFree(buf);
6506 }
6507 }
6508 info.AuthAttrs.cAttr = 1;
6509 info.AuthAttrs.rgAttr = &attr;
6510 SetLastError(0xdeadbeef);
6511 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info,
6512 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6513 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6514 ok(!ret && GetLastError() == E_INVALIDARG,
6515 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6516 else
6517 {
6518 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6519 if (buf)
6520 {
6521 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n",
6522 size);
6523 if (size == sizeof(PKCSSignerWithAuthAttr))
6524 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size),
6525 "Unexpected value\n");
6526 else
6527 ok(0, "Unexpected value\n");
6528 LocalFree(buf);
6529 }
6530 }
6531 }
6532
6533 static void test_decodePKCSSignerInfo(DWORD dwEncoding)
6534 {
6535 BOOL ret;
6536 LPBYTE buf = NULL;
6537 DWORD size = 0;
6538 CMSG_SIGNER_INFO *info;
6539
6540 /* A PKCS signer can't be decoded without a serial number. */
6541 SetLastError(0xdeadbeef);
6542 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6543 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6544 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6545 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT ||
6546 GetLastError() == OSS_DATA_ERROR /* Win9x */),
6547 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n",
6548 GetLastError());
6549 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6550 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6551 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6552 ok(ret || broken(GetLastError() == OSS_DATA_ERROR),
6553 "CryptDecodeObjectEx failed: %x\n", GetLastError());
6554 if (buf)
6555 {
6556 info = (CMSG_SIGNER_INFO *)buf;
6557 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6558 info->dwVersion);
6559 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6560 "Unexpected size %d\n", info->Issuer.cbData);
6561 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6562 info->Issuer.cbData), "Unexpected value\n");
6563 ok(info->SerialNumber.cbData == sizeof(serialNum),
6564 "Unexpected size %d\n", info->SerialNumber.cbData);
6565 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6566 "Unexpected value\n");
6567 LocalFree(buf);
6568 }
6569 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6570 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6571 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6572 if (buf)
6573 {
6574 info = (CMSG_SIGNER_INFO *)buf;
6575 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6576 info->dwVersion);
6577 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6578 "Unexpected size %d\n", info->Issuer.cbData);
6579 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6580 info->Issuer.cbData), "Unexpected value\n");
6581 ok(info->SerialNumber.cbData == sizeof(serialNum),
6582 "Unexpected size %d\n", info->SerialNumber.cbData);
6583 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6584 "Unexpected value\n");
6585 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6586 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6587 LocalFree(buf);
6588 }
6589 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6590 PKCSSignerWithHashAndEncryptionAlgo,
6591 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6592 NULL, &buf, &size);
6593 if (buf)
6594 {
6595 info = (CMSG_SIGNER_INFO *)buf;
6596 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6597 info->dwVersion);
6598 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6599 "Unexpected size %d\n", info->Issuer.cbData);
6600 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6601 info->Issuer.cbData), "Unexpected value\n");
6602 ok(info->SerialNumber.cbData == sizeof(serialNum),
6603 "Unexpected size %d\n", info->SerialNumber.cbData);
6604 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6605 "Unexpected value\n");
6606 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6607 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6608 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6609 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6610 LocalFree(buf);
6611 }
6612 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6613 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6614 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6615 if (buf)
6616 {
6617 info = (CMSG_SIGNER_INFO *)buf;
6618 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6619 info->dwVersion);
6620 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull),
6621 "Unexpected size %d\n", info->Issuer.cbData);
6622 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull,
6623 info->Issuer.cbData), "Unexpected value\n");
6624 ok(info->SerialNumber.cbData == sizeof(serialNum),
6625 "Unexpected size %d\n", info->SerialNumber.cbData);
6626 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)),
6627 "Unexpected value\n");
6628 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"),
6629 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId);
6630 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"),
6631 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId);
6632 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6633 info->EncryptedHash.cbData);
6634 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6635 "Unexpected value\n");
6636 LocalFree(buf);
6637 }
6638 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO,
6639 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr),
6640 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6641 if (buf)
6642 {
6643 info = (CMSG_SIGNER_INFO *)buf;
6644 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n",
6645 info->AuthAttrs.cAttr);
6646 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME),
6647 "Expected %s, got %s\n", szOID_COMMON_NAME,
6648 info->AuthAttrs.rgAttr[0].pszObjId);
6649 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n",
6650 info->AuthAttrs.rgAttr[0].cValue);
6651 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData ==
6652 sizeof(encodedCommonName), "Unexpected size %d\n",
6653 info->AuthAttrs.rgAttr[0].rgValue[0].cbData);
6654 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData,
6655 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n");
6656 LocalFree(buf);
6657 }
6658 }
6659
6660 static const BYTE CMSSignerWithKeyId[] = {
6661 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,
6662 0x04,0x06,0x00,0x05,0x00,0x04,0x00 };
6663
6664 static void test_encodeCMSSignerInfo(DWORD dwEncoding)
6665 {
6666 BOOL ret;
6667 LPBYTE buf = NULL;
6668 DWORD size = 0;
6669 CMSG_CMS_SIGNER_INFO info = { 0 };
6670 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6671
6672 SetLastError(0xdeadbeef);
6673 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6674 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6675 ok(!ret, "Expected failure, got %d\n", ret);
6676 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6677 {
6678 skip("no CMS_SIGNER_INFO encode support\n");
6679 return;
6680 }
6681 ok(GetLastError() == E_INVALIDARG,
6682 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6683 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6684 SetLastError(0xdeadbeef);
6685 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6686 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6687 ok(!ret, "Expected failure, got %d\n", ret);
6688 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6689 {
6690 skip("no CMS_SIGNER_INFO encode support\n");
6691 return;
6692 }
6693 ok(GetLastError() == E_INVALIDARG,
6694 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6695 /* To be encoded, a signer must have a valid cert ID, where a valid ID may
6696 * be a key id or a issuer serial number with at least the issuer set, and
6697 * the encoding must include PKCS_7_ASN_ENCODING.
6698 * (That isn't enough to be decoded, see decoding tests.)
6699 */
6700 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6701 sizeof(encodedCommonNameNoNull);
6702 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6703 SetLastError(0xdeadbeef);
6704 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6705 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6706 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6707 ok(!ret && GetLastError() == E_INVALIDARG,
6708 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6709 else
6710 {
6711 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6712 if (buf)
6713 {
6714 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size);
6715 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n");
6716 LocalFree(buf);
6717 }
6718 }
6719 U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum);
6720 U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum;
6721 SetLastError(0xdeadbeef);
6722 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6723 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6724 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6725 ok(!ret && GetLastError() == E_INVALIDARG,
6726 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6727 else
6728 {
6729 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6730 if (buf)
6731 {
6732 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n",
6733 size);
6734 ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n");
6735 LocalFree(buf);
6736 }
6737 }
6738 info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER;
6739 U(info.SignerId).KeyId.cbData = sizeof(serialNum);
6740 U(info.SignerId).KeyId.pbData = (BYTE *)serialNum;
6741 SetLastError(0xdeadbeef);
6742 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6743 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6744 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6745 ok(!ret && GetLastError() == E_INVALIDARG,
6746 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6747 else
6748 {
6749 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6750 if (buf)
6751 {
6752 ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n",
6753 size);
6754 ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n");
6755 LocalFree(buf);
6756 }
6757 }
6758 /* While a CERT_ID can have a hash type, that's not allowed in CMS, where
6759 * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed
6760 * (see RFC 3852, section 5.3.)
6761 */
6762 info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH;
6763 U(info.SignerId).HashId.cbData = sizeof(hash);
6764 U(info.SignerId).HashId.pbData = (BYTE *)hash;
6765 SetLastError(0xdeadbeef);
6766 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6767 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6768 ok(!ret && GetLastError() == E_INVALIDARG,
6769 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6770 /* Now with a hash algo */
6771 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER;
6772 U(info.SignerId).IssuerSerialNumber.Issuer.cbData =
6773 sizeof(encodedCommonNameNoNull);
6774 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull;
6775 info.HashAlgorithm.pszObjId = oid1;
6776 SetLastError(0xdeadbeef);
6777 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6778 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6779 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6780 ok(!ret && GetLastError() == E_INVALIDARG,
6781 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6782 else
6783 {
6784 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6785 if (buf)
6786 {
6787 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n",
6788 size);
6789 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size),
6790 "Unexpected value\n");
6791 LocalFree(buf);
6792 }
6793 }
6794 info.HashEncryptionAlgorithm.pszObjId = oid2;
6795 SetLastError(0xdeadbeef);
6796 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6797 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6798 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6799 ok(!ret && GetLastError() == E_INVALIDARG,
6800 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6801 else
6802 {
6803 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6804 if (buf)
6805 {
6806 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo),
6807 "Unexpected size %d\n", size);
6808 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size),
6809 "Unexpected value\n");
6810 LocalFree(buf);
6811 }
6812 }
6813 info.EncryptedHash.cbData = sizeof(hash);
6814 info.EncryptedHash.pbData = (BYTE *)hash;
6815 SetLastError(0xdeadbeef);
6816 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info,
6817 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
6818 if (!(dwEncoding & PKCS_7_ASN_ENCODING))
6819 ok(!ret && GetLastError() == E_INVALIDARG,
6820 "Expected E_INVALIDARG, got %08x\n", GetLastError());
6821 else
6822 {
6823 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError());
6824 if (buf)
6825 {
6826 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n",
6827 size);
6828 ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n");
6829 LocalFree(buf);
6830 }
6831 }
6832 }
6833
6834 static void test_decodeCMSSignerInfo(DWORD dwEncoding)
6835 {
6836 BOOL ret;
6837 LPBYTE buf = NULL;
6838 DWORD size = 0;
6839 CMSG_CMS_SIGNER_INFO *info;
6840 static char oid1[] = "1.2.3", oid2[] = "1.5.6";
6841
6842 /* A CMS signer can't be decoded without a serial number. */
6843 SetLastError(0xdeadbeef);
6844 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6845 minimalPKCSSigner, sizeof(minimalPKCSSigner),
6846 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6847 ok(!ret, "expected failure\n");
6848 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
6849 {
6850 skip("no CMS_SIGNER_INFO decode support\n");
6851 return;
6852 }
6853 ok(GetLastError() == CRYPT_E_ASN1_CORRUPT,
6854 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError());
6855 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6856 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial),
6857 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6858 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6859 if (buf)
6860 {
6861 info = (CMSG_CMS_SIGNER_INFO *)buf;
6862 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6863 info->dwVersion);
6864 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6865 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6866 info->SignerId.dwIdChoice);
6867 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6868 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6869 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6870 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6871 encodedCommonNameNoNull,
6872 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6873 "Unexpected value\n");
6874 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6875 sizeof(serialNum), "Unexpected size %d\n",
6876 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6877 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6878 serialNum, sizeof(serialNum)), "Unexpected value\n");
6879 LocalFree(buf);
6880 }
6881 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6882 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo),
6883 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6884 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6885 if (buf)
6886 {
6887 info = (CMSG_CMS_SIGNER_INFO *)buf;
6888 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6889 info->dwVersion);
6890 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6891 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6892 info->SignerId.dwIdChoice);
6893 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6894 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6895 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6896 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6897 encodedCommonNameNoNull,
6898 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6899 "Unexpected value\n");
6900 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6901 sizeof(serialNum), "Unexpected size %d\n",
6902 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6903 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6904 serialNum, sizeof(serialNum)), "Unexpected value\n");
6905 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6906 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6907 LocalFree(buf);
6908 }
6909 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6910 PKCSSignerWithHashAndEncryptionAlgo,
6911 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG,
6912 NULL, &buf, &size);
6913 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6914 if (buf)
6915 {
6916 info = (CMSG_CMS_SIGNER_INFO *)buf;
6917 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6918 info->dwVersion);
6919 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6920 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6921 info->SignerId.dwIdChoice);
6922 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6923 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6924 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6925 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6926 encodedCommonNameNoNull,
6927 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6928 "Unexpected value\n");
6929 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6930 sizeof(serialNum), "Unexpected size %d\n",
6931 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6932 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6933 serialNum, sizeof(serialNum)), "Unexpected value\n");
6934 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6935 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6936 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6937 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6938 LocalFree(buf);
6939 }
6940 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6941 PKCSSignerWithHash, sizeof(PKCSSignerWithHash),
6942 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6943 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6944 if (buf)
6945 {
6946 info = (CMSG_CMS_SIGNER_INFO *)buf;
6947 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6948 info->dwVersion);
6949 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER,
6950 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n",
6951 info->SignerId.dwIdChoice);
6952 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData ==
6953 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n",
6954 U(info->SignerId).IssuerSerialNumber.Issuer.cbData);
6955 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData,
6956 encodedCommonNameNoNull,
6957 U(info->SignerId).IssuerSerialNumber.Issuer.cbData),
6958 "Unexpected value\n");
6959 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData ==
6960 sizeof(serialNum), "Unexpected size %d\n",
6961 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData);
6962 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData,
6963 serialNum, sizeof(serialNum)), "Unexpected value\n");
6964 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1),
6965 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId);
6966 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2),
6967 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId);
6968 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n",
6969 info->EncryptedHash.cbData);
6970 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)),
6971 "Unexpected value\n");
6972 LocalFree(buf);
6973 }
6974 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO,
6975 CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId),
6976 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size);
6977 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError());
6978 if (buf)
6979 {
6980 info = (CMSG_CMS_SIGNER_INFO *)buf;
6981 ok(info->dwVersion == 0, "Expected version 0, got %d\n",
6982 info->dwVersion);
6983 ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER,
6984 "Expected CERT_ID_KEY_IDENTIFIER, got %d\n",
6985 info->SignerId.dwIdChoice);
6986 ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum),
6987 "Unexpected size %d\n", U(info->SignerId).KeyId.cbData);
6988 ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)),
6989 "Unexpected value\n");
6990 LocalFree(buf);
6991 }
6992 }
6993
6994 static BYTE emptyDNSPermittedConstraints[] = {
6995 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 };
6996 static BYTE emptyDNSExcludedConstraints[] = {
6997 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 };
6998 static BYTE DNSExcludedConstraints[] = {
6999 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,
7000 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7001 static BYTE permittedAndExcludedConstraints[] = {
7002 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7003 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,
7004 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7005 static BYTE permittedAndExcludedWithMinConstraints[] = {
7006 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7007 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,
7008 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7009 static BYTE permittedAndExcludedWithMinMaxConstraints[] = {
7010 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,
7011 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,
7012 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 };
7013
7014 static void test_encodeNameConstraints(DWORD dwEncoding)
7015 {
7016 BOOL ret;
7017 CERT_NAME_CONSTRAINTS_INFO constraints = { 0 };
7018 CERT_GENERAL_SUBTREE permitted = { { 0 } };
7019 CERT_GENERAL_SUBTREE excluded = { { 0 } };
7020 LPBYTE buf;
7021 DWORD size;
7022
7023 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7024 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7025 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7026 {
7027 skip("no X509_NAME_CONSTRAINTS encode support\n");
7028 return;
7029 }
7030 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7031 if (ret)
7032 {
7033 ok(size == sizeof(emptySequence), "Unexpected size\n");
7034 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
7035 LocalFree(buf);
7036 }
7037 constraints.cPermittedSubtree = 1;
7038 constraints.rgPermittedSubtree = &permitted;
7039 SetLastError(0xdeadbeef);
7040 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7041 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7042 ok(!ret && GetLastError() == E_INVALIDARG,
7043 "Expected E_INVALIDARG, got %08x\n", GetLastError());
7044 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7045 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7046 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7047 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7048 if (ret)
7049 {
7050 ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n");
7051 ok(!memcmp(buf, emptyDNSPermittedConstraints, size),
7052 "Unexpected value\n");
7053 LocalFree(buf);
7054 }
7055 constraints.cPermittedSubtree = 0;
7056 constraints.cExcludedSubtree = 1;
7057 constraints.rgExcludedSubtree = &excluded;
7058 excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
7059 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7060 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7061 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7062 if (ret)
7063 {
7064 ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n");
7065 ok(!memcmp(buf, emptyDNSExcludedConstraints, size),
7066 "Unexpected value\n");
7067 LocalFree(buf);
7068 }
7069 U(excluded.Base).pwszURL = (LPWSTR)url;
7070 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7071 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7072 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7073 if (ret)
7074 {
7075 ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n");
7076 ok(!memcmp(buf, DNSExcludedConstraints, size),
7077 "Unexpected value\n");
7078 LocalFree(buf);
7079 }
7080 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
7081 U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7082 U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7083 constraints.cPermittedSubtree = 1;
7084 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7085 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7086 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7087 if (ret)
7088 {
7089 ok(size == sizeof(permittedAndExcludedConstraints),
7090 "Unexpected size\n");
7091 ok(!memcmp(buf, permittedAndExcludedConstraints, size),
7092 "Unexpected value\n");
7093 LocalFree(buf);
7094 }
7095 permitted.dwMinimum = 5;
7096 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7097 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7098 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7099 if (ret)
7100 {
7101 ok(size == sizeof(permittedAndExcludedWithMinConstraints),
7102 "Unexpected size\n");
7103 ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size),
7104 "Unexpected value\n");
7105 LocalFree(buf);
7106 }
7107 permitted.fMaximum = TRUE;
7108 permitted.dwMaximum = 3;
7109 SetLastError(0xdeadbeef);
7110 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints,
7111 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7112 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7113 if (ret)
7114 {
7115 ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints),
7116 "Unexpected size\n");
7117 ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size),
7118 "Unexpected value\n");
7119 LocalFree(buf);
7120 }
7121 }
7122
7123 struct EncodedNameConstraints
7124 {
7125 CRYPT_DATA_BLOB encoded;
7126 CERT_NAME_CONSTRAINTS_INFO constraints;
7127 };
7128
7129 static CERT_GENERAL_SUBTREE emptyDNSSubtree = {
7130 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7131 static CERT_GENERAL_SUBTREE DNSSubtree = {
7132 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 };
7133 static CERT_GENERAL_SUBTREE IPAddressSubtree = {
7134 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 };
7135 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = {
7136 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 };
7137 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = {
7138 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 };
7139
7140 struct EncodedNameConstraints encodedNameConstraints[] = {
7141 { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } },
7142 { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints },
7143 { 1, &emptyDNSSubtree, 0, NULL } },
7144 { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints },
7145 { 0, NULL, 1, &emptyDNSSubtree } },
7146 { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints },
7147 { 0, NULL, 1, &DNSSubtree } },
7148 { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints },
7149 { 1, &IPAddressSubtree, 1, &DNSSubtree } },
7150 { { sizeof(permittedAndExcludedWithMinConstraints),
7151 permittedAndExcludedWithMinConstraints },
7152 { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } },
7153 { { sizeof(permittedAndExcludedWithMinMaxConstraints),
7154 permittedAndExcludedWithMinMaxConstraints },
7155 { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } },
7156 };
7157
7158 static void test_decodeNameConstraints(DWORD dwEncoding)
7159 {
7160 BOOL ret;
7161 DWORD i;
7162 CERT_NAME_CONSTRAINTS_INFO *constraints;
7163
7164 U(DNSSubtree.Base).pwszURL = (LPWSTR)url;
7165 U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7166 U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7167 U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7168 U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7169 U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr);
7170 U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr;
7171 for (i = 0;
7172 i < sizeof(encodedNameConstraints) / sizeof(encodedNameConstraints[0]);
7173 i++)
7174 {
7175 DWORD size;
7176
7177 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS,
7178 encodedNameConstraints[i].encoded.pbData,
7179 encodedNameConstraints[i].encoded.cbData,
7180 CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size);
7181 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7182 {
7183 skip("no X509_NAME_CONSTRAINTS decode support\n");
7184 return;
7185 }
7186 ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError());
7187 if (ret)
7188 {
7189 DWORD j;
7190
7191 if (constraints->cPermittedSubtree !=
7192 encodedNameConstraints[i].constraints.cPermittedSubtree)
7193 fprintf(stderr, "%d: expected %d permitted, got %d\n", i,
7194 encodedNameConstraints[i].constraints.cPermittedSubtree,
7195 constraints->cPermittedSubtree);
7196 if (constraints->cPermittedSubtree ==
7197 encodedNameConstraints[i].constraints.cPermittedSubtree)
7198 {
7199 for (j = 0; j < constraints->cPermittedSubtree; j++)
7200 {
7201 compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base,
7202 &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base);
7203 }
7204 }
7205 if (constraints->cExcludedSubtree !=
7206 encodedNameConstraints[i].constraints.cExcludedSubtree)
7207 fprintf(stderr, "%d: expected %d excluded, got %d\n", i,
7208 encodedNameConstraints[i].constraints.cExcludedSubtree,
7209 constraints->cExcludedSubtree);
7210 if (constraints->cExcludedSubtree ==
7211 encodedNameConstraints[i].constraints.cExcludedSubtree)
7212 {
7213 for (j = 0; j < constraints->cExcludedSubtree; j++)
7214 {
7215 compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base,
7216 &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base);
7217 }
7218 }
7219 LocalFree(constraints);
7220 }
7221 }
7222 }
7223
7224 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ',
7225 'n','o','t','i','c','e',0 };
7226 static const BYTE noticeWithDisplayText[] = {
7227 0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00,
7228 0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74,
7229 0x00,0x69,0x00,0x63,0x00,0x65
7230 };
7231 static char org[] = "Wine";
7232 static int noticeNumbers[] = { 2,3 };
7233 static BYTE noticeWithReference[] = {
7234 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7235 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7236 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7237 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7238 };
7239
7240 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding)
7241 {
7242 BOOL ret;
7243 LPBYTE buf;
7244 DWORD size;
7245 CERT_POLICY_QUALIFIER_USER_NOTICE notice;
7246 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference;
7247
7248 memset(&notice, 0, sizeof(notice));
7249 ret = pCryptEncodeObjectEx(dwEncoding,
7250 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7251 NULL, &buf, &size);
7252 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7253 {
7254 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n");
7255 return;
7256 }
7257 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7258 if (ret)
7259 {
7260 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7261 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7262 LocalFree(buf);
7263 }
7264 notice.pszDisplayText = noticeText;
7265 ret = pCryptEncodeObjectEx(dwEncoding,
7266 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7267 NULL, &buf, &size);
7268 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7269 if (ret)
7270 {
7271 ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size);
7272 ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n");
7273 LocalFree(buf);
7274 }
7275 reference.pszOrganization = org;
7276 reference.cNoticeNumbers = 2;
7277 reference.rgNoticeNumbers = noticeNumbers;
7278 notice.pNoticeReference = &reference;
7279 ret = pCryptEncodeObjectEx(dwEncoding,
7280 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, &notice, CRYPT_ENCODE_ALLOC_FLAG,
7281 NULL, &buf, &size);
7282 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7283 if (ret)
7284 {
7285 ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size);
7286 ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n");
7287 LocalFree(buf);
7288 }
7289 }
7290
7291 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding)
7292 {
7293 BOOL ret;
7294 CERT_POLICY_QUALIFIER_USER_NOTICE *notice;
7295 DWORD size;
7296
7297 ret = pCryptDecodeObjectEx(dwEncoding,
7298 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7299 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7300 &notice, &size);
7301 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7302 {
7303 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n");
7304 return;
7305 }
7306 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7307 if (ret)
7308 {
7309 ok(notice->pszDisplayText == NULL, "unexpected display text\n");
7310 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7311 LocalFree(notice);
7312 }
7313 ret = pCryptDecodeObjectEx(dwEncoding,
7314 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7315 noticeWithDisplayText, sizeof(noticeWithDisplayText),
7316 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7317 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7318 if (ret)
7319 {
7320 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7321 "unexpected display text\n");
7322 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n");
7323 LocalFree(notice);
7324 }
7325 ret = pCryptDecodeObjectEx(dwEncoding,
7326 X509_PKIX_POLICY_QUALIFIER_USERNOTICE,
7327 noticeWithReference, sizeof(noticeWithReference),
7328 CRYPT_DECODE_ALLOC_FLAG, NULL, &notice, &size);
7329 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7330 if (ret)
7331 {
7332 ok(!lstrcmpW(notice->pszDisplayText, noticeText),
7333 "unexpected display text\n");
7334 ok(notice->pNoticeReference != NULL, "expected a notice reference\n");
7335 if (notice->pNoticeReference)
7336 {
7337 ok(!strcmp(notice->pNoticeReference->pszOrganization, org),
7338 "unexpected organization %s\n",
7339 notice->pNoticeReference->pszOrganization);
7340 ok(notice->pNoticeReference->cNoticeNumbers == 2,
7341 "expected 2 notice numbers, got %d\n",
7342 notice->pNoticeReference->cNoticeNumbers);
7343 ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0],
7344 "unexpected notice number %d\n",
7345 notice->pNoticeReference->rgNoticeNumbers[0]);
7346 ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1],
7347 "unexpected notice number %d\n",
7348 notice->pNoticeReference->rgNoticeNumbers[1]);
7349 }
7350 LocalFree(notice);
7351 }
7352 }
7353
7354 static char oid_any_policy[] = "2.5.29.32.0";
7355 static const BYTE policiesWithAnyPolicy[] = {
7356 0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00
7357 };
7358 static char oid1[] = "1.2.3";
7359 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2";
7360 static const BYTE twoPolicies[] = {
7361 0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a,
7362 0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02,
7363 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02,
7364 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,
7365 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,
7366 0x74,0x00,0x69,0x00,0x63,0x00,0x65
7367 };
7368
7369 static void test_encodeCertPolicies(DWORD dwEncoding)
7370 {
7371 BOOL ret;
7372 CERT_POLICIES_INFO info;
7373 CERT_POLICY_INFO policy[2];
7374 CERT_POLICY_QUALIFIER_INFO qualifier;
7375 LPBYTE buf;
7376 DWORD size;
7377
7378 memset(&info, 0, sizeof(info));
7379 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7380 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7381 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7382 if (ret)
7383 {
7384 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size);
7385 ok(!memcmp(buf, emptySequence, size), "unexpected value\n");
7386 LocalFree(buf);
7387 }
7388 memset(policy, 0, sizeof(policy));
7389 info.cPolicyInfo = 1;
7390 info.rgPolicyInfo = policy;
7391 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7392 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7393 ok(!ret && (GetLastError() == E_INVALIDARG ||
7394 GetLastError() == OSS_LIMITED /* Win9x/NT4 */),
7395 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError());
7396 policy[0].pszPolicyIdentifier = oid_any_policy;
7397 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7398 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7399 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7400 if (ret)
7401 {
7402 ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size);
7403 ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n");
7404 LocalFree(buf);
7405 }
7406 policy[1].pszPolicyIdentifier = oid1;
7407 memset(&qualifier, 0, sizeof(qualifier));
7408 qualifier.pszPolicyQualifierId = oid_user_notice;
7409 qualifier.Qualifier.cbData = sizeof(noticeWithReference);
7410 qualifier.Qualifier.pbData = noticeWithReference;
7411 policy[1].cPolicyQualifier = 1;
7412 policy[1].rgPolicyQualifier = &qualifier;
7413 info.cPolicyInfo = 2;
7414 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info,
7415 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7416 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7417 if (ret)
7418 {
7419 ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size);
7420 ok(!memcmp(buf, twoPolicies, size), "unexpected value\n");
7421 LocalFree(buf);
7422 }
7423 }
7424
7425 static void test_decodeCertPolicies(DWORD dwEncoding)
7426 {
7427 BOOL ret;
7428 CERT_POLICIES_INFO *info;
7429 DWORD size;
7430
7431 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7432 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7433 &info, &size);
7434 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7435 if (ret)
7436 {
7437 ok(info->cPolicyInfo == 0, "unexpected policy info %d\n",
7438 info->cPolicyInfo);
7439 LocalFree(info);
7440 }
7441 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7442 policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy),
7443 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7444 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7445 if (ret)
7446 {
7447 ok(info->cPolicyInfo == 1, "unexpected policy info %d\n",
7448 info->cPolicyInfo);
7449 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7450 "unexpected policy id %s\n",
7451 info->rgPolicyInfo[0].pszPolicyIdentifier);
7452 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7453 "unexpected policy qualifier count %d\n",
7454 info->rgPolicyInfo[0].cPolicyQualifier);
7455 LocalFree(info);
7456 }
7457 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES,
7458 twoPolicies, sizeof(twoPolicies),
7459 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7460 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7461 if (ret)
7462 {
7463 ok(info->cPolicyInfo == 2, "unexpected policy info %d\n",
7464 info->cPolicyInfo);
7465 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy),
7466 "unexpected policy id %s\n",
7467 info->rgPolicyInfo[0].pszPolicyIdentifier);
7468 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0,
7469 "unexpected policy qualifier count %d\n",
7470 info->rgPolicyInfo[0].cPolicyQualifier);
7471 ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1),
7472 "unexpected policy id %s\n",
7473 info->rgPolicyInfo[1].pszPolicyIdentifier);
7474 ok(info->rgPolicyInfo[1].cPolicyQualifier == 1,
7475 "unexpected policy qualifier count %d\n",
7476 info->rgPolicyInfo[1].cPolicyQualifier);
7477 ok(!strcmp(
7478 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId,
7479 oid_user_notice), "unexpected policy qualifier id %s\n",
7480 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId);
7481 ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData ==
7482 sizeof(noticeWithReference), "unexpected qualifier size %d\n",
7483 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData);
7484 ok(!memcmp(
7485 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData,
7486 noticeWithReference, sizeof(noticeWithReference)),
7487 "unexpected qualifier value\n");
7488 LocalFree(info);
7489 }
7490 }
7491
7492 static const BYTE policyMappingWithOneMapping[] = {
7493 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 };
7494 static const BYTE policyMappingWithTwoMappings[] = {
7495 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06,
7496 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 };
7497 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS,
7498 szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS };
7499
7500 static void test_encodeCertPolicyMappings(DWORD dwEncoding)
7501 {
7502 static char oid2[] = "2.3.4";
7503 static char oid3[] = "1.3.4";
7504 static char oid4[] = "2.5.6";
7505 BOOL ret;
7506 CERT_POLICY_MAPPINGS_INFO info = { 0 };
7507 CERT_POLICY_MAPPING mapping[2];
7508 LPBYTE buf;
7509 DWORD size, i;
7510
7511 /* Each of the mapping OIDs is equivalent, so check with all of them */
7512 for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7513 {
7514 memset(&info, 0, sizeof(info));
7515 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7516 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7517 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7518 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7519 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7520 {
7521 win_skip("no policy mappings support\n");
7522 return;
7523 }
7524 if (ret)
7525 {
7526 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7527 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7528 "unexpected value\n");
7529 LocalFree(buf);
7530 }
7531 mapping[0].pszIssuerDomainPolicy = NULL;
7532 mapping[0].pszSubjectDomainPolicy = NULL;
7533 info.cPolicyMapping = 1;
7534 info.rgPolicyMapping = mapping;
7535 SetLastError(0xdeadbeef);
7536 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7537 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7538 ok(!ret && GetLastError() == E_INVALIDARG,
7539 "expected E_INVALIDARG, got %08x\n", GetLastError());
7540 mapping[0].pszIssuerDomainPolicy = oid1;
7541 mapping[0].pszSubjectDomainPolicy = oid2;
7542 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7543 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7544 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7545 if (ret)
7546 {
7547 ok(size == sizeof(policyMappingWithOneMapping),
7548 "unexpected size %d\n", size);
7549 ok(!memcmp(buf, policyMappingWithOneMapping, size),
7550 "unexpected value\n");
7551 LocalFree(buf);
7552 }
7553 mapping[1].pszIssuerDomainPolicy = oid3;
7554 mapping[1].pszSubjectDomainPolicy = oid4;
7555 info.cPolicyMapping = 2;
7556 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info,
7557 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7558 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7559 if (ret)
7560 {
7561 ok(size == sizeof(policyMappingWithTwoMappings),
7562 "unexpected size %d\n", size);
7563 ok(!memcmp(buf, policyMappingWithTwoMappings, size),
7564 "unexpected value\n");
7565 LocalFree(buf);
7566 }
7567 }
7568 }
7569
7570 static void test_decodeCertPolicyMappings(DWORD dwEncoding)
7571 {
7572 DWORD size, i;
7573 CERT_POLICY_MAPPINGS_INFO *info;
7574 BOOL ret;
7575
7576 /* Each of the mapping OIDs is equivalent, so check with all of them */
7577 for (i = 0; i < sizeof(mappingOids) / sizeof(mappingOids[0]); i++)
7578 {
7579 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7580 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7581 &info, &size);
7582 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7583 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7584 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7585 {
7586 win_skip("no policy mappings support\n");
7587 return;
7588 }
7589 if (ret)
7590 {
7591 ok(info->cPolicyMapping == 0,
7592 "expected 0 policy mappings, got %d\n", info->cPolicyMapping);
7593 LocalFree(info);
7594 }
7595 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7596 policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping),
7597 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7598 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7599 if (ret)
7600 {
7601 ok(info->cPolicyMapping == 1,
7602 "expected 1 policy mappings, got %d\n", info->cPolicyMapping);
7603 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7604 "unexpected issuer policy %s\n",
7605 info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7606 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7607 "2.3.4"), "unexpected subject policy %s\n",
7608 info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7609 LocalFree(info);
7610 }
7611 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i],
7612 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings),
7613 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7614 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7615 if (ret)
7616 {
7617 ok(info->cPolicyMapping == 2,
7618 "expected 2 policy mappings, got %d\n", info->cPolicyMapping);
7619 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"),
7620 "unexpected issuer policy %s\n",
7621 info->rgPolicyMapping[0].pszIssuerDomainPolicy);
7622 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy,
7623 "2.3.4"), "unexpected subject policy %s\n",
7624 info->rgPolicyMapping[0].pszSubjectDomainPolicy);
7625 ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"),
7626 "unexpected issuer policy %s\n",
7627 info->rgPolicyMapping[1].pszIssuerDomainPolicy);
7628 ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy,
7629 "2.5.6"), "unexpected subject policy %s\n",
7630 info->rgPolicyMapping[1].pszSubjectDomainPolicy);
7631 LocalFree(info);
7632 }
7633 }
7634 }
7635
7636 static const BYTE policyConstraintsWithRequireExplicit[] = {
7637 0x30,0x03,0x80,0x01,0x00 };
7638 static const BYTE policyConstraintsWithInhibitMapping[] = {
7639 0x30,0x03,0x81,0x01,0x01 };
7640 static const BYTE policyConstraintsWithBoth[] = {
7641 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 };
7642
7643 static void test_encodeCertPolicyConstraints(DWORD dwEncoding)
7644 {
7645 CERT_POLICY_CONSTRAINTS_INFO info = { 0 };
7646 LPBYTE buf;
7647 DWORD size;
7648 BOOL ret;
7649
7650 /* Even though RFC 5280 explicitly states CAs must not issue empty
7651 * policy constraints (section 4.2.1.11), the API doesn't prevent it.
7652 */
7653 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7654 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7655 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7656 "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7657 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7658 {
7659 win_skip("no policy constraints support\n");
7660 return;
7661 }
7662 if (ret)
7663 {
7664 ok(size == sizeof(emptySequence), "unexpected size %d\n", size);
7665 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
7666 "unexpected value\n");
7667 LocalFree(buf);
7668 }
7669 /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts
7670 * is not, then a skip of 0 is encoded.
7671 */
7672 info.fRequireExplicitPolicy = TRUE;
7673 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7674 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7675 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7676 if (ret)
7677 {
7678 ok(size == sizeof(policyConstraintsWithRequireExplicit),
7679 "unexpected size %d\n", size);
7680 ok(!memcmp(buf, policyConstraintsWithRequireExplicit,
7681 sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n");
7682 LocalFree(buf);
7683 }
7684 /* With inhibit policy mapping */
7685 info.fRequireExplicitPolicy = FALSE;
7686 info.dwRequireExplicitPolicySkipCerts = 0;
7687 info.fInhibitPolicyMapping = TRUE;
7688 info.dwInhibitPolicyMappingSkipCerts = 1;
7689 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7690 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7691 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7692 if (ret)
7693 {
7694 ok(size == sizeof(policyConstraintsWithInhibitMapping),
7695 "unexpected size %d\n", size);
7696 ok(!memcmp(buf, policyConstraintsWithInhibitMapping,
7697 sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n");
7698 LocalFree(buf);
7699 }
7700 /* And with both */
7701 info.fRequireExplicitPolicy = TRUE;
7702 info.dwRequireExplicitPolicySkipCerts = 1;
7703 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info,
7704 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
7705 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError());
7706 if (ret)
7707 {
7708 ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n",
7709 size);
7710 ok(!memcmp(buf, policyConstraintsWithBoth,
7711 sizeof(policyConstraintsWithBoth)), "unexpected value\n");
7712 LocalFree(buf);
7713 }
7714 }
7715
7716 static void test_decodeCertPolicyConstraints(DWORD dwEncoding)
7717 {
7718 CERT_POLICY_CONSTRAINTS_INFO *info;
7719 DWORD size;
7720 BOOL ret;
7721
7722 /* Again, even though CAs must not issue such constraints, they can be
7723 * decoded.
7724 */
7725 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7726 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
7727 &info, &size);
7728 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND),
7729 "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7730 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND)
7731 {
7732 win_skip("no policy mappings support\n");
7733 return;
7734 }
7735 if (ret)
7736 {
7737 ok(!info->fRequireExplicitPolicy,
7738 "expected require explicit = FALSE\n");
7739 ok(!info->fInhibitPolicyMapping,
7740 "expected implicit mapping = FALSE\n");
7741 LocalFree(info);
7742 }
7743 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7744 policyConstraintsWithRequireExplicit,
7745 sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG,
7746 NULL, &info, &size);
7747 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7748 if (ret)
7749 {
7750 ok(info->fRequireExplicitPolicy,
7751 "expected require explicit = TRUE\n");
7752 ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n",
7753 info->dwRequireExplicitPolicySkipCerts);
7754 ok(!info->fInhibitPolicyMapping,
7755 "expected implicit mapping = FALSE\n");
7756 LocalFree(info);
7757 }
7758 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7759 policyConstraintsWithInhibitMapping,
7760 sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG,
7761 NULL, &info, &size);
7762 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7763 if (ret)
7764 {
7765 ok(!info->fRequireExplicitPolicy,
7766 "expected require explicit = FALSE\n");
7767 ok(info->fInhibitPolicyMapping,
7768 "expected implicit mapping = TRUE\n");
7769 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7770 info->dwInhibitPolicyMappingSkipCerts);
7771 LocalFree(info);
7772 }
7773 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS,
7774 policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth),
7775 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size);
7776 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError());
7777 if (ret)
7778 {
7779 ok(info->fRequireExplicitPolicy,
7780 "expected require explicit = TRUE\n");
7781 ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n",
7782 info->dwRequireExplicitPolicySkipCerts);
7783 ok(info->fInhibitPolicyMapping,
7784 "expected implicit mapping = TRUE\n");
7785 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n",
7786 info->dwInhibitPolicyMappingSkipCerts);
7787 LocalFree(info);
7788 }
7789 }
7790
7791 /* Free *pInfo with HeapFree */
7792 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
7793 {
7794 BOOL ret;
7795 DWORD size = 0;
7796 HCRYPTKEY key;
7797
7798 /* This crashes
7799 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
7800 */
7801 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
7802 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7803 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7804 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
7805 &size);
7806 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7807 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7808 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
7809 NULL, &size);
7810 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7811 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7812 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7813 0, NULL, NULL, &size);
7814 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7815 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7816 /* Test with no key */
7817 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
7818 0, NULL, NULL, &size);
7819 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n",
7820 GetLastError());
7821 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
7822 ok(ret, "CryptGenKey failed: %08x\n", GetLastError());
7823 if (ret)
7824 {
7825 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
7826 NULL, 0, NULL, NULL, &size);
7827 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError());
7828 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
7829 if (*pInfo)
7830 {
7831 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
7832 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
7833 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n",
7834 GetLastError());
7835 if (ret)
7836 {
7837 /* By default (we passed NULL as the OID) the OID is
7838 * szOID_RSA_RSA.
7839 */
7840 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
7841 "Expected %s, got %s\n", szOID_RSA_RSA,
7842 (*pInfo)->Algorithm.pszObjId);
7843 }
7844 }
7845 }
7846 CryptDestroyKey(key);
7847 }
7848
7849 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
7850 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
7851 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
7852 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7853 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7854 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7855 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
7856 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
7857 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
7858 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
7859 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
7860 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
7861 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
7862 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
7863 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
7864 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
7865 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
7866 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
7867 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
7868 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
7869 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
7870 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
7871 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
7872 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
7873 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
7874
7875 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
7876 {
7877 BOOL ret;
7878 HCRYPTKEY key;
7879 PCCERT_CONTEXT context;
7880 DWORD dwSize;
7881 ALG_ID ai;
7882
7883 /* These crash
7884 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
7885 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
7886 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
7887 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7888 NULL);
7889 */
7890 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
7891 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7892 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7893 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
7894 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
7895 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError());
7896 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
7897 &key);
7898 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
7899 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError());
7900
7901 /* Export key with standard algorithm (CALG_RSA_KEYX) */
7902 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
7903 &key);
7904 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7905
7906 dwSize = sizeof(ai);
7907 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7908 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7909 if(ret)
7910 {
7911 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7912 ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai);
7913 }
7914
7915 CryptDestroyKey(key);
7916
7917 /* Repeat with forced algorithm */
7918 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL,
7919 &key);
7920 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7921
7922 dwSize = sizeof(ai);
7923 CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0);
7924 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError());
7925 if(ret)
7926 {
7927 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize);
7928 ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai);
7929 }
7930
7931 CryptDestroyKey(key);
7932
7933 /* Test importing a public key from a certificate context */
7934 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
7935 sizeof(expiredCert));
7936 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n",
7937 GetLastError());
7938 if (context)
7939 {
7940 ok(!strcmp(szOID_RSA_RSA,
7941 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
7942 "Expected %s, got %s\n", szOID_RSA_RSA,
7943 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
7944 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
7945 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
7946 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError());
7947 CryptDestroyKey(key);
7948 CertFreeCertificateContext(context);
7949 }
7950 }
7951
7952 static const char cspName[] = "WineCryptTemp";
7953
7954 static void testPortPublicKeyInfo(void)
7955 {
7956 HCRYPTPROV csp;
7957 BOOL ret;
7958 PCERT_PUBLIC_KEY_INFO info = NULL;
7959
7960 /* Just in case a previous run failed, delete this thing */
7961 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7962 CRYPT_DELETEKEYSET);
7963 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7964 CRYPT_NEWKEYSET);
7965 ok(ret,"CryptAcquireContextA failed\n");
7966
7967 testExportPublicKey(csp, &info);
7968 testImportPublicKey(csp, info);
7969
7970 HeapFree(GetProcessHeap(), 0, info);
7971 CryptReleaseContext(csp, 0);
7972 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
7973 CRYPT_DELETEKEYSET);
7974 ok(ret,"CryptAcquireContextA failed\n");
7975 }
7976
7977 START_TEST(encode)
7978 {
7979 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
7980 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
7981 HMODULE hCrypt32;
7982 DWORD i;
7983
7984 hCrypt32 = GetModuleHandleA("crypt32.dll");
7985 pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx");
7986 pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx");
7987 if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx)
7988 {
7989 win_skip("CryptDecodeObjectEx() is not available\n");
7990 return;
7991 }
7992
7993 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
7994 {
7995 test_encodeInt(encodings[i]);
7996 test_decodeInt(encodings[i]);
7997 test_encodeEnumerated(encodings[i]);
7998 test_decodeEnumerated(encodings[i]);
7999 test_encodeFiletime(encodings[i]);
8000 test_decodeFiletime(encodings[i]);
8001 test_encodeName(encodings[i]);
8002 test_decodeName(encodings[i]);
8003 test_encodeUnicodeName(encodings[i]);
8004 test_decodeUnicodeName(encodings[i]);
8005 test_encodeNameValue(encodings[i]);
8006 test_decodeNameValue(encodings[i]);
8007 test_encodeUnicodeNameValue(encodings[i]);
8008 test_decodeUnicodeNameValue(encodings[i]);
8009 test_encodeAltName(encodings[i]);
8010 test_decodeAltName(encodings[i]);
8011 test_encodeOctets(encodings[i]);
8012 test_decodeOctets(encodings[i]);
8013 test_encodeBits(encodings[i]);
8014 test_decodeBits(encodings[i]);
8015 test_encodeBasicConstraints(encodings[i]);
8016 test_decodeBasicConstraints(encodings[i]);
8017 test_encodeRsaPublicKey(encodings[i]);
8018 test_decodeRsaPublicKey(encodings[i]);
8019 test_encodeSequenceOfAny(encodings[i]);
8020 test_decodeSequenceOfAny(encodings[i]);
8021 test_encodeExtensions(encodings[i]);
8022 test_decodeExtensions(encodings[i]);
8023 test_encodePublicKeyInfo(encodings[i]);
8024 test_decodePublicKeyInfo(encodings[i]);
8025 test_encodeCertToBeSigned(encodings[i]);
8026 test_decodeCertToBeSigned(encodings[i]);
8027 test_encodeCert(encodings[i]);
8028 test_decodeCert(encodings[i]);
8029 test_encodeCRLDistPoints(encodings[i]);
8030 test_decodeCRLDistPoints(encodings[i]);
8031 test_encodeCRLIssuingDistPoint(encodings[i]);
8032 test_decodeCRLIssuingDistPoint(encodings[i]);
8033 test_encodeCRLToBeSigned(encodings[i]);
8034 test_decodeCRLToBeSigned(encodings[i]);
8035 test_encodeEnhancedKeyUsage(encodings[i]);
8036 test_decodeEnhancedKeyUsage(encodings[i]);
8037 test_encodeAuthorityKeyId(encodings[i]);
8038 test_decodeAuthorityKeyId(encodings[i]);
8039 test_encodeAuthorityKeyId2(encodings[i]);
8040 test_decodeAuthorityKeyId2(encodings[i]);
8041 test_encodeAuthorityInfoAccess(encodings[i]);
8042 test_decodeAuthorityInfoAccess(encodings[i]);
8043 test_encodeCTL(encodings[i]);
8044 test_decodeCTL(encodings[i]);
8045 test_encodePKCSContentInfo(encodings[i]);
8046 test_decodePKCSContentInfo(encodings[i]);
8047 test_encodePKCSAttribute(encodings[i]);
8048 test_decodePKCSAttribute(encodings[i]);
8049 test_encodePKCSAttributes(encodings[i]);
8050 test_decodePKCSAttributes(encodings[i]);
8051 test_encodePKCSSMimeCapabilities(encodings[i]);
8052 test_decodePKCSSMimeCapabilities(encodings[i]);
8053 test_encodePKCSSignerInfo(encodings[i]);
8054 test_decodePKCSSignerInfo(encodings[i]);
8055 test_encodeCMSSignerInfo(encodings[i]);
8056 test_decodeCMSSignerInfo(encodings[i]);
8057 test_encodeNameConstraints(encodings[i]);
8058 test_decodeNameConstraints(encodings[i]);
8059 test_encodePolicyQualifierUserNotice(encodings[i]);
8060 test_decodePolicyQualifierUserNotice(encodings[i]);
8061 test_encodeCertPolicies(encodings[i]);
8062 test_decodeCertPolicies(encodings[i]);
8063 test_encodeCertPolicyMappings(encodings[i]);
8064 test_decodeCertPolicyMappings(encodings[i]);
8065 test_encodeCertPolicyConstraints(encodings[i]);
8066 test_decodeCertPolicyConstraints(encodings[i]);
8067 }
8068 testPortPublicKeyInfo();
8069 }