2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx
4 * Copyright 2005 Juan Lang
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/test.h"
35 static const BYTE bin1[] = {0x02,0x01,0x01};
36 static const BYTE bin2[] = {0x02,0x01,0x7f};
37 static const BYTE bin3[] = {0x02,0x02,0x00,0x80};
38 static const BYTE bin4[] = {0x02,0x02,0x01,0x00};
39 static const BYTE bin5[] = {0x02,0x01,0x80};
40 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f};
41 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d};
43 static const struct encodedInt ints[] = {
60 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
61 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
62 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
64 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
65 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
66 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0};
68 static const struct encodedBigInt bigInts[] = {
69 { bin8, bin9, bin10 },
70 { bin11, bin12, bin13 },
73 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
74 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0};
75 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0};
76 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0};
78 /* Decoded is the same as original, so don't bother storing a separate copy */
79 static const struct encodedBigInt bigUInts[] = {
80 { bin14, bin15, NULL },
81 { bin16, bin17, NULL },
84 static void test_encodeInt(DWORD dwEncoding)
89 CRYPT_INTEGER_BLOB blob;
92 /* CryptEncodeObjectEx with NULL bufSize crashes..
93 ret = CryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
96 /* check bogus encoding */
97 ret = CryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL,
99 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
100 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
101 /* check with NULL integer buffer. Windows XP incorrectly returns an
104 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL,
106 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
107 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
108 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
110 /* encode as normal integer */
111 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0,
112 NULL, NULL, &bufSize);
113 ok(ret, "Expected success, got %ld\n", GetLastError());
114 ret = CryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val,
115 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
116 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
119 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
121 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
122 buf[1], ints[i].encoded[1]);
123 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
124 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
127 /* encode as multibyte integer */
128 blob.cbData = sizeof(ints[i].val);
129 blob.pbData = (BYTE *)&ints[i].val;
130 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
131 0, NULL, NULL, &bufSize);
132 ok(ret, "Expected success, got %ld\n", GetLastError());
133 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
134 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
135 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
138 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
140 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n",
141 buf[1], ints[i].encoded[1]);
142 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1),
143 "Encoded value of 0x%08x didn't match expected\n", ints[i].val);
147 /* encode a couple bigger ints, just to show it's little-endian and leading
148 * sign bytes are dropped
150 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
152 blob.cbData = strlen((const char*)bigInts[i].val);
153 blob.pbData = (BYTE *)bigInts[i].val;
154 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
155 0, NULL, NULL, &bufSize);
156 ok(ret, "Expected success, got %ld\n", GetLastError());
157 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob,
158 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
159 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
162 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
164 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n",
165 buf[1], bigInts[i].encoded[1]);
166 ok(!memcmp(buf + 1, bigInts[i].encoded + 1,
167 bigInts[i].encoded[1] + 1),
168 "Encoded value didn't match expected\n");
172 /* and, encode some uints */
173 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
175 blob.cbData = strlen((const char*)bigUInts[i].val);
176 blob.pbData = (BYTE*)bigUInts[i].val;
177 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
178 0, NULL, NULL, &bufSize);
179 ok(ret, "Expected success, got %ld\n", GetLastError());
180 ret = CryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob,
181 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
182 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
185 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n",
187 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n",
188 buf[1], bigUInts[i].encoded[1]);
189 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1,
190 bigUInts[i].encoded[1] + 1),
191 "Encoded value didn't match expected\n");
197 static void test_decodeInt(DWORD dwEncoding)
199 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff };
200 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' };
201 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 };
202 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 };
208 /* CryptDecodeObjectEx with NULL bufSize crashes..
209 ret = CryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded,
210 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL);
212 /* check bogus encoding */
213 ret = CryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded,
214 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize);
215 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
216 "Expected ERROR_FILE_NOT_FOUND, got %ld\n", GetLastError());
217 /* check with NULL integer buffer */
218 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL,
220 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
221 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
222 /* check with a valid, but too large, integer */
223 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2,
224 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
225 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
226 "Expected CRYPT_E_ASN1_LARGE, got %ld\n", GetLastError());
227 /* check with a DER-encoded string */
228 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2,
229 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
230 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
231 "Expected CRYPT_E_ASN1_BADTAG, got %ld\n", GetLastError());
232 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
234 /* When the output buffer is NULL, this always succeeds */
235 SetLastError(0xdeadbeef);
236 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
237 (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL,
239 ok(ret && GetLastError() == NOERROR,
240 "Expected success and NOERROR, got %ld\n", GetLastError());
241 ret = CryptDecodeObjectEx(dwEncoding, X509_INTEGER,
242 (BYTE *)ints[i].encoded, ints[i].encoded[1] + 2,
243 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
244 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
245 ok(bufSize == sizeof(int), "Expected size %d, got %ld\n", sizeof(int),
247 ok(buf != NULL, "Expected allocated buffer\n");
250 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n",
251 ints[i].val, *(int *)buf);
255 for (i = 0; i < sizeof(bigInts) / sizeof(bigInts[0]); i++)
257 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
258 (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL,
260 ok(ret && GetLastError() == NOERROR,
261 "Expected success and NOERROR, got %ld\n", GetLastError());
262 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER,
263 (BYTE *)bigInts[i].encoded, bigInts[i].encoded[1] + 2,
264 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
265 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
266 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB),
267 "Expected size at least %d, got %ld\n", sizeof(CRYPT_INTEGER_BLOB),
269 ok(buf != NULL, "Expected allocated buffer\n");
272 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
274 ok(blob->cbData == strlen((const char*)bigInts[i].decoded),
275 "Expected len %d, got %ld\n", strlen((const char*)bigInts[i].decoded),
277 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData),
278 "Unexpected value\n");
282 for (i = 0; i < sizeof(bigUInts) / sizeof(bigUInts[0]); i++)
284 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
285 (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL,
287 ok(ret && GetLastError() == NOERROR,
288 "Expected success and NOERROR, got %ld\n", GetLastError());
289 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT,
290 (BYTE *)bigUInts[i].encoded, bigUInts[i].encoded[1] + 2,
291 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
292 ok(ret, "CryptDecodeObjectEx failed: %ld\n", GetLastError());
293 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB),
294 "Expected size at least %d, got %ld\n", sizeof(CRYPT_INTEGER_BLOB),
296 ok(buf != NULL, "Expected allocated buffer\n");
299 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf;
301 ok(blob->cbData == strlen((const char*)bigUInts[i].val),
302 "Expected len %d, got %ld\n", strlen((const char*)bigUInts[i].val),
304 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData),
305 "Unexpected value\n");
309 /* Decode the value 1 with long-form length */
310 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm,
311 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
312 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
315 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf);
318 /* Try to decode some bogus large items */
319 /* The buffer size is smaller than the encoded length, so this should fail
320 * with CRYPT_E_ASN1_EOD if it's being decoded.
321 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit
322 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes.
323 * So this test unfortunately isn't useful.
324 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig,
325 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
326 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE,
327 "Expected CRYPT_E_ASN1_LARGE, got %08lx\n", GetLastError());
329 /* This will try to decode the buffer and overflow it, check that it's
332 ret = CryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus,
333 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
334 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
335 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
338 static const BYTE bin18[] = {0x0a,0x01,0x01};
339 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80};
341 /* These are always encoded unsigned, and aren't constrained to be any
344 static const struct encodedInt enums[] = {
349 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to
352 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED,
353 szOID_CRL_REASON_CODE };
355 static void test_encodeEnumerated(DWORD dwEncoding)
359 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
361 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
367 ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i],
368 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
370 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
374 "Got unexpected type %d for enumerated (expected 0xa)\n",
376 ok(buf[1] == enums[j].encoded[1],
377 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]);
378 ok(!memcmp(buf + 1, enums[j].encoded + 1,
379 enums[j].encoded[1] + 1),
380 "Encoded value of 0x%08x didn't match expected\n",
388 static void test_decodeEnumerated(DWORD dwEncoding)
392 for (i = 0; i < sizeof(enumeratedTypes) / sizeof(enumeratedTypes[0]); i++)
394 for (j = 0; j < sizeof(enums) / sizeof(enums[0]); j++)
397 DWORD bufSize = sizeof(int);
400 ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i],
401 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL,
402 (BYTE *)&val, &bufSize);
403 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
404 ok(bufSize == sizeof(int),
405 "Got unexpected size %ld for enumerated (expected %d)\n",
406 bufSize, sizeof(int));
407 ok(val == enums[j].val, "Unexpected value %d, expected %d\n",
413 struct encodedFiletime
416 const BYTE *encodedTime;
419 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType,
420 const struct encodedFiletime *time)
427 ret = SystemTimeToFileTime(&time->sysTime, &ft);
428 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
429 ret = CryptEncodeObjectEx(dwEncoding, structType, &ft,
430 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
431 /* years other than 1950-2050 are not allowed for encodings other than
432 * X509_CHOICE_OF_TIME.
434 if (structType == X509_CHOICE_OF_TIME ||
435 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
437 ok(ret, "CryptEncodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
439 ok(buf != NULL, "Expected an allocated buffer\n");
442 ok(buf[0] == time->encodedTime[0],
443 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0],
445 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %ld\n",
446 time->encodedTime[1], bufSize);
447 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]),
448 "Got unexpected value for time encoding\n");
453 ok(!ret && GetLastError() == CRYPT_E_BAD_ENCODE,
454 "Expected CRYPT_E_BAD_ENCODE, got 0x%08lx\n", GetLastError());
457 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType,
458 const struct encodedFiletime *time)
460 FILETIME ft1 = { 0 }, ft2 = { 0 };
461 DWORD size = sizeof(ft2);
464 ret = SystemTimeToFileTime(&time->sysTime, &ft1);
465 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
466 ret = CryptDecodeObjectEx(dwEncoding, structType, time->encodedTime,
467 time->encodedTime[1] + 2, 0, NULL, &ft2, &size);
468 /* years other than 1950-2050 are not allowed for encodings other than
469 * X509_CHOICE_OF_TIME.
471 if (structType == X509_CHOICE_OF_TIME ||
472 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050))
474 ok(ret, "CryptDecodeObjectEx failed: %ld (0x%08lx)\n", GetLastError(),
476 ok(!memcmp(&ft1, &ft2, sizeof(ft1)),
477 "Got unexpected value for time decoding\n");
480 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
481 "Expected CRYPT_E_ASN1_BADTAG, got 0x%08lx\n", GetLastError());
484 static const BYTE bin20[] = {
485 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'};
486 static const BYTE bin21[] = {
487 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
488 static const BYTE bin22[] = {
489 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'};
491 static const struct encodedFiletime times[] = {
492 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 },
493 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 },
494 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 },
497 static void test_encodeFiletime(DWORD dwEncoding)
501 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
503 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
504 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
505 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, ×[i]);
509 static const BYTE bin23[] = {
510 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'};
511 static const BYTE bin24[] = {
512 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'};
513 static const BYTE bin25[] = {
514 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'};
515 static const BYTE bin26[] = {
516 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'};
517 static const BYTE bin27[] = {
518 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'};
519 static const BYTE bin28[] = {
520 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'};
521 static const BYTE bin29[] = {
522 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'};
523 static const BYTE bin30[] = {
524 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'};
525 static const BYTE bin31[] = {
526 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'};
527 static const BYTE bin32[] = {
528 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'};
529 static const BYTE bin33[] = {
530 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'};
531 static const BYTE bin34[] = {
532 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'};
533 static const BYTE bin35[] = {
534 0x17,0x08, '4','5','0','6','0','6','1','6'};
535 static const BYTE bin36[] = {
536 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'};
537 static const BYTE bin37[] = {
538 0x18,0x04, '2','1','4','5'};
539 static const BYTE bin38[] = {
540 0x18,0x08, '2','1','4','5','0','6','0','6'};
542 static void test_decodeFiletime(DWORD dwEncoding)
544 static const struct encodedFiletime otherTimes[] = {
545 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 },
546 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 },
547 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 },
548 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 },
549 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 },
550 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 },
551 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 },
552 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 },
553 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 },
554 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 },
555 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 },
556 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 },
558 /* An oddball case that succeeds in Windows, but doesn't seem correct
559 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" },
561 static const unsigned char *bogusTimes[] = {
562 /* oddly, this succeeds on Windows, with year 2765
563 "\x18" "\x0f" "21r50606161000Z",
571 FILETIME ft1 = { 0 }, ft2 = { 0 };
574 /* Check bogus length with non-NULL buffer */
575 ret = SystemTimeToFileTime(×[0].sysTime, &ft1);
576 ok(ret, "SystemTimeToFileTime failed: %ld\n", GetLastError());
578 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
579 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size);
580 ok(!ret && GetLastError() == ERROR_MORE_DATA,
581 "Expected ERROR_MORE_DATA, got %ld\n", GetLastError());
583 for (i = 0; i < sizeof(times) / sizeof(times[0]); i++)
585 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]);
586 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, ×[i]);
587 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, ×[i]);
589 for (i = 0; i < sizeof(otherTimes) / sizeof(otherTimes[0]); i++)
591 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]);
592 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]);
593 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]);
595 for (i = 0; i < sizeof(bogusTimes) / sizeof(bogusTimes[0]); i++)
598 ret = CryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME,
599 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size);
600 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
601 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
611 static const char commonName[] = "Juan Lang";
612 static const char surName[] = "Lang";
613 static const char bogusIA5[] = "\x80";
614 static const char bogusPrintable[] = "~";
615 static const char bogusNumeric[] = "A";
616 static const unsigned char bin39[] = {
617 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
618 static const unsigned char bin40[] = {
619 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x16,0x0a,'J','u','a','n',' ','L','a','n','g',0};
620 static const unsigned char bin41[] = {
621 0x30,0x10,0x31,0x0e,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x16,0x05,'L','a','n','g',0};
622 static const unsigned char bin42[] = {
623 0x30,0x12,0x31,0x10,0x30,0x0e,0x06,0x00,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0};
624 static const unsigned char bin43[] = {
625 0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x03,0x16,0x02,0x80,0};
626 static const unsigned char bin44[] = {
627 0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x03,0x13,0x02,0x7e,0};
628 static const unsigned char bin45[] = {
629 0x30,0x0d,0x31,0x0b,0x30,0x09,0x06,0x03,0x55,0x04,0x03,0x12,0x02,0x41,0};
630 static const struct EncodedName names[] = {
631 { { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING,
632 { sizeof(commonName), (BYTE *)commonName } }, bin39 },
633 { { szOID_COMMON_NAME, CERT_RDN_IA5_STRING,
634 { sizeof(commonName), (BYTE *)commonName } }, bin40 },
635 { { szOID_SUR_NAME, CERT_RDN_IA5_STRING,
636 { sizeof(surName), (BYTE *)surName } }, bin41 },
637 { { NULL, CERT_RDN_PRINTABLE_STRING,
638 { sizeof(commonName), (BYTE *)commonName } }, bin42 },
639 /* The following test isn't a very good one, because it doesn't encode any
640 * Japanese characters. I'm leaving it out for now.
641 { { szOID_COMMON_NAME, CERT_RDN_T61_STRING,
642 { sizeof(commonName), (BYTE *)commonName } },
643 "\x30\x15\x31\x13\x30\x11\x06\x03\x55\x04\x03\x14\x0aJuan Lang" },
645 /* The following tests succeed under Windows, but really should fail,
646 * they contain characters that are illegal for the encoding. I'm
647 * including them to justify my lazy encoding.
649 { { szOID_COMMON_NAME, CERT_RDN_IA5_STRING,
650 { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin43 },
651 { { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING,
652 { sizeof(bogusPrintable), (BYTE *)bogusPrintable } }, bin44 },
653 { { szOID_COMMON_NAME, CERT_RDN_NUMERIC_STRING,
654 { sizeof(bogusNumeric), (BYTE *)bogusNumeric } }, bin45 },
657 static const BYTE emptySequence[] = { 0x30, 0 };
658 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 };
659 static const BYTE twoRDNs[] = {
660 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04,
661 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03,
662 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0};
664 static const BYTE us[] = { 0x55, 0x53 };
665 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f,
667 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70,
668 0x6f, 0x6c, 0x69, 0x73 };
669 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61,
670 0x76, 0x65, 0x72, 0x73 };
671 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76,
672 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 };
673 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f,
675 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64,
676 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d };
678 #define _blob_of(arr) { sizeof(arr), (LPBYTE)arr }
679 const CERT_RDN_ATTR rdnAttrs[] = {
680 { "2.5.4.6", CERT_RDN_PRINTABLE_STRING, _blob_of(us) },
681 { "2.5.4.8", CERT_RDN_PRINTABLE_STRING, _blob_of(minnesota) },
682 { "2.5.4.7", CERT_RDN_PRINTABLE_STRING, _blob_of(minneapolis) },
683 { "2.5.4.10", CERT_RDN_PRINTABLE_STRING, _blob_of(codeweavers) },
684 { "2.5.4.11", CERT_RDN_PRINTABLE_STRING, _blob_of(wine) },
685 { "2.5.4.3", CERT_RDN_PRINTABLE_STRING, _blob_of(localhostAttr) },
686 { "1.2.840.113549.1.9.1", CERT_RDN_IA5_STRING, _blob_of(aric) },
688 const CERT_RDN_ATTR decodedRdnAttrs[] = {
689 { "2.5.4.6", CERT_RDN_PRINTABLE_STRING, _blob_of(us) },
690 { "2.5.4.3", CERT_RDN_PRINTABLE_STRING, _blob_of(localhostAttr) },
691 { "2.5.4.8", CERT_RDN_PRINTABLE_STRING, _blob_of(minnesota) },
692 { "2.5.4.7", CERT_RDN_PRINTABLE_STRING, _blob_of(minneapolis) },
693 { "2.5.4.10", CERT_RDN_PRINTABLE_STRING, _blob_of(codeweavers) },
694 { "2.5.4.11", CERT_RDN_PRINTABLE_STRING, _blob_of(wine) },
695 { "1.2.840.113549.1.9.1", CERT_RDN_IA5_STRING, _blob_of(aric) },
699 static const BYTE encodedRDNAttrs[] = {
700 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55,
701 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68,
702 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e,
703 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69,
704 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a,
705 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06,
706 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c,
707 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,
708 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65,
709 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d
712 static void test_encodeName(DWORD dwEncoding)
714 CERT_RDN_ATTR attrs[2];
721 /* Test with NULL pvStructInfo */
722 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
723 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
724 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
725 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
726 /* Test with empty CERT_NAME_INFO */
729 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
730 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
731 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
734 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)),
735 "Got unexpected encoding for empty name\n");
738 /* Test with bogus CERT_RDN */
740 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
741 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
742 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
743 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
744 /* Test with empty CERT_RDN */
746 rdn.rgRDNAttr = NULL;
749 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
750 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
751 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
754 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
755 "Got unexpected encoding for empty RDN array\n");
758 /* Test with bogus attr array */
760 rdn.rgRDNAttr = NULL;
761 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
762 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
763 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
764 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
765 /* oddly, a bogus OID is accepted by Windows XP; not testing.
766 attrs[0].pszObjId = "bogus";
767 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
768 attrs[0].Value.cbData = sizeof(commonName);
769 attrs[0].Value.pbData = (BYTE *)commonName;
771 rdn.rgRDNAttr = attrs;
772 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
773 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
774 ok(!ret, "Expected failure, got success\n");
776 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
777 * the encoded attributes to be swapped.
779 attrs[0].pszObjId = szOID_COMMON_NAME;
780 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
781 attrs[0].Value.cbData = sizeof(commonName);
782 attrs[0].Value.pbData = (BYTE *)commonName;
783 attrs[1].pszObjId = szOID_SUR_NAME;
784 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
785 attrs[1].Value.cbData = sizeof(surName);
786 attrs[1].Value.pbData = (BYTE *)surName;
788 rdn.rgRDNAttr = attrs;
789 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
790 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
791 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
794 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
795 "Got unexpected encoding for two RDN array\n");
798 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
800 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
801 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
802 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
803 ok(!ret && GetLastError() == E_INVALIDARG,
804 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
805 for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
808 rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
809 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
810 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
811 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
814 ok(size == names[i].encoded[1] + 2, "Expected size %d, got %ld\n",
815 names[i].encoded[1] + 2, size);
816 ok(!memcmp(buf, names[i].encoded, names[i].encoded[1] + 2),
817 "Got unexpected encoding\n");
821 /* Test a more complex name */
822 rdn.cRDNAttr = sizeof(rdnAttrs) / sizeof(rdnAttrs[0]);
823 rdn.rgRDNAttr = (PCERT_RDN_ATTR)rdnAttrs;
828 ret = CryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info,
829 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size);
830 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
833 ok(size == sizeof(encodedRDNAttrs), "Expected size %d, got %ld\n",
834 sizeof(encodedRDNAttrs), size);
835 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n");
840 static void compareRDNAttrs(const CERT_RDN_ATTR *expected,
841 const CERT_RDN_ATTR *got)
843 if (expected->pszObjId && strlen(expected->pszObjId))
845 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n",
849 ok(!strcmp(got->pszObjId, expected->pszObjId),
850 "Got unexpected OID %s, expected %s\n", got->pszObjId,
854 ok(got->dwValueType == expected->dwValueType,
855 "Expected string type %ld, got %ld\n", expected->dwValueType,
857 ok(got->Value.cbData == expected->Value.cbData,
858 "Unexpected data size, got %ld, expected %ld\n", got->Value.cbData,
859 expected->Value.cbData);
860 if (got->Value.cbData && got->Value.pbData)
861 ok(!memcmp(got->Value.pbData, expected->Value.pbData,
862 min(got->Value.cbData, expected->Value.cbData)), "Unexpected value\n");
865 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got)
867 ok(got->cRDNAttr == expected->cRDNAttr,
868 "Expected %ld RDN attrs, got %ld\n", expected->cRDNAttr, got->cRDNAttr);
873 for (i = 0; i < got->cRDNAttr; i++)
874 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]);
878 static void compareNames(const CERT_NAME_INFO *expected,
879 const CERT_NAME_INFO *got)
881 ok(got->cRDN == expected->cRDN, "Expected %ld RDNs, got %ld\n",
882 expected->cRDN, got->cRDN);
887 for (i = 0; i < got->cRDN; i++)
888 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]);
892 static void test_decodeName(DWORD dwEncoding)
899 CERT_NAME_INFO info = { 1, &rdn };
901 for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
903 /* When the output buffer is NULL, this always succeeds */
904 SetLastError(0xdeadbeef);
905 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
906 names[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
907 ok(ret && GetLastError() == NOERROR,
908 "Expected success and NOERROR, got %08lx\n", GetLastError());
909 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
910 names[i].encoded[1] + 2,
911 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
912 (BYTE *)&buf, &bufSize);
913 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
915 rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
918 compareNames(&info, (CERT_NAME_INFO *)buf);
922 /* test empty name */
924 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence,
925 emptySequence[1] + 2,
926 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
927 (BYTE *)&buf, &bufSize);
928 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
929 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
930 * decoder works the same way, so only test the count.
934 ok(bufSize == sizeof(CERT_NAME_INFO),
935 "Expected bufSize %d, got %ld\n", sizeof(CERT_NAME_INFO), bufSize);
936 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
937 "Expected 0 RDNs in empty info, got %ld\n",
938 ((CERT_NAME_INFO *)buf)->cRDN);
943 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
945 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
946 (BYTE *)&buf, &bufSize);
947 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
950 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
952 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
953 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
954 "Got unexpected value for empty RDN\n");
957 /* test two RDN attrs */
959 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
961 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
962 (BYTE *)&buf, &bufSize);
963 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
966 CERT_RDN_ATTR attrs[] = {
967 { szOID_SUR_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
969 { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
970 (BYTE *)commonName } },
973 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
974 rdn.rgRDNAttr = attrs;
975 compareNames(&info, (CERT_NAME_INFO *)buf);
978 /* And, a slightly more complicated name */
981 ret = CryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs,
982 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize);
983 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
986 rdn.cRDNAttr = sizeof(decodedRdnAttrs) / sizeof(decodedRdnAttrs[0]);
987 rdn.rgRDNAttr = (PCERT_RDN_ATTR)decodedRdnAttrs;
988 compareNames(&info, (CERT_NAME_INFO *)buf);
993 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
994 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
995 'h','q','.','o','r','g',0 };
996 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
997 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
999 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
1001 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
1002 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
1003 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
1004 static const BYTE localhost[] = { 127, 0, 0, 1 };
1005 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
1008 static void test_encodeAltName(DWORD dwEncoding)
1010 CERT_ALT_NAME_INFO info = { 0 };
1011 CERT_ALT_NAME_ENTRY entry = { 0 };
1016 /* Test with empty info */
1017 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1018 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1021 ok(size == sizeof(emptySequence), "Expected size %d, got %ld\n",
1022 sizeof(emptySequence), size);
1023 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n");
1026 /* Test with an empty entry */
1028 info.rgAltEntry = &entry;
1029 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1030 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1031 ok(!ret && GetLastError() == E_INVALIDARG,
1032 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1033 /* Test with an empty pointer */
1034 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
1035 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1036 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1039 ok(size == sizeof(emptyURL), "Expected size %d, got %ld\n",
1040 sizeof(emptyURL), size);
1041 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
1044 /* Test with a real URL */
1045 U(entry).pwszURL = (LPWSTR)url;
1046 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1047 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1050 ok(size == sizeof(encodedURL), "Expected size %d, got %ld\n",
1051 sizeof(encodedURL), size);
1052 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
1055 /* Now with the URL containing an invalid IA5 char */
1056 U(entry).pwszURL = (LPWSTR)nihongoURL;
1057 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1058 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1059 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
1060 "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
1061 /* The first invalid character is at index 7 */
1062 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
1063 "Expected invalid char at index 7, got %ld\n",
1064 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
1065 /* Now with the URL missing a scheme */
1066 U(entry).pwszURL = (LPWSTR)dnsName;
1067 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1068 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1069 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1072 /* This succeeds, but it shouldn't, so don't worry about conforming */
1075 /* Now with a DNS name */
1076 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
1077 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1078 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1079 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1082 ok(size == sizeof(encodedDnsName), "Expected size %d, got %ld\n",
1083 sizeof(encodedDnsName), size);
1084 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1087 /* Test with an IP address */
1088 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1089 U(entry).IPAddress.cbData = sizeof(localhost);
1090 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1091 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1092 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1095 ok(size == sizeof(encodedIPAddr), "Expected size %d, got %ld\n",
1096 sizeof(encodedIPAddr), size);
1097 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1102 static void test_decodeAltName(DWORD dwEncoding)
1104 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1106 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1111 CERT_ALT_NAME_INFO *info;
1113 /* Test some bogus ones first */
1114 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1115 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1116 NULL, (BYTE *)&buf, &bufSize);
1117 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1118 "Expected CRYPT_E_ASN1_BADTAG, got %08lx\n", GetLastError());
1119 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1120 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1122 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1123 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1124 /* Now expected cases */
1125 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence,
1126 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1128 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1131 info = (CERT_ALT_NAME_INFO *)buf;
1133 ok(info->cAltEntry == 0, "Expected 0 entries, got %ld\n",
1137 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1138 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1140 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1143 info = (CERT_ALT_NAME_INFO *)buf;
1145 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1147 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1148 "Expected CERT_ALT_NAME_URL, got %ld\n",
1149 info->rgAltEntry[0].dwAltNameChoice);
1150 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1151 "Expected empty URL\n");
1154 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1155 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1157 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1160 info = (CERT_ALT_NAME_INFO *)buf;
1162 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1164 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1165 "Expected CERT_ALT_NAME_URL, got %ld\n",
1166 info->rgAltEntry[0].dwAltNameChoice);
1167 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1170 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1171 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1173 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1176 info = (CERT_ALT_NAME_INFO *)buf;
1178 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1180 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1181 "Expected CERT_ALT_NAME_DNS_NAME, got %ld\n",
1182 info->rgAltEntry[0].dwAltNameChoice);
1183 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1184 "Unexpected DNS name\n");
1187 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1188 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1190 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1193 info = (CERT_ALT_NAME_INFO *)buf;
1195 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1197 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1198 "Expected CERT_ALT_NAME_IP_ADDRESS, got %ld\n",
1199 info->rgAltEntry[0].dwAltNameChoice);
1200 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1201 "Unexpected IP address length %ld\n",
1202 U(info->rgAltEntry[0]).IPAddress.cbData);
1203 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1204 sizeof(localhost)), "Unexpected IP address value\n");
1209 struct encodedOctets
1212 const BYTE *encoded;
1215 static const unsigned char bin46[] = { 'h','i',0 };
1216 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1217 static const unsigned char bin48[] = {
1218 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1219 static const unsigned char bin49[] = {
1220 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1221 static const unsigned char bin50[] = { 0 };
1222 static const unsigned char bin51[] = { 0x04,0x00,0 };
1224 static const struct encodedOctets octets[] = {
1230 static void test_encodeOctets(DWORD dwEncoding)
1232 CRYPT_DATA_BLOB blob;
1235 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1241 blob.cbData = strlen((const char*)octets[i].val);
1242 blob.pbData = (BYTE*)octets[i].val;
1243 ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1244 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1245 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
1249 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1250 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1251 buf[1], octets[i].encoded[1]);
1252 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1253 octets[i].encoded[1] + 1), "Got unexpected value\n");
1259 static void test_decodeOctets(DWORD dwEncoding)
1263 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1269 ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1270 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1271 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1272 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1273 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1274 "Expected size >= %d, got %ld\n",
1275 sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1276 ok(buf != NULL, "Expected allocated buffer\n");
1279 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1282 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1283 "Unexpected value\n");
1289 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1294 const BYTE *encoded;
1296 const BYTE *decoded;
1299 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff };
1300 static const unsigned char bin53[] = { 0xff,0xff };
1301 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe };
1302 static const unsigned char bin55[] = { 0xff,0xfe };
1303 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe };
1304 static const unsigned char bin57[] = { 0xfe };
1305 static const unsigned char bin58[] = { 0x03,0x01,0x00 };
1307 static const struct encodedBits bits[] = {
1308 /* normal test cases */
1309 { 0, bin52, 2, bin53 },
1310 { 1, bin54, 2, bin55 },
1311 /* strange test case, showing cUnusedBits >= 8 is allowed */
1312 { 9, bin56, 1, bin57 },
1313 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1314 { 17, bin58, 0, NULL },
1317 static void test_encodeBits(DWORD dwEncoding)
1321 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1323 CRYPT_BIT_BLOB blob;
1328 blob.cbData = sizeof(bytesToEncode);
1329 blob.pbData = (BYTE *)bytesToEncode;
1330 blob.cUnusedBits = bits[i].cUnusedBits;
1331 ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1332 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1333 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1336 ok(bufSize == bits[i].encoded[1] + 2,
1337 "Got unexpected size %ld, expected %d\n", bufSize,
1338 bits[i].encoded[1] + 2);
1339 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1340 "Unexpected value\n");
1346 static void test_decodeBits(DWORD dwEncoding)
1348 static const BYTE ber[] = "\x03\x02\x01\xff";
1349 static const BYTE berDecoded = 0xfe;
1356 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1358 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1359 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1361 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1364 CRYPT_BIT_BLOB *blob;
1366 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1367 "Got unexpected size %ld, expected >= %ld\n", bufSize,
1368 sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded);
1369 blob = (CRYPT_BIT_BLOB *)buf;
1370 ok(blob->cbData == bits[i].cbDecoded,
1371 "Got unexpected length %ld, expected %ld\n", blob->cbData,
1373 if (blob->cbData && bits[i].cbDecoded)
1374 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1375 "Unexpected value\n");
1379 /* special case: check that something that's valid in BER but not in DER
1380 * decodes successfully
1382 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1383 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1384 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1387 CRYPT_BIT_BLOB *blob;
1389 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1390 "Got unexpected size %ld, expected >= %d\n", bufSize,
1391 sizeof(CRYPT_BIT_BLOB) + berDecoded);
1392 blob = (CRYPT_BIT_BLOB *)buf;
1393 ok(blob->cbData == sizeof(berDecoded),
1394 "Got unexpected length %ld, expected %d\n", blob->cbData,
1395 sizeof(berDecoded));
1397 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1404 CERT_BASIC_CONSTRAINTS2_INFO info;
1405 const BYTE *encoded;
1408 static const unsigned char bin59[] = { 0x30,0x00 };
1409 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff };
1410 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 };
1411 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1412 static const struct Constraints2 constraints2[] = {
1413 /* empty constraints */
1414 { { FALSE, FALSE, 0}, bin59 },
1416 { { TRUE, FALSE, 0}, bin60 },
1417 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1418 * but that's not the case
1420 { { FALSE, TRUE, 0}, bin61 },
1421 /* can be a CA and has path length constraints set */
1422 { { TRUE, TRUE, 1}, bin62 },
1425 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 };
1426 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11,
1427 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16,
1428 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93,
1429 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1430 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00,
1431 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26,
1432 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30,
1433 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19,
1434 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 };
1436 static void test_encodeBasicConstraints(DWORD dwEncoding)
1438 DWORD i, bufSize = 0;
1439 CERT_BASIC_CONSTRAINTS_INFO info;
1440 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName),
1441 (LPBYTE)encodedDomainName };
1445 /* First test with the simpler info2 */
1446 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1448 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1449 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1451 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1454 ok(bufSize == constraints2[i].encoded[1] + 2,
1455 "Expected %d bytes, got %ld\n", constraints2[i].encoded[1] + 2,
1457 ok(!memcmp(buf, constraints2[i].encoded,
1458 constraints2[i].encoded[1] + 2), "Unexpected value\n");
1462 /* Now test with more complex basic constraints */
1463 info.SubjectType.cbData = 0;
1464 info.fPathLenConstraint = FALSE;
1465 info.cSubtreesConstraint = 0;
1466 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1467 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1468 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1471 ok(bufSize == sizeof(emptyConstraint), "Expected %d bytes, got %ld\n",
1472 sizeof(emptyConstraint), bufSize);
1473 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)),
1474 "Unexpected value\n");
1477 /* None of the certs I examined had any subtree constraint, but I test one
1478 * anyway just in case.
1480 info.cSubtreesConstraint = 1;
1481 info.rgSubtreesConstraint = &nameBlob;
1482 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info,
1483 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1484 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1487 ok(bufSize == sizeof(constraintWithDomainName),
1488 "Expected %d bytes, got %ld\n", sizeof(constraintWithDomainName),
1490 ok(!memcmp(buf, constraintWithDomainName,
1491 sizeof(constraintWithDomainName)), "Unexpected value\n");
1494 /* FIXME: test encoding with subject type. */
1497 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 };
1499 static void test_decodeBasicConstraints(DWORD dwEncoding)
1501 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01,
1503 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1509 /* First test with simpler info2 */
1510 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1512 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1513 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1514 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1515 ok(ret, "CryptDecodeObjectEx failed for item %ld: %08lx\n", i,
1519 CERT_BASIC_CONSTRAINTS2_INFO *info =
1520 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1522 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1523 "Unexpected value for item %ld\n", i);
1527 /* Check with the order of encoded elements inverted */
1529 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1530 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1532 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1533 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1534 ok(!buf, "Expected buf to be set to NULL\n");
1535 /* Check with a non-DER bool */
1536 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1537 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1538 (BYTE *)&buf, &bufSize);
1539 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1542 CERT_BASIC_CONSTRAINTS2_INFO *info =
1543 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1545 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
1548 /* Check with a non-basic constraints value */
1549 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1550 names[0].encoded, names[0].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1551 (BYTE *)&buf, &bufSize);
1552 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1553 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1554 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */
1555 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
1556 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL,
1557 (BYTE *)&buf, &bufSize);
1558 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1561 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
1563 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
1564 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
1565 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n");
1568 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS,
1569 constraintWithDomainName, sizeof(constraintWithDomainName),
1570 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1571 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1574 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf;
1576 ok(info->SubjectType.cbData == 0, "Expected no subject type\n");
1577 ok(!info->fPathLenConstraint, "Expected no path length constraint\n");
1578 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n");
1579 if (info->cSubtreesConstraint && info->rgSubtreesConstraint)
1581 ok(info->rgSubtreesConstraint[0].cbData ==
1582 sizeof(encodedDomainName), "Expected %d bytes, got %ld\n",
1583 sizeof(encodedDomainName), info->rgSubtreesConstraint[0].cbData);
1584 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName,
1585 sizeof(encodedDomainName)), "Unexpected value\n");
1591 /* These are terrible public keys of course, I'm just testing encoding */
1592 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
1593 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
1594 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
1595 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
1596 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
1597 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1598 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
1599 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1601 struct EncodedRSAPubKey
1603 const BYTE *modulus;
1605 const BYTE *encoded;
1606 size_t decodedModulusLen;
1609 struct EncodedRSAPubKey rsaPubKeys[] = {
1610 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
1611 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
1612 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
1613 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
1616 static void test_encodeRsaPublicKey(DWORD dwEncoding)
1618 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
1619 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
1620 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
1623 DWORD bufSize = 0, i;
1625 /* Try with a bogus blob type */
1627 hdr->bVersion = CUR_BLOB_VERSION;
1629 hdr->aiKeyAlg = CALG_RSA_KEYX;
1630 rsaPubKey->magic = 0x31415352;
1631 rsaPubKey->bitlen = sizeof(modulus1) * 8;
1632 rsaPubKey->pubexp = 65537;
1633 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
1636 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1637 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1639 ok(!ret && GetLastError() == E_INVALIDARG,
1640 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
1641 /* Now with a bogus reserved field */
1642 hdr->bType = PUBLICKEYBLOB;
1644 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1645 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1649 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1650 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1651 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1654 /* Now with a bogus blob version */
1657 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1658 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1662 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1663 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1664 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1667 /* And with a bogus alg ID */
1668 hdr->bVersion = CUR_BLOB_VERSION;
1669 hdr->aiKeyAlg = CALG_DES;
1670 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1671 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1675 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1676 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1677 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1680 /* Check a couple of RSA-related OIDs */
1681 hdr->aiKeyAlg = CALG_RSA_KEYX;
1682 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
1683 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1684 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1685 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1686 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1687 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1688 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1689 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1690 /* Finally, all valid */
1691 hdr->aiKeyAlg = CALG_RSA_KEYX;
1692 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1694 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1695 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
1696 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1697 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1698 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1701 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
1702 "Expected size %d, got %ld\n", rsaPubKeys[i].encoded[1] + 2,
1704 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
1705 "Unexpected value\n");
1711 static void test_decodeRsaPublicKey(DWORD dwEncoding)
1718 /* Try with a bad length */
1719 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1720 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
1721 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1722 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1723 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", CRYPT_E_ASN1_EOD);
1724 /* Try with a couple of RSA-related OIDs */
1725 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
1726 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
1727 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1728 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1729 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1730 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1731 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
1732 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1733 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1734 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1735 /* Now try success cases */
1736 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1739 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1740 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
1741 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1742 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1745 BLOBHEADER *hdr = (BLOBHEADER *)buf;
1746 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
1748 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1749 rsaPubKeys[i].decodedModulusLen,
1750 "Expected size at least %d, got %ld\n",
1751 sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1752 rsaPubKeys[i].decodedModulusLen, bufSize);
1753 ok(hdr->bType == PUBLICKEYBLOB,
1754 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
1756 ok(hdr->bVersion == CUR_BLOB_VERSION,
1757 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
1758 CUR_BLOB_VERSION, hdr->bVersion);
1759 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
1761 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
1762 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
1763 ok(rsaPubKey->magic == 0x31415352,
1764 "Expected magic RSA1, got %08lx\n", rsaPubKey->magic);
1765 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
1766 "Expected bit len %d, got %ld\n",
1767 rsaPubKeys[i].decodedModulusLen * 8, rsaPubKey->bitlen);
1768 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %ld\n",
1770 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1771 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
1772 "Unexpected modulus\n");
1778 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
1779 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
1780 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1782 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
1783 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
1784 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
1785 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1787 static void test_encodeSequenceOfAny(DWORD dwEncoding)
1789 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
1790 CRYPT_SEQUENCE_OF_ANY seq;
1796 /* Encode a homogenous sequence */
1797 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
1799 blobs[i].cbData = ints[i].encoded[1] + 2;
1800 blobs[i].pbData = (BYTE *)ints[i].encoded;
1802 seq.cValue = sizeof(ints) / sizeof(ints[0]);
1803 seq.rgValue = blobs;
1805 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1806 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1807 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1810 ok(bufSize == sizeof(intSequence), "Expected %d bytes, got %ld\n",
1811 sizeof(intSequence), bufSize);
1812 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
1815 /* Change the type of the first element in the sequence, and give it
1818 blobs[0].cbData = times[0].encodedTime[1] + 2;
1819 blobs[0].pbData = (BYTE *)times[0].encodedTime;
1820 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1821 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1822 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1825 ok(bufSize == sizeof(mixedSequence), "Expected %d bytes, got %ld\n",
1826 sizeof(mixedSequence), bufSize);
1827 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
1828 "Unexpected value\n");
1833 static void test_decodeSequenceOfAny(DWORD dwEncoding)
1839 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
1840 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1841 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1844 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1847 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1848 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1850 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
1852 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
1853 "Expected %d bytes, got %ld\n", ints[i].encoded[1] + 2,
1854 seq->rgValue[i].cbData);
1855 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
1856 ints[i].encoded[1] + 2), "Unexpected value\n");
1860 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
1861 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1863 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1866 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1868 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1869 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1871 /* Just check the first element since it's all that changed */
1872 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
1873 "Expected %d bytes, got %ld\n", times[0].encodedTime[1] + 2,
1874 seq->rgValue[0].cbData);
1875 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
1876 times[0].encodedTime[1] + 2), "Unexpected value\n");
1881 struct encodedExtensions
1883 CERT_EXTENSIONS exts;
1884 const BYTE *encoded;
1887 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1888 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1890 static CERT_EXTENSION criticalExt =
1891 { szOID_BASIC_CONSTRAINTS2, TRUE, { 8, crit_ext_data } };
1892 static CERT_EXTENSION nonCriticalExt =
1893 { szOID_BASIC_CONSTRAINTS2, FALSE, { 8, noncrit_ext_data } };
1895 static const BYTE ext0[] = { 0x30,0x00 };
1896 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
1897 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1898 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
1899 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1901 static const struct encodedExtensions exts[] = {
1902 { { 0, NULL }, ext0 },
1903 { { 1, &criticalExt }, ext1 },
1904 { { 1, &nonCriticalExt }, ext2 },
1907 static void test_encodeExtensions(DWORD dwEncoding)
1911 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1917 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
1918 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1919 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1922 ok(bufSize == exts[i].encoded[1] + 2,
1923 "Expected %d bytes, got %ld\n", exts[i].encoded[1] + 2, bufSize);
1924 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
1925 "Unexpected value\n");
1931 static void test_decodeExtensions(DWORD dwEncoding)
1935 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1941 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
1942 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1943 NULL, (BYTE *)&buf, &bufSize);
1944 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1947 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
1950 ok(ext->cExtension == exts[i].exts.cExtension,
1951 "Expected %ld extensions, see %ld\n", exts[i].exts.cExtension,
1953 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
1955 ok(!strcmp(ext->rgExtension[j].pszObjId,
1956 exts[i].exts.rgExtension[j].pszObjId),
1957 "Expected OID %s, got %s\n",
1958 exts[i].exts.rgExtension[j].pszObjId,
1959 ext->rgExtension[j].pszObjId);
1960 ok(!memcmp(ext->rgExtension[j].Value.pbData,
1961 exts[i].exts.rgExtension[j].Value.pbData,
1962 exts[i].exts.rgExtension[j].Value.cbData),
1963 "Unexpected value\n");
1970 /* MS encodes public key info with a NULL if the algorithm identifier's
1971 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
1972 * it encodes them by omitting the algorithm parameters. This latter approach
1973 * seems more correct, so accept either form.
1975 struct encodedPublicKey
1977 CERT_PUBLIC_KEY_INFO info;
1978 const BYTE *encoded;
1979 const BYTE *encodedNoNull;
1980 CERT_PUBLIC_KEY_INFO decoded;
1983 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
1985 static const BYTE params[] = { 0x02, 0x01, 0x01 };
1987 static const unsigned char bin64[] = {
1988 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00};
1989 static const unsigned char bin65[] = {
1990 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00};
1991 static const unsigned char bin66[] = {
1992 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00};
1993 static const unsigned char bin67[] = {
1994 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00};
1995 static const unsigned char bin68[] = {
1996 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
1997 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
1998 static const unsigned char bin69[] = {
1999 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
2000 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f};
2001 static const unsigned char bin70[] = {
2002 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2003 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2005 static const unsigned char bin71[] = {
2006 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
2007 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
2009 static unsigned char bin72[] = { 0x05,0x00};
2011 static const struct encodedPublicKey pubKeys[] = {
2012 /* with a bogus OID */
2013 { { { "1.2.3", { 0, NULL } }, { 0, NULL, 0 } },
2015 { { "1.2.3", { 2, bin72 } }, { 0, NULL, 0 } } },
2016 /* some normal keys */
2017 { { { szOID_RSA, { 0, NULL } }, { 0, NULL, 0} },
2019 { { szOID_RSA, { 2, bin72 } }, { 0, NULL, 0 } } },
2020 { { { szOID_RSA, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
2022 { { szOID_RSA, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
2023 /* with add'l parameters--note they must be DER-encoded */
2024 { { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2025 (BYTE *)aKey, 0 } },
2027 { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
2028 (BYTE *)aKey, 0 } } },
2031 static void test_encodePublicKeyInfo(DWORD dwEncoding)
2035 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2041 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2042 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
2044 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2047 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
2048 bufSize == pubKeys[i].encodedNoNull[1] + 2,
2049 "Expected %d or %d bytes, got %ld\n", pubKeys[i].encoded[1] + 2,
2050 pubKeys[i].encodedNoNull[1] + 2, bufSize);
2051 if (bufSize == pubKeys[i].encoded[1] + 2)
2052 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
2053 "Unexpected value\n");
2054 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
2055 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
2056 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
2062 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
2063 const CERT_PUBLIC_KEY_INFO *got)
2065 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
2066 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
2067 got->Algorithm.pszObjId);
2068 ok(expected->Algorithm.Parameters.cbData ==
2069 got->Algorithm.Parameters.cbData,
2070 "Expected parameters of %ld bytes, got %ld\n",
2071 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
2072 if (expected->Algorithm.Parameters.cbData)
2073 ok(!memcmp(expected->Algorithm.Parameters.pbData,
2074 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
2075 "Unexpected algorithm parameters\n");
2076 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
2077 "Expected public key of %ld bytes, got %ld\n",
2078 expected->PublicKey.cbData, got->PublicKey.cbData);
2079 if (expected->PublicKey.cbData)
2080 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
2081 got->PublicKey.cbData), "Unexpected public key value\n");
2084 static void test_decodePublicKeyInfo(DWORD dwEncoding)
2086 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06,
2087 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03,
2088 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
2089 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f };
2095 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
2097 /* The NULL form decodes to the decoded member */
2098 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2099 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2100 NULL, (BYTE *)&buf, &bufSize);
2101 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2104 comparePublicKeyInfo(&pubKeys[i].decoded,
2105 (CERT_PUBLIC_KEY_INFO *)buf);
2108 /* The non-NULL form decodes to the original */
2109 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2110 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
2111 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2112 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2115 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
2119 /* Test with bogus (not valid DER) parameters */
2120 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
2121 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2122 NULL, (BYTE *)&buf, &bufSize);
2123 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2124 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2127 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
2128 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2129 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
2130 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
2131 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2132 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
2133 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2134 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2135 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2136 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2137 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
2138 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2139 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
2140 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2141 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
2142 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
2143 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2144 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2145 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2146 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2147 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2148 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2149 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
2150 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
2151 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
2152 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2153 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
2154 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2155 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2156 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2157 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2158 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
2159 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
2160 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
2161 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
2162 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
2163 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
2164 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
2165 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2167 /* This is the encoded form of the printable string "Juan Lang" */
2168 static const BYTE encodedCommonName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11,
2169 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c,
2170 0x61, 0x6e, 0x67, 0x00 };
2171 static const BYTE serialNum[] = { 0x01 };
2173 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2178 CERT_INFO info = { 0 };
2180 /* Test with NULL pvStructInfo */
2181 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2182 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2183 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2184 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2185 /* Test with a V1 cert */
2186 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2187 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2188 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2191 ok(size == v1Cert[1] + 2, "Expected size %d, got %ld\n",
2192 v1Cert[1] + 2, size);
2193 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2197 info.dwVersion = CERT_V2;
2198 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2199 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2200 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2203 ok(size == sizeof(v2Cert), "Expected size %d, got %ld\n",
2204 sizeof(v2Cert), size);
2205 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2209 info.dwVersion = CERT_V3;
2210 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2211 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2212 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2215 ok(size == sizeof(v3Cert), "Expected size %d, got %ld\n",
2216 sizeof(v3Cert), size);
2217 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2220 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2221 * API doesn't prevent it)
2223 info.dwVersion = CERT_V1;
2224 info.cExtension = 1;
2225 info.rgExtension = &criticalExt;
2226 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2227 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2228 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2231 ok(size == sizeof(v1CertWithConstraints), "Expected size %d, got %ld\n",
2232 sizeof(v1CertWithConstraints), size);
2233 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2236 /* test v1 cert with a serial number */
2237 info.SerialNumber.cbData = sizeof(serialNum);
2238 info.SerialNumber.pbData = (BYTE *)serialNum;
2239 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2240 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2243 ok(size == sizeof(v1CertWithSerial), "Expected size %d, got %ld\n",
2244 sizeof(v1CertWithSerial), size);
2245 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2248 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2249 info.Issuer.cbData = sizeof(encodedCommonName);
2250 info.Issuer.pbData = (BYTE *)encodedCommonName;
2251 info.Subject.cbData = sizeof(encodedCommonName);
2252 info.Subject.pbData = (BYTE *)encodedCommonName;
2253 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2254 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2257 ok(size == sizeof(bigCert), "Expected size %d, got %ld\n",
2258 sizeof(bigCert), size);
2259 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2262 /* for now, I let more interesting tests be done for each subcomponent,
2263 * rather than retesting them all here.
2267 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2269 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2270 v1CertWithConstraints, v1CertWithSerial };
2275 /* Test with NULL pbEncoded */
2276 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2277 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2278 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2279 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
2280 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2281 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2282 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2283 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2284 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2285 * minimum a cert must have a non-zero serial number, an issuer, and a
2288 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2290 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2291 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2292 (BYTE *)&buf, &size);
2293 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2294 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2296 /* Now check with serial number, subject and issuer specified */
2297 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2298 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2299 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2302 CERT_INFO *info = (CERT_INFO *)buf;
2304 ok(size >= sizeof(CERT_INFO), "Expected size at least %d, got %ld\n",
2305 sizeof(CERT_INFO), size);
2306 ok(info->SerialNumber.cbData == 1,
2307 "Expected serial number size 1, got %ld\n", info->SerialNumber.cbData);
2308 ok(*info->SerialNumber.pbData == *serialNum,
2309 "Expected serial number %d, got %d\n", *serialNum,
2310 *info->SerialNumber.pbData);
2311 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2312 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2313 info->Issuer.cbData);
2314 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2315 "Unexpected issuer\n");
2316 ok(info->Subject.cbData == sizeof(encodedCommonName),
2317 "Expected subject of %d bytes, got %ld\n", sizeof(encodedCommonName),
2318 info->Subject.cbData);
2319 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2320 info->Subject.cbData), "Unexpected subject\n");
2325 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2328 static const BYTE signedBigCert[] = {
2329 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2330 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2331 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2332 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2333 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2334 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2335 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2336 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2337 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2338 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2339 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2340 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2342 static void test_encodeCert(DWORD dwEncoding)
2344 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
2345 * also that bigCert is a NULL-terminated string, so don't count its
2346 * last byte (otherwise the signed cert won't decode.)
2348 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2349 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2354 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2355 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2356 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2359 ok(bufSize == sizeof(signedBigCert), "Expected size %d, got %ld\n",
2360 sizeof(signedBigCert), bufSize);
2361 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2366 static void test_decodeCert(DWORD dwEncoding)
2372 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2373 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2374 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2377 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2379 ok(info->ToBeSigned.cbData == sizeof(bigCert),
2380 "Expected cert to be %d bytes, got %ld\n", sizeof(bigCert),
2381 info->ToBeSigned.cbData);
2382 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2383 "Unexpected cert\n");
2384 ok(info->Signature.cbData == sizeof(hash),
2385 "Expected signature size %d, got %ld\n", sizeof(hash),
2386 info->Signature.cbData);
2387 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2388 "Unexpected signature\n");
2393 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2394 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2395 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2396 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2397 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2399 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2400 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2401 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2402 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2403 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2404 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2405 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2406 0x2e, 0x6f, 0x72, 0x67 };
2407 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2408 CRL_REASON_AFFILIATION_CHANGED;
2410 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2412 CRL_DIST_POINTS_INFO info = { 0 };
2413 CRL_DIST_POINT point = { { 0 } };
2414 CERT_ALT_NAME_ENTRY entry = { 0 };
2419 /* Test with an empty info */
2420 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2421 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2422 ok(!ret && GetLastError() == E_INVALIDARG,
2423 "Expected E_INVALIDARG, got %08lx\n", GetLastError());
2424 /* Test with one empty dist point */
2425 info.cDistPoint = 1;
2426 info.rgDistPoint = &point;
2427 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2428 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2431 ok(size == sizeof(emptyDistPoint), "Expected size %d, got %ld\n",
2432 sizeof(emptyDistPoint), size);
2433 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2436 /* A dist point with an invalid name */
2437 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2438 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2439 U(entry).pwszURL = (LPWSTR)nihongoURL;
2440 U(point.DistPointName).FullName.cAltEntry = 1;
2441 U(point.DistPointName).FullName.rgAltEntry = &entry;
2442 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2443 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2444 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2445 "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
2446 /* The first invalid character is at index 7 */
2447 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2448 "Expected invalid char at index 7, got %ld\n",
2449 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2450 /* A dist point with (just) a valid name */
2451 U(entry).pwszURL = (LPWSTR)url;
2452 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2453 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2456 ok(size == sizeof(distPointWithUrl), "Expected size %d, got %ld\n",
2457 sizeof(distPointWithUrl), size);
2458 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2461 /* A dist point with (just) reason flags */
2462 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2463 point.ReasonFlags.cbData = sizeof(crlReason);
2464 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2465 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2466 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2469 ok(size == sizeof(distPointWithReason), "Expected size %d, got %ld\n",
2470 sizeof(distPointWithReason), size);
2471 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2474 /* A dist point with just an issuer */
2475 point.ReasonFlags.cbData = 0;
2476 point.CRLIssuer.cAltEntry = 1;
2477 point.CRLIssuer.rgAltEntry = &entry;
2478 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2479 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2482 ok(size == sizeof(distPointWithIssuer), "Expected size %d, got %ld\n",
2483 sizeof(distPointWithIssuer), size);
2484 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2487 /* A dist point with both a name and an issuer */
2488 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2489 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2490 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2493 ok(size == sizeof(distPointWithUrlAndIssuer),
2494 "Expected size %d, got %ld\n", sizeof(distPointWithUrlAndIssuer),
2496 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2501 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2506 PCRL_DIST_POINTS_INFO info;
2507 PCRL_DIST_POINT point;
2508 PCERT_ALT_NAME_ENTRY entry;
2510 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2511 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2512 (BYTE *)&buf, &size);
2515 info = (PCRL_DIST_POINTS_INFO)buf;
2516 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2517 "Expected size at least %d, got %ld\n",
2518 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2519 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2521 point = info->rgDistPoint;
2522 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
2523 "Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
2524 point->DistPointName.dwDistPointNameChoice);
2525 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2526 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2529 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2530 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2531 (BYTE *)&buf, &size);
2534 info = (PCRL_DIST_POINTS_INFO)buf;
2535 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2536 "Expected size at least %d, got %ld\n",
2537 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2538 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2540 point = info->rgDistPoint;
2541 ok(point->DistPointName.dwDistPointNameChoice ==
2542 CRL_DIST_POINT_FULL_NAME,
2543 "Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
2544 point->DistPointName.dwDistPointNameChoice);
2545 ok(U(point->DistPointName).FullName.cAltEntry == 1,
2546 "Expected 1 name entry, got %ld\n",
2547 U(point->DistPointName).FullName.cAltEntry);
2548 entry = U(point->DistPointName).FullName.rgAltEntry;
2549 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2550 "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2551 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2552 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2553 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2556 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2557 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2558 NULL, (BYTE *)&buf, &size);
2561 info = (PCRL_DIST_POINTS_INFO)buf;
2562 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2563 "Expected size at least %d, got %ld\n",
2564 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2565 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2567 point = info->rgDistPoint;
2568 ok(point->DistPointName.dwDistPointNameChoice ==
2569 CRL_DIST_POINT_NO_NAME,
2570 "Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
2571 point->DistPointName.dwDistPointNameChoice);
2572 ok(point->ReasonFlags.cbData == sizeof(crlReason),
2573 "Expected reason length\n");
2574 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
2575 "Unexpected reason\n");
2576 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2579 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2580 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
2581 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2584 info = (PCRL_DIST_POINTS_INFO)buf;
2585 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2586 "Expected size at least %d, got %ld\n",
2587 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2588 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2590 point = info->rgDistPoint;
2591 ok(point->DistPointName.dwDistPointNameChoice ==
2592 CRL_DIST_POINT_FULL_NAME,
2593 "Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
2594 point->DistPointName.dwDistPointNameChoice);
2595 ok(U(point->DistPointName).FullName.cAltEntry == 1,
2596 "Expected 1 name entry, got %ld\n",
2597 U(point->DistPointName).FullName.cAltEntry);
2598 entry = U(point->DistPointName).FullName.rgAltEntry;
2599 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2600 "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2601 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2602 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2603 ok(point->CRLIssuer.cAltEntry == 1,
2604 "Expected 1 issuer entry, got %ld\n", point->CRLIssuer.cAltEntry);
2605 entry = point->CRLIssuer.rgAltEntry;
2606 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2607 "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2608 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2613 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
2614 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2616 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2617 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
2618 0x30, 0x30, 0x30, 0x30, 0x5a };
2619 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
2620 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
2621 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
2622 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
2624 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
2625 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2626 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
2627 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
2628 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
2629 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2630 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
2631 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2632 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
2633 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2634 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
2635 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2636 static const BYTE v1CRLWithExt[] = { 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x30,
2637 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2638 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31, 0x36,
2639 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2640 0x30, 0x2c, 0x30, 0x2a, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2641 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14,
2642 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2643 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2645 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
2650 CRL_INFO info = { 0 };
2651 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
2653 /* Test with a V1 CRL */
2654 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2655 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2656 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2659 ok(size == sizeof(v1CRL), "Expected size %d, got %ld\n",
2660 sizeof(v1CRL), size);
2661 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
2665 info.dwVersion = CRL_V2;
2666 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2667 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2668 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2671 ok(size == v2CRL[1] + 2, "Expected size %d, got %ld\n",
2672 v2CRL[1] + 2, size);
2673 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
2676 /* v1 CRL with a name */
2677 info.dwVersion = CRL_V1;
2678 info.Issuer.cbData = sizeof(encodedCommonName);
2679 info.Issuer.pbData = (BYTE *)encodedCommonName;
2680 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2681 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2682 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2685 ok(size == sizeof(v1CRLWithIssuer), "Expected size %d, got %ld\n",
2686 sizeof(v1CRLWithIssuer), size);
2687 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
2690 /* v1 CRL with a name and a NULL entry pointer */
2692 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2693 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2694 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2695 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2696 /* now set an empty entry */
2697 info.rgCRLEntry = &entry;
2698 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2699 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2702 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
2703 "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEmptyEntry),
2705 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
2706 "Got unexpected value\n");
2709 /* an entry with a serial number */
2710 entry.SerialNumber.cbData = sizeof(serialNum);
2711 entry.SerialNumber.pbData = (BYTE *)serialNum;
2712 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2713 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2716 ok(size == sizeof(v1CRLWithIssuerAndEntry),
2717 "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEntry), size);
2718 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
2719 "Got unexpected value\n");
2722 /* and finally, an entry with an extension */
2723 entry.cExtension = 1;
2724 entry.rgExtension = &criticalExt;
2725 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2726 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2727 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2730 ok(size == sizeof(v1CRLWithExt), "Expected size %d, got %ld\n",
2731 sizeof(v1CRLWithExt), size);
2732 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
2737 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
2739 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
2744 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
2746 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2747 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2748 (BYTE *)&buf, &size);
2749 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2750 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2752 /* at a minimum, a CRL must contain an issuer: */
2753 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2754 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2755 (BYTE *)&buf, &size);
2756 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2759 CRL_INFO *info = (CRL_INFO *)buf;
2761 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2762 sizeof(CRL_INFO), size);
2763 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %ld\n",
2765 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2766 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2767 info->Issuer.cbData);
2768 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2769 "Unexpected issuer\n");
2772 /* check decoding with an empty CRL entry */
2773 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2774 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
2775 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2776 todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2777 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2778 /* with a real CRL entry */
2779 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2780 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
2781 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2782 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2785 CRL_INFO *info = (CRL_INFO *)buf;
2788 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2789 sizeof(CRL_INFO), size);
2790 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2792 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2793 entry = info->rgCRLEntry;
2794 ok(entry->SerialNumber.cbData == 1,
2795 "Expected serial number size 1, got %ld\n",
2796 entry->SerialNumber.cbData);
2797 ok(*entry->SerialNumber.pbData == *serialNum,
2798 "Expected serial number %d, got %d\n", *serialNum,
2799 *entry->SerialNumber.pbData);
2800 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2801 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2802 info->Issuer.cbData);
2803 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2804 "Unexpected issuer\n");
2806 /* and finally, with an extension */
2807 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2808 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
2809 NULL, (BYTE *)&buf, &size);
2810 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2813 CRL_INFO *info = (CRL_INFO *)buf;
2816 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2817 sizeof(CRL_INFO), size);
2818 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2820 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2821 entry = info->rgCRLEntry;
2822 ok(entry->SerialNumber.cbData == 1,
2823 "Expected serial number size 1, got %ld\n",
2824 entry->SerialNumber.cbData);
2825 ok(*entry->SerialNumber.pbData == *serialNum,
2826 "Expected serial number %d, got %d\n", *serialNum,
2827 *entry->SerialNumber.pbData);
2828 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2829 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2830 info->Issuer.cbData);
2831 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2832 "Unexpected issuer\n");
2833 /* Oddly, the extensions don't seem to be decoded. Is this just an MS
2834 * bug, or am I missing something?
2836 ok(info->cExtension == 0, "Expected 0 extensions, got %ld\n",
2841 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING,
2842 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA };
2843 static const BYTE encodedUsage[] = {
2844 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03,
2845 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09,
2846 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 };
2848 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding)
2853 CERT_ENHKEY_USAGE usage;
2855 /* Test with empty usage */
2856 usage.cUsageIdentifier = 0;
2857 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
2858 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2859 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2862 ok(size == sizeof(emptySequence), "Expected size %d, got %ld\n",
2863 sizeof(emptySequence), size);
2864 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n");
2867 /* Test with a few usages */
2868 usage.cUsageIdentifier = sizeof(keyUsages) / sizeof(keyUsages[0]);
2869 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages;
2870 ret = CryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage,
2871 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2872 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2875 ok(size == sizeof(encodedUsage), "Expected size %d, got %ld\n",
2876 sizeof(encodedUsage), size);
2877 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n");
2882 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding)
2888 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
2889 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL,
2890 (BYTE *)&buf, &size);
2891 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2894 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
2896 ok(size >= sizeof(CERT_ENHKEY_USAGE),
2897 "Expected size at least %d, got %ld\n", sizeof(CERT_ENHKEY_USAGE),
2899 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %ld\n",
2900 usage->cUsageIdentifier);
2903 ret = CryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE,
2904 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL,
2905 (BYTE *)&buf, &size);
2906 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2909 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf;
2912 ok(size >= sizeof(CERT_ENHKEY_USAGE),
2913 "Expected size at least %d, got %ld\n", sizeof(CERT_ENHKEY_USAGE),
2915 ok(usage->cUsageIdentifier == sizeof(keyUsages) / sizeof(keyUsages[0]),
2916 "Expected %d CRL entries, got %ld\n",
2917 sizeof(keyUsages) / sizeof(keyUsages[0]),
2918 usage->cUsageIdentifier);
2919 for (i = 0; i < usage->cUsageIdentifier; i++)
2920 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]),
2921 "Expected OID %s, got %s\n", keyUsages[i],
2922 usage->rgpszUsageIdentifier[i]);
2927 /* Free *pInfo with HeapFree */
2928 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
2935 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
2937 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
2938 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2939 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2940 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
2942 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2943 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2944 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
2946 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2947 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2948 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
2949 0, NULL, NULL, &size);
2950 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2951 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2952 /* Test with no key */
2953 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
2954 0, NULL, NULL, &size);
2955 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08lx\n",
2957 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
2958 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
2961 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2962 NULL, 0, NULL, NULL, &size);
2963 ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n", GetLastError());
2964 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2967 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
2968 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
2969 ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n",
2973 /* By default (we passed NULL as the OID) the OID is
2976 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
2977 "Expected %s, got %s\n", szOID_RSA_RSA,
2978 (*pInfo)->Algorithm.pszObjId);
2984 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2,
2985 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6,
2986 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06,
2987 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30,
2988 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
2989 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
2990 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30,
2991 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30,
2992 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30,
2993 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40,
2994 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63,
2995 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7,
2996 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41,
2997 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29,
2998 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e,
2999 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5,
3000 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a,
3001 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b,
3002 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02,
3003 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0,
3004 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3,
3005 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31,
3006 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70,
3007 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef,
3008 0x49, 0xe5, 0xf9, 0x65, 0xf3 };
3010 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
3014 PCCERT_CONTEXT context;
3017 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
3018 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
3019 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
3020 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
3023 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
3024 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3025 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
3026 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
3027 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
3028 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
3029 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
3031 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
3032 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
3033 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
3035 ok(ret, "CryptImportPublicKeyInfoEx failed: %08lx\n", GetLastError());
3036 CryptDestroyKey(key);
3038 /* Test importing a public key from a certificate context */
3039 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert,
3040 sizeof(expiredCert));
3041 ok(context != NULL, "CertCreateCertificateContext failed: %08lx\n",
3045 ok(!strcmp(szOID_RSA_RSA,
3046 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId),
3047 "Expected %s, got %s\n", szOID_RSA_RSA,
3048 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId);
3049 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING,
3050 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key);
3051 ok(ret, "CryptImportPublicKeyInfoEx failed: %08lx\n", GetLastError());
3052 CryptDestroyKey(key);
3053 CertFreeCertificateContext(context);
3057 static const char cspName[] = "WineCryptTemp";
3059 static void testPortPublicKeyInfo(void)
3063 PCERT_PUBLIC_KEY_INFO info = NULL;
3065 /* Just in case a previous run failed, delete this thing */
3066 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3067 CRYPT_DELETEKEYSET);
3068 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3071 testExportPublicKey(csp, &info);
3072 testImportPublicKey(csp, info);
3074 HeapFree(GetProcessHeap(), 0, info);
3075 CryptReleaseContext(csp, 0);
3076 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
3077 CRYPT_DELETEKEYSET);
3082 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
3083 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
3086 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
3088 test_encodeInt(encodings[i]);
3089 test_decodeInt(encodings[i]);
3090 test_encodeEnumerated(encodings[i]);
3091 test_decodeEnumerated(encodings[i]);
3092 test_encodeFiletime(encodings[i]);
3093 test_decodeFiletime(encodings[i]);
3094 test_encodeName(encodings[i]);
3095 test_decodeName(encodings[i]);
3096 test_encodeAltName(encodings[i]);
3097 test_decodeAltName(encodings[i]);
3098 test_encodeOctets(encodings[i]);
3099 test_decodeOctets(encodings[i]);
3100 test_encodeBits(encodings[i]);
3101 test_decodeBits(encodings[i]);
3102 test_encodeBasicConstraints(encodings[i]);
3103 test_decodeBasicConstraints(encodings[i]);
3104 test_encodeRsaPublicKey(encodings[i]);
3105 test_decodeRsaPublicKey(encodings[i]);
3106 test_encodeSequenceOfAny(encodings[i]);
3107 test_decodeSequenceOfAny(encodings[i]);
3108 test_encodeExtensions(encodings[i]);
3109 test_decodeExtensions(encodings[i]);
3110 test_encodePublicKeyInfo(encodings[i]);
3111 test_decodePublicKeyInfo(encodings[i]);
3112 test_encodeCertToBeSigned(encodings[i]);
3113 test_decodeCertToBeSigned(encodings[i]);
3114 test_encodeCert(encodings[i]);
3115 test_decodeCert(encodings[i]);
3116 test_encodeCRLDistPoints(encodings[i]);
3117 test_decodeCRLDistPoints(encodings[i]);
3118 test_encodeCRLToBeSigned(encodings[i]);
3119 test_decodeCRLToBeSigned(encodings[i]);
3120 test_encodeEnhancedKeyUsage(encodings[i]);
3121 test_decodeEnhancedKeyUsage(encodings[i]);
3123 testPortPublicKeyInfo();