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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
27 #include "wine/test.h"
35 static const BYTE bin1[] = {0x02,0x01,0x01,0};
36 static const BYTE bin2[] = {0x02,0x01,0x7f,0};
37 static const BYTE bin3[] = {0x02,0x02,0x00,0x80,0};
38 static const BYTE bin4[] = {0x02,0x02,0x01,0x00,0};
39 static const BYTE bin5[] = {0x02,0x01,0x80,0};
40 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f,0};
41 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d,0};
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,0};
339 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80,0};
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',0};
486 static const BYTE bin21[] = {
487 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z',0};
488 static const BYTE bin22[] = {
489 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z',0};
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',0};
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',0};
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',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',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',0};
519 static const BYTE bin28[] = {
520 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6',0};
521 static const BYTE bin29[] = {
522 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0',0};
523 static const BYTE bin30[] = {
524 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z',0};
525 static const BYTE bin31[] = {
526 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1',0};
527 static const BYTE bin32[] = {
528 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1',0};
529 static const BYTE bin33[] = {
530 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0',0};
531 static const BYTE bin34[] = {
532 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0',0};
533 static const BYTE bin35[] = {
534 0x17,0x08, '4','5','0','6','0','6','1','6',0};
535 static const BYTE bin36[] = {
536 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z',0};
537 static const BYTE bin37[] = {
538 0x18,0x04, '2','1','4','5',0};
539 static const BYTE bin38[] = {
540 0x18,0x08, '2','1','4','5','0','6','0','6',0};
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 emptyName[] = { 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 void test_encodeName(DWORD dwEncoding)
666 CERT_RDN_ATTR attrs[2];
673 /* Test with NULL pvStructInfo */
674 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, NULL,
675 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
676 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
677 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
678 /* Test with empty CERT_NAME_INFO */
681 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
682 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
683 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
686 ok(!memcmp(buf, emptyName, sizeof(emptyName)),
687 "Got unexpected encoding for empty name\n");
690 /* Test with bogus CERT_RDN */
692 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
693 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
694 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
695 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
696 /* Test with empty CERT_RDN */
698 rdn.rgRDNAttr = NULL;
701 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
702 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
703 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
706 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)),
707 "Got unexpected encoding for empty RDN array\n");
710 /* Test with bogus attr array */
712 rdn.rgRDNAttr = NULL;
713 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
714 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
715 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
716 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
717 /* oddly, a bogus OID is accepted by Windows XP; not testing.
718 attrs[0].pszObjId = "bogus";
719 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
720 attrs[0].Value.cbData = sizeof(commonName);
721 attrs[0].Value.pbData = (BYTE *)commonName;
723 rdn.rgRDNAttr = attrs;
724 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
725 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
726 ok(!ret, "Expected failure, got success\n");
728 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of
729 * the encoded attributes to be swapped.
731 attrs[0].pszObjId = szOID_COMMON_NAME;
732 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING;
733 attrs[0].Value.cbData = sizeof(commonName);
734 attrs[0].Value.pbData = (BYTE *)commonName;
735 attrs[1].pszObjId = szOID_SUR_NAME;
736 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING;
737 attrs[1].Value.cbData = sizeof(surName);
738 attrs[1].Value.pbData = (BYTE *)surName;
740 rdn.rgRDNAttr = attrs;
741 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
742 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
743 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
746 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)),
747 "Got unexpected encoding for two RDN array\n");
750 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */
752 attrs[0].dwValueType = CERT_RDN_ANY_TYPE;
753 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
754 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
755 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
756 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
757 for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
760 rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
761 ret = CryptEncodeObjectEx(dwEncoding, X509_NAME, &info,
762 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
763 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
766 ok(size == names[i].encoded[1] + 2, "Expected size %d, got %ld\n",
767 names[i].encoded[1] + 2, size);
768 ok(!memcmp(buf, names[i].encoded, names[i].encoded[1] + 2),
769 "Got unexpected encoding\n");
775 static void compareNames(const CERT_NAME_INFO *expected,
776 const CERT_NAME_INFO *got)
778 ok(got->cRDN == expected->cRDN, "Expected %ld RDNs, got %ld\n",
779 expected->cRDN, got->cRDN);
782 ok(got->rgRDN[0].cRDNAttr == expected->rgRDN[0].cRDNAttr,
783 "Expected %ld RDN attrs, got %ld\n", expected->rgRDN[0].cRDNAttr,
784 got->rgRDN[0].cRDNAttr);
785 if (got->rgRDN[0].cRDNAttr)
787 if (expected->rgRDN[0].rgRDNAttr[0].pszObjId &&
788 strlen(expected->rgRDN[0].rgRDNAttr[0].pszObjId))
790 ok(got->rgRDN[0].rgRDNAttr[0].pszObjId != NULL,
791 "Expected OID %s, got NULL\n",
792 expected->rgRDN[0].rgRDNAttr[0].pszObjId);
793 if (got->rgRDN[0].rgRDNAttr[0].pszObjId)
794 ok(!strcmp(got->rgRDN[0].rgRDNAttr[0].pszObjId,
795 expected->rgRDN[0].rgRDNAttr[0].pszObjId),
796 "Got unexpected OID %s, expected %s\n",
797 got->rgRDN[0].rgRDNAttr[0].pszObjId,
798 expected->rgRDN[0].rgRDNAttr[0].pszObjId);
800 ok(got->rgRDN[0].rgRDNAttr[0].Value.cbData ==
801 expected->rgRDN[0].rgRDNAttr[0].Value.cbData,
802 "Unexpected data size, got %ld, expected %ld\n",
803 got->rgRDN[0].rgRDNAttr[0].Value.cbData,
804 expected->rgRDN[0].rgRDNAttr[0].Value.cbData);
805 if (got->rgRDN[0].rgRDNAttr[0].Value.cbData &&
806 got->rgRDN[0].rgRDNAttr[0].Value.pbData)
807 ok(!memcmp(got->rgRDN[0].rgRDNAttr[0].Value.pbData,
808 expected->rgRDN[0].rgRDNAttr[0].Value.pbData,
809 min(got->rgRDN[0].rgRDNAttr[0].Value.cbData,
810 expected->rgRDN[0].rgRDNAttr[0].Value.cbData)),
811 "Unexpected value\n");
816 static void test_decodeName(DWORD dwEncoding)
823 CERT_NAME_INFO info = { 1, &rdn };
825 for (i = 0; i < sizeof(names) / sizeof(names[0]); i++)
827 /* When the output buffer is NULL, this always succeeds */
828 SetLastError(0xdeadbeef);
829 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
830 names[i].encoded[1] + 2, 0, NULL, NULL, &bufSize);
831 ok(ret && GetLastError() == NOERROR,
832 "Expected success and NOERROR, got %08lx\n", GetLastError());
833 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, names[i].encoded,
834 names[i].encoded[1] + 2,
835 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
836 (BYTE *)&buf, &bufSize);
837 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
839 rdn.rgRDNAttr = (CERT_RDN_ATTR *)&names[i].attr;
842 compareNames(&info, (CERT_NAME_INFO *)buf);
846 /* test empty name */
848 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyName,
850 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
851 (BYTE *)&buf, &bufSize);
852 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
853 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My
854 * decoder works the same way, so only test the count.
858 ok(bufSize == sizeof(CERT_NAME_INFO),
859 "Expected bufSize %d, got %ld\n", sizeof(CERT_NAME_INFO), bufSize);
860 ok(((CERT_NAME_INFO *)buf)->cRDN == 0,
861 "Expected 0 RDNs in empty info, got %ld\n",
862 ((CERT_NAME_INFO *)buf)->cRDN);
867 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs,
869 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
870 (BYTE *)&buf, &bufSize);
871 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
874 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf;
876 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) &&
877 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0,
878 "Got unexpected value for empty RDN\n");
881 /* test two RDN attrs */
883 ret = CryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs,
885 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL,
886 (BYTE *)&buf, &bufSize);
887 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
890 CERT_RDN_ATTR attrs[] = {
891 { szOID_SUR_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(surName),
893 { szOID_COMMON_NAME, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName),
894 (BYTE *)commonName } },
897 rdn.cRDNAttr = sizeof(attrs) / sizeof(attrs[0]);
898 rdn.rgRDNAttr = attrs;
899 compareNames(&info, (CERT_NAME_INFO *)buf);
904 static const BYTE emptyAltName[] = { 0x30, 0x00 };
905 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 };
906 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e',
907 'h','q','.','o','r','g',0 };
908 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74,
909 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e,
911 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f,
913 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 };
914 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69,
915 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
916 static const BYTE localhost[] = { 127, 0, 0, 1 };
917 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00,
920 static void test_encodeAltName(DWORD dwEncoding)
922 CERT_ALT_NAME_INFO info = { 0 };
923 CERT_ALT_NAME_ENTRY entry = { 0 };
928 /* Test with empty info */
929 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
930 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
933 ok(size == sizeof(emptyAltName), "Expected size %d, got %ld\n",
934 sizeof(emptyAltName), size);
935 ok(!memcmp(buf, emptyAltName, size), "Unexpected value\n");
938 /* Test with an empty entry */
940 info.rgAltEntry = &entry;
941 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
942 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
943 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
944 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
946 /* Test with an empty pointer */
947 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
948 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
949 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
952 ok(size == sizeof(emptyURL), "Expected size %d, got %ld\n",
953 sizeof(emptyURL), size);
954 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n");
957 /* Test with a real URL */
958 U(entry).pwszURL = (LPWSTR)url;
959 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
960 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
963 ok(size == sizeof(encodedURL), "Expected size %d, got %ld\n",
964 sizeof(encodedURL), size);
965 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n");
968 /* Now with the URL containing an invalid IA5 char */
969 U(entry).pwszURL = (LPWSTR)nihongoURL;
970 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
971 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
972 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
973 "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
974 /* The first invalid character is at index 7 */
975 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
976 "Expected invalid char at index 7, got %ld\n",
977 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
978 /* Now with the URL missing a scheme */
979 U(entry).pwszURL = (LPWSTR)dnsName;
980 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
981 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
982 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
985 /* This succeeds, but it shouldn't, so don't worry about conforming */
988 /* Now with a DNS name */
989 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME;
990 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
991 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
992 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
995 ok(size == sizeof(encodedDnsName), "Expected size %d, got %ld\n",
996 sizeof(encodedDnsName), size);
997 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n");
1000 /* Test with an IP address */
1001 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS;
1002 U(entry).IPAddress.cbData = sizeof(localhost);
1003 U(entry).IPAddress.pbData = (LPBYTE)localhost;
1004 ret = CryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info,
1005 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
1008 ok(size == sizeof(encodedIPAddr), "Expected size %d, got %ld\n",
1009 sizeof(encodedIPAddr), size);
1010 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n");
1015 static void test_decodeAltName(DWORD dwEncoding)
1017 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f,
1019 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00,
1024 CERT_ALT_NAME_INFO *info;
1026 /* Test some bogus ones first */
1027 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1028 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG,
1029 NULL, (BYTE *)&buf, &bufSize);
1030 ok(!ret && GetLastError() == CRYPT_E_ASN1_BADTAG,
1031 "Expected CRYPT_E_ASN1_BADTAG, got %08lx\n", GetLastError());
1032 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME,
1033 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1035 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1036 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1037 /* Now expected cases */
1038 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyAltName,
1039 emptyAltName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1041 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1044 info = (CERT_ALT_NAME_INFO *)buf;
1046 ok(info->cAltEntry == 0, "Expected 0 entries, got %ld\n",
1050 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL,
1051 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1053 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1056 info = (CERT_ALT_NAME_INFO *)buf;
1058 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1060 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1061 "Expected CERT_ALT_NAME_URL, got %ld\n",
1062 info->rgAltEntry[0].dwAltNameChoice);
1063 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL,
1064 "Expected empty URL\n");
1067 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL,
1068 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1070 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1073 info = (CERT_ALT_NAME_INFO *)buf;
1075 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1077 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL,
1078 "Expected CERT_ALT_NAME_URL, got %ld\n",
1079 info->rgAltEntry[0].dwAltNameChoice);
1080 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n");
1083 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName,
1084 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1086 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1089 info = (CERT_ALT_NAME_INFO *)buf;
1091 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1093 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME,
1094 "Expected CERT_ALT_NAME_DNS_NAME, got %ld\n",
1095 info->rgAltEntry[0].dwAltNameChoice);
1096 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName),
1097 "Unexpected DNS name\n");
1100 ret = CryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr,
1101 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1103 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1106 info = (CERT_ALT_NAME_INFO *)buf;
1108 ok(info->cAltEntry == 1, "Expected 1 entries, got %ld\n",
1110 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS,
1111 "Expected CERT_ALT_NAME_IP_ADDRESS, got %ld\n",
1112 info->rgAltEntry[0].dwAltNameChoice);
1113 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost),
1114 "Unexpected IP address length %ld\n",
1115 U(info->rgAltEntry[0]).IPAddress.cbData);
1116 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost,
1117 sizeof(localhost)), "Unexpected IP address value\n");
1122 struct encodedOctets
1125 const BYTE *encoded;
1128 static const unsigned char bin46[] = { 'h','i',0 };
1129 static const unsigned char bin47[] = { 0x04,0x02,'h','i',0 };
1130 static const unsigned char bin48[] = {
1131 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1132 static const unsigned char bin49[] = {
1133 0x04,0x0f,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g',0 };
1134 static const unsigned char bin50[] = { 0 };
1135 static const unsigned char bin51[] = { 0x04,0x00,0 };
1137 static const struct encodedOctets octets[] = {
1143 static void test_encodeOctets(DWORD dwEncoding)
1145 CRYPT_DATA_BLOB blob;
1148 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1154 blob.cbData = strlen((const char*)octets[i].val);
1155 blob.pbData = (BYTE*)octets[i].val;
1156 ret = CryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob,
1157 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1158 ok(ret, "CryptEncodeObjectEx failed: %ld\n", GetLastError());
1162 "Got unexpected type %d for octet string (expected 4)\n", buf[0]);
1163 ok(buf[1] == octets[i].encoded[1], "Got length %d, expected %d\n",
1164 buf[1], octets[i].encoded[1]);
1165 ok(!memcmp(buf + 1, octets[i].encoded + 1,
1166 octets[i].encoded[1] + 1), "Got unexpected value\n");
1172 static void test_decodeOctets(DWORD dwEncoding)
1176 for (i = 0; i < sizeof(octets) / sizeof(octets[0]); i++)
1182 ret = CryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING,
1183 (BYTE *)octets[i].encoded, octets[i].encoded[1] + 2,
1184 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1185 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1186 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1],
1187 "Expected size >= %d, got %ld\n",
1188 sizeof(CRYPT_DATA_BLOB) + octets[i].encoded[1], bufSize);
1189 ok(buf != NULL, "Expected allocated buffer\n");
1192 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf;
1195 ok(!memcmp(blob->pbData, octets[i].val, blob->cbData),
1196 "Unexpected value\n");
1202 static const BYTE bytesToEncode[] = { 0xff, 0xff };
1207 const BYTE *encoded;
1209 const BYTE *decoded;
1212 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff,0 };
1213 static const unsigned char bin53[] = { 0xff,0xff,0 };
1214 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe,0 };
1215 static const unsigned char bin55[] = { 0xff,0xfe,0 };
1216 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe,0 };
1217 static const unsigned char bin57[] = { 0xfe,0 };
1218 static const unsigned char bin58[] = { 0x03,0x01,0x00,0 };
1220 static const struct encodedBits bits[] = {
1221 /* normal test cases */
1222 { 0, bin52, 2, bin53 },
1223 { 1, bin54, 2, bin55 },
1224 /* strange test case, showing cUnusedBits >= 8 is allowed */
1225 { 9, bin56, 1, bin57 },
1226 /* even stranger test case, showing cUnusedBits > cbData * 8 is allowed */
1227 { 17, bin58, 0, NULL },
1230 static void test_encodeBits(DWORD dwEncoding)
1234 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1236 CRYPT_BIT_BLOB blob;
1241 blob.cbData = sizeof(bytesToEncode);
1242 blob.pbData = (BYTE *)bytesToEncode;
1243 blob.cUnusedBits = bits[i].cUnusedBits;
1244 ret = CryptEncodeObjectEx(dwEncoding, X509_BITS, &blob,
1245 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1246 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1249 ok(bufSize == bits[i].encoded[1] + 2,
1250 "Got unexpected size %ld, expected %d\n", bufSize,
1251 bits[i].encoded[1] + 2);
1252 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2),
1253 "Unexpected value\n");
1259 static void test_decodeBits(DWORD dwEncoding)
1261 static const BYTE ber[] = "\x03\x02\x01\xff";
1262 static const BYTE berDecoded = 0xfe;
1269 for (i = 0; i < sizeof(bits) / sizeof(bits[0]); i++)
1271 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded,
1272 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1274 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1277 CRYPT_BIT_BLOB *blob;
1279 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded,
1280 "Got unexpected size %ld, expected >= %ld\n", bufSize,
1281 sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded);
1282 blob = (CRYPT_BIT_BLOB *)buf;
1283 ok(blob->cbData == bits[i].cbDecoded,
1284 "Got unexpected length %ld, expected %ld\n", blob->cbData,
1286 if (blob->cbData && bits[i].cbDecoded)
1287 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded),
1288 "Unexpected value\n");
1292 /* special case: check that something that's valid in BER but not in DER
1293 * decodes successfully
1295 ret = CryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2,
1296 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1297 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1300 CRYPT_BIT_BLOB *blob;
1302 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded),
1303 "Got unexpected size %ld, expected >= %d\n", bufSize,
1304 sizeof(CRYPT_BIT_BLOB) + berDecoded);
1305 blob = (CRYPT_BIT_BLOB *)buf;
1306 ok(blob->cbData == sizeof(berDecoded),
1307 "Got unexpected length %ld, expected %d\n", blob->cbData,
1308 sizeof(berDecoded));
1310 ok(*blob->pbData == berDecoded, "Unexpected value\n");
1317 CERT_BASIC_CONSTRAINTS2_INFO info;
1318 const BYTE *encoded;
1321 static const unsigned char bin59[] = { 0x30,0x00,0 };
1322 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff,0 };
1323 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00,0 };
1324 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0 };
1325 static const struct Constraints2 constraints2[] = {
1326 /* empty constraints */
1327 { { FALSE, FALSE, 0}, bin59 },
1329 { { TRUE, FALSE, 0}, bin60 },
1330 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well,
1331 * but that's not the case
1333 { { FALSE, TRUE, 0}, bin61 },
1334 /* can be a CA and has path length constraints set */
1335 { { TRUE, TRUE, 1}, bin62 },
1338 static void test_encodeBasicConstraints(DWORD dwEncoding)
1342 /* First test with the simpler info2 */
1343 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1349 ret = CryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1350 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1352 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1355 ok(bufSize == constraints2[i].encoded[1] + 2,
1356 "Expected %d bytes, got %ld\n", constraints2[i].encoded[1] + 2,
1358 ok(!memcmp(buf, constraints2[i].encoded,
1359 constraints2[i].encoded[1] + 2), "Unexpected value\n");
1365 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01,0 };
1367 static void test_decodeBasicConstraints(DWORD dwEncoding)
1369 static const BYTE inverted[] = "\x30\x06\x02\x01\x01\x01\x01\xff";
1370 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 };
1376 /* First test with simpler info2 */
1377 for (i = 0; i < sizeof(constraints2) / sizeof(constraints2[0]); i++)
1379 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1380 constraints2[i].encoded, constraints2[i].encoded[1] + 2,
1381 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1382 ok(ret, "CryptDecodeObjectEx failed for item %ld: %08lx\n", i,
1386 CERT_BASIC_CONSTRAINTS2_INFO *info =
1387 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1389 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)),
1390 "Unexpected value for item %ld\n", i);
1394 /* Check with the order of encoded elements inverted */
1396 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1397 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1399 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1400 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1401 ok(!buf, "Expected buf to be set to NULL\n");
1402 /* Check with a non-DER bool */
1403 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1404 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1405 (BYTE *)&buf, &bufSize);
1406 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1409 CERT_BASIC_CONSTRAINTS2_INFO *info =
1410 (CERT_BASIC_CONSTRAINTS2_INFO *)buf;
1412 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n");
1415 /* Check with a non-basic constraints value */
1416 ret = CryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2,
1417 names[0].encoded, names[0].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
1418 (BYTE *)&buf, &bufSize);
1419 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1420 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1423 /* These are terrible public keys of course, I'm just testing encoding */
1424 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 };
1425 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 };
1426 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 };
1427 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 };
1428 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 };
1429 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1430 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 };
1431 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 };
1433 struct EncodedRSAPubKey
1435 const BYTE *modulus;
1437 const BYTE *encoded;
1438 size_t decodedModulusLen;
1441 struct EncodedRSAPubKey rsaPubKeys[] = {
1442 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) },
1443 { modulus2, sizeof(modulus2), mod2_encoded, 5 },
1444 { modulus3, sizeof(modulus3), mod3_encoded, 5 },
1445 { modulus4, sizeof(modulus4), mod4_encoded, 8 },
1448 static void test_encodeRsaPublicKey(DWORD dwEncoding)
1450 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)];
1451 BLOBHEADER *hdr = (BLOBHEADER *)toEncode;
1452 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER));
1455 DWORD bufSize = 0, i;
1457 /* Try with a bogus blob type */
1459 hdr->bVersion = CUR_BLOB_VERSION;
1461 hdr->aiKeyAlg = CALG_RSA_KEYX;
1462 rsaPubKey->magic = 0x31415352;
1463 rsaPubKey->bitlen = sizeof(modulus1) * 8;
1464 rsaPubKey->pubexp = 65537;
1465 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1,
1468 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1469 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1471 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
1472 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
1474 /* Now with a bogus reserved field */
1475 hdr->bType = PUBLICKEYBLOB;
1477 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1478 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1482 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1483 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1484 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1487 /* Now with a bogus blob version */
1490 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1491 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1495 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1496 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1497 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1500 /* And with a bogus alg ID */
1501 hdr->bVersion = CUR_BLOB_VERSION;
1502 hdr->aiKeyAlg = CALG_DES;
1503 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1504 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1508 ok(bufSize == rsaPubKeys[0].encoded[1] + 2,
1509 "Expected size %d, got %ld\n", rsaPubKeys[0].encoded[1] + 2, bufSize);
1510 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n");
1513 /* Check a couple of RSA-related OIDs */
1514 hdr->aiKeyAlg = CALG_RSA_KEYX;
1515 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA,
1516 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1517 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1518 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1519 ret = CryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1520 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1521 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1522 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1523 /* Finally, all valid */
1524 hdr->aiKeyAlg = CALG_RSA_KEYX;
1525 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1527 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1528 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen);
1529 ret = CryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1530 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1531 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1534 ok(bufSize == rsaPubKeys[i].encoded[1] + 2,
1535 "Expected size %d, got %ld\n", rsaPubKeys[i].encoded[1] + 2,
1537 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize),
1538 "Unexpected value\n");
1544 static void test_decodeRsaPublicKey(DWORD dwEncoding)
1551 /* Try with a bad length */
1552 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1553 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1],
1554 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1555 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
1556 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", CRYPT_E_ASN1_EOD);
1557 /* Try with a couple of RSA-related OIDs */
1558 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA,
1559 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
1560 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1561 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1562 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1563 ret = CryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA,
1564 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2,
1565 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1566 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
1567 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
1568 /* Now try success cases */
1569 for (i = 0; i < sizeof(rsaPubKeys) / sizeof(rsaPubKeys[0]); i++)
1572 ret = CryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB,
1573 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2,
1574 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1575 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1578 BLOBHEADER *hdr = (BLOBHEADER *)buf;
1579 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER));
1581 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1582 rsaPubKeys[i].decodedModulusLen,
1583 "Expected size at least %d, got %ld\n",
1584 sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) +
1585 rsaPubKeys[i].decodedModulusLen, bufSize);
1586 ok(hdr->bType == PUBLICKEYBLOB,
1587 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB,
1589 ok(hdr->bVersion == CUR_BLOB_VERSION,
1590 "Expected version CUR_BLOB_VERSION (%d), got %d\n",
1591 CUR_BLOB_VERSION, hdr->bVersion);
1592 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n",
1594 ok(hdr->aiKeyAlg == CALG_RSA_KEYX,
1595 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg);
1596 ok(rsaPubKey->magic == 0x31415352,
1597 "Expected magic RSA1, got %08lx\n", rsaPubKey->magic);
1598 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8,
1599 "Expected bit len %d, got %ld\n",
1600 rsaPubKeys[i].decodedModulusLen * 8, rsaPubKey->bitlen);
1601 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %ld\n",
1603 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY),
1604 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen),
1605 "Unexpected modulus\n");
1611 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01,
1612 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02,
1613 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1615 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30,
1616 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f,
1617 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02,
1618 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d };
1620 static void test_encodeSequenceOfAny(DWORD dwEncoding)
1622 CRYPT_DER_BLOB blobs[sizeof(ints) / sizeof(ints[0])];
1623 CRYPT_SEQUENCE_OF_ANY seq;
1629 /* Encode a homogenous sequence */
1630 for (i = 0; i < sizeof(ints) / sizeof(ints[0]); i++)
1632 blobs[i].cbData = ints[i].encoded[1] + 2;
1633 blobs[i].pbData = (BYTE *)ints[i].encoded;
1635 seq.cValue = sizeof(ints) / sizeof(ints[0]);
1636 seq.rgValue = blobs;
1638 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1639 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1640 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1643 ok(bufSize == sizeof(intSequence), "Expected %d bytes, got %ld\n",
1644 sizeof(intSequence), bufSize);
1645 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n");
1648 /* Change the type of the first element in the sequence, and give it
1651 blobs[0].cbData = times[0].encodedTime[1] + 2;
1652 blobs[0].pbData = (BYTE *)times[0].encodedTime;
1653 ret = CryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq,
1654 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1655 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1658 ok(bufSize == sizeof(mixedSequence), "Expected %d bytes, got %ld\n",
1659 sizeof(mixedSequence), bufSize);
1660 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2),
1661 "Unexpected value\n");
1666 static void test_decodeSequenceOfAny(DWORD dwEncoding)
1672 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence,
1673 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1674 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1677 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1680 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1681 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1683 for (i = 0; i < min(seq->cValue, sizeof(ints) / sizeof(ints[0])); i++)
1685 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2,
1686 "Expected %d bytes, got %ld\n", ints[i].encoded[1] + 2,
1687 seq->rgValue[i].cbData);
1688 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded,
1689 ints[i].encoded[1] + 2), "Unexpected value\n");
1693 ret = CryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence,
1694 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1696 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1699 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf;
1701 ok(seq->cValue == sizeof(ints) / sizeof(ints[0]),
1702 "Expected %d elements, got %ld\n", sizeof(ints) / sizeof(ints[0]),
1704 /* Just check the first element since it's all that changed */
1705 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2,
1706 "Expected %d bytes, got %ld\n", times[0].encodedTime[1] + 2,
1707 seq->rgValue[0].cbData);
1708 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime,
1709 times[0].encodedTime[1] + 2), "Unexpected value\n");
1714 struct encodedExtensions
1716 CERT_EXTENSIONS exts;
1717 const BYTE *encoded;
1720 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1721 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1723 static CERT_EXTENSION criticalExt =
1724 { szOID_BASIC_CONSTRAINTS2, TRUE, { 8, crit_ext_data } };
1725 static CERT_EXTENSION nonCriticalExt =
1726 { szOID_BASIC_CONSTRAINTS2, FALSE, { 8, noncrit_ext_data } };
1728 static const BYTE ext0[] = { 0x30,0x00 };
1729 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,
1730 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1731 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04,
1732 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 };
1734 static const struct encodedExtensions exts[] = {
1735 { { 0, NULL }, ext0 },
1736 { { 1, &criticalExt }, ext1 },
1737 { { 1, &nonCriticalExt }, ext2 },
1740 static void test_encodeExtensions(DWORD dwEncoding)
1744 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1750 ret = CryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts,
1751 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize);
1752 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1755 ok(bufSize == exts[i].encoded[1] + 2,
1756 "Expected %d bytes, got %ld\n", exts[i].encoded[1] + 2, bufSize);
1757 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2),
1758 "Unexpected value\n");
1764 static void test_decodeExtensions(DWORD dwEncoding)
1768 for (i = 0; i < sizeof(exts) / sizeof(exts[i]); i++)
1774 ret = CryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS,
1775 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1776 NULL, (BYTE *)&buf, &bufSize);
1777 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1780 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf;
1783 ok(ext->cExtension == exts[i].exts.cExtension,
1784 "Expected %ld extensions, see %ld\n", exts[i].exts.cExtension,
1786 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++)
1788 ok(!strcmp(ext->rgExtension[j].pszObjId,
1789 exts[i].exts.rgExtension[j].pszObjId),
1790 "Expected OID %s, got %s\n",
1791 exts[i].exts.rgExtension[j].pszObjId,
1792 ext->rgExtension[j].pszObjId);
1793 ok(!memcmp(ext->rgExtension[j].Value.pbData,
1794 exts[i].exts.rgExtension[j].Value.pbData,
1795 exts[i].exts.rgExtension[j].Value.cbData),
1796 "Unexpected value\n");
1803 /* MS encodes public key info with a NULL if the algorithm identifier's
1804 * parameters are empty. However, when encoding an algorithm in a CERT_INFO,
1805 * it encodes them by omitting the algorithm parameters. This latter approach
1806 * seems more correct, so accept either form.
1808 struct encodedPublicKey
1810 CERT_PUBLIC_KEY_INFO info;
1811 const BYTE *encoded;
1812 const BYTE *encodedNoNull;
1813 CERT_PUBLIC_KEY_INFO decoded;
1816 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
1818 static const BYTE params[] = { 0x02, 0x01, 0x01 };
1820 static const unsigned char bin64[] = {
1821 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00,0};
1822 static const unsigned char bin65[] = {
1823 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00,0};
1824 static const unsigned char bin66[] = {
1825 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00,0};
1826 static const unsigned char bin67[] = {
1827 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00,0};
1828 static const unsigned char bin68[] = {
1829 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01,
1830 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0};
1831 static const unsigned char bin69[] = {
1832 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01,
1833 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0};
1834 static const unsigned char bin70[] = {
1835 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
1836 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
1838 static const unsigned char bin71[] = {
1839 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01,
1840 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,
1842 static unsigned char bin72[] = { 0x05,0x00,0};
1844 static const struct encodedPublicKey pubKeys[] = {
1845 /* with a bogus OID */
1846 { { { "1.2.3", { 0, NULL } }, { 0, NULL, 0 } },
1848 { { "1.2.3", { 2, bin72 } }, { 0, NULL, 0 } } },
1849 /* some normal keys */
1850 { { { szOID_RSA, { 0, NULL } }, { 0, NULL, 0} },
1852 { { szOID_RSA, { 2, bin72 } }, { 0, NULL, 0 } } },
1853 { { { szOID_RSA, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} },
1855 { { szOID_RSA, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } },
1856 /* with add'l parameters--note they must be DER-encoded */
1857 { { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
1858 (BYTE *)aKey, 0 } },
1860 { { szOID_RSA, { sizeof(params), (BYTE *)params } }, { sizeof(aKey),
1861 (BYTE *)aKey, 0 } } },
1864 static void test_encodePublicKeyInfo(DWORD dwEncoding)
1868 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
1874 ret = CryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1875 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf,
1877 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
1880 ok(bufSize == pubKeys[i].encoded[1] + 2 ||
1881 bufSize == pubKeys[i].encodedNoNull[1] + 2,
1882 "Expected %d or %d bytes, got %ld\n", pubKeys[i].encoded[1] + 2,
1883 pubKeys[i].encodedNoNull[1] + 2, bufSize);
1884 if (bufSize == pubKeys[i].encoded[1] + 2)
1885 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2),
1886 "Unexpected value\n");
1887 else if (bufSize == pubKeys[i].encodedNoNull[1] + 2)
1888 ok(!memcmp(buf, pubKeys[i].encodedNoNull,
1889 pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n");
1895 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected,
1896 const CERT_PUBLIC_KEY_INFO *got)
1898 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId),
1899 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId,
1900 got->Algorithm.pszObjId);
1901 ok(expected->Algorithm.Parameters.cbData ==
1902 got->Algorithm.Parameters.cbData,
1903 "Expected parameters of %ld bytes, got %ld\n",
1904 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData);
1905 if (expected->Algorithm.Parameters.cbData)
1906 ok(!memcmp(expected->Algorithm.Parameters.pbData,
1907 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData),
1908 "Unexpected algorithm parameters\n");
1909 ok(expected->PublicKey.cbData == got->PublicKey.cbData,
1910 "Expected public key of %ld bytes, got %ld\n",
1911 expected->PublicKey.cbData, got->PublicKey.cbData);
1912 if (expected->PublicKey.cbData)
1913 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData,
1914 got->PublicKey.cbData), "Unexpected public key value\n");
1917 static void test_decodePublicKeyInfo(DWORD dwEncoding)
1919 static const BYTE bogusPubKeyInfo[] =
1920 "\x30\x22\x30\x0d\x06\x06\x2a\x86\x48\x86\xf7\x0d\x01\x01\x01\x01\x01"
1921 "\x03\x11\x00\x00\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e"
1928 for (i = 0; i < sizeof(pubKeys) / sizeof(pubKeys[0]); i++)
1930 /* The NULL form decodes to the decoded member */
1931 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1932 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1933 NULL, (BYTE *)&buf, &bufSize);
1934 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1937 comparePublicKeyInfo(&pubKeys[i].decoded,
1938 (CERT_PUBLIC_KEY_INFO *)buf);
1941 /* The non-NULL form decodes to the original */
1942 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1943 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2,
1944 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
1945 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
1948 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf);
1952 /* Test with bogus (not valid DER) parameters */
1953 ret = CryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO,
1954 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
1955 NULL, (BYTE *)&buf, &bufSize);
1956 ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
1957 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
1960 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00,
1961 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
1962 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30,
1963 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30,
1964 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
1965 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02,
1966 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
1967 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
1968 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
1969 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
1970 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02,
1971 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
1972 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f,
1973 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
1974 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 };
1975 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30,
1976 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
1977 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
1978 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
1979 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
1980 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
1981 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
1982 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30,
1983 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31,
1984 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36,
1985 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
1986 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14,
1987 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
1988 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
1989 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
1990 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
1991 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22,
1992 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30,
1993 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30,
1994 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30,
1995 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20,
1996 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01,
1997 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01,
1998 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2000 /* This is the encoded form of the printable string "Juan Lang" */
2001 static const BYTE encodedCommonName[] = { 0x30, 0x15, 0x31, 0x13, 0x30, 0x11,
2002 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c,
2003 0x61, 0x6e, 0x67, 0x00 };
2004 static const BYTE serialNum[] = { 0x01 };
2006 static void test_encodeCertToBeSigned(DWORD dwEncoding)
2011 CERT_INFO info = { 0 };
2013 /* Test with NULL pvStructInfo */
2014 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL,
2015 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2016 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2017 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2018 /* Test with a V1 cert */
2019 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2020 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2021 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2024 ok(size == v1Cert[1] + 2, "Expected size %d, got %ld\n",
2025 v1Cert[1] + 2, size);
2026 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n");
2030 info.dwVersion = CERT_V2;
2031 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2032 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2033 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2036 ok(size == sizeof(v2Cert), "Expected size %d, got %ld\n",
2037 sizeof(v2Cert), size);
2038 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n");
2042 info.dwVersion = CERT_V3;
2043 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2044 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2045 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2048 ok(size == sizeof(v3Cert), "Expected size %d, got %ld\n",
2049 sizeof(v3Cert), size);
2050 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n");
2053 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but
2054 * API doesn't prevent it)
2056 info.dwVersion = CERT_V1;
2057 info.cExtension = 1;
2058 info.rgExtension = &criticalExt;
2059 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2060 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2061 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2064 ok(size == sizeof(v1CertWithConstraints), "Expected size %d, got %ld\n",
2065 sizeof(v1CertWithConstraints), size);
2066 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n");
2069 /* test v1 cert with a serial number */
2070 info.SerialNumber.cbData = sizeof(serialNum);
2071 info.SerialNumber.pbData = (BYTE *)serialNum;
2072 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2073 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2076 ok(size == sizeof(v1CertWithSerial), "Expected size %d, got %ld\n",
2077 sizeof(v1CertWithSerial), size);
2078 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n");
2081 /* Test v1 cert with an issuer name, a subject name, and a serial number */
2082 info.Issuer.cbData = sizeof(encodedCommonName);
2083 info.Issuer.pbData = (BYTE *)encodedCommonName;
2084 info.Subject.cbData = sizeof(encodedCommonName);
2085 info.Subject.pbData = (BYTE *)encodedCommonName;
2086 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info,
2087 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2090 ok(size == sizeof(bigCert), "Expected size %d, got %ld\n",
2091 sizeof(bigCert), size);
2092 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n");
2095 /* for now, I let more interesting tests be done for each subcomponent,
2096 * rather than retesting them all here.
2100 static void test_decodeCertToBeSigned(DWORD dwEncoding)
2102 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert,
2103 v1CertWithConstraints, v1CertWithSerial };
2108 /* Test with NULL pbEncoded */
2109 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0,
2110 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2111 ok(!ret && GetLastError() == CRYPT_E_ASN1_EOD,
2112 "Expected CRYPT_E_ASN1_EOD, got %08lx\n", GetLastError());
2113 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1,
2114 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2115 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2116 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2117 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT, because at a
2118 * minimum a cert must have a non-zero serial number, an issuer, and a
2121 for (i = 0; i < sizeof(corruptCerts) / sizeof(corruptCerts[0]); i++)
2123 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED,
2124 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2125 (BYTE *)&buf, &size);
2126 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2127 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2129 /* Now check with serial number, subject and issuer specified */
2130 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert,
2131 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2132 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2135 CERT_INFO *info = (CERT_INFO *)buf;
2137 ok(size >= sizeof(CERT_INFO), "Expected size at least %d, got %ld\n",
2138 sizeof(CERT_INFO), size);
2139 ok(info->SerialNumber.cbData == 1,
2140 "Expected serial number size 1, got %ld\n", info->SerialNumber.cbData);
2141 ok(*info->SerialNumber.pbData == *serialNum,
2142 "Expected serial number %d, got %d\n", *serialNum,
2143 *info->SerialNumber.pbData);
2144 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2145 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2146 info->Issuer.cbData);
2147 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2148 "Unexpected issuer\n");
2149 ok(info->Subject.cbData == sizeof(encodedCommonName),
2150 "Expected subject of %d bytes, got %ld\n", sizeof(encodedCommonName),
2151 info->Subject.cbData);
2152 ok(!memcmp(info->Subject.pbData, encodedCommonName,
2153 info->Subject.cbData), "Unexpected subject\n");
2158 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd,
2161 static const BYTE signedBigCert[] = {
2162 0x30, 0x81, 0x93, 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 0x00, 0x30,
2163 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2164 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 0x18, 0x0f,
2165 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2166 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30,
2167 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06,
2168 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61,
2169 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3,
2170 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff,
2171 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2172 0x00, 0x03, 0x11, 0x00, 0x0f, 0x0e, 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07,
2173 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 };
2175 static void test_encodeCert(DWORD dwEncoding)
2177 /* Note the SignatureAlgorithm must match that in the encoded cert. Note
2178 * also that bigCert is a NULL-terminated string, so don't count its
2179 * last byte (otherwise the signed cert won't decode.)
2181 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert },
2182 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } };
2187 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT, &info,
2188 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &bufSize);
2189 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2192 ok(bufSize == sizeof(signedBigCert), "Expected size %d, got %ld\n",
2193 sizeof(signedBigCert), bufSize);
2194 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n");
2199 static void test_decodeCert(DWORD dwEncoding)
2205 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert,
2206 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2207 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2210 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf;
2212 ok(info->ToBeSigned.cbData == sizeof(bigCert),
2213 "Expected cert to be %d bytes, got %ld\n", sizeof(bigCert),
2214 info->ToBeSigned.cbData);
2215 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData),
2216 "Unexpected cert\n");
2217 ok(info->Signature.cbData == sizeof(hash),
2218 "Expected signature size %d, got %ld\n", sizeof(hash),
2219 info->Signature.cbData);
2220 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData),
2221 "Unexpected signature\n");
2226 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 };
2227 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15,
2228 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69,
2229 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2230 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02,
2232 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13,
2233 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65,
2234 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 };
2235 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0,
2236 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77,
2237 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11,
2238 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71,
2239 0x2e, 0x6f, 0x72, 0x67 };
2240 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE |
2241 CRL_REASON_AFFILIATION_CHANGED;
2243 static void test_encodeCRLDistPoints(DWORD dwEncoding)
2245 CRL_DIST_POINTS_INFO info = { 0 };
2246 CRL_DIST_POINT point = { { 0 } };
2247 CERT_ALT_NAME_ENTRY entry = { 0 };
2252 /* Test with an empty info */
2253 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2254 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2255 ok(!ret && GetLastError() == HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER),
2256 "Expected HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER), got %08lx\n",
2258 /* Test with one empty dist point */
2259 info.cDistPoint = 1;
2260 info.rgDistPoint = &point;
2261 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2262 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2265 ok(size == sizeof(emptyDistPoint), "Expected size %d, got %ld\n",
2266 sizeof(emptyDistPoint), size);
2267 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n");
2270 /* A dist point with an invalid name */
2271 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2272 entry.dwAltNameChoice = CERT_ALT_NAME_URL;
2273 U(entry).pwszURL = (LPWSTR)nihongoURL;
2274 U(point.DistPointName).FullName.cAltEntry = 1;
2275 U(point.DistPointName).FullName.rgAltEntry = &entry;
2276 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2277 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2278 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING,
2279 "Expected CRYPT_E_INVALID_IA5_STRING, got %08lx\n", GetLastError());
2280 /* The first invalid character is at index 7 */
2281 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7,
2282 "Expected invalid char at index 7, got %ld\n",
2283 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size));
2284 /* A dist point with (just) a valid name */
2285 U(entry).pwszURL = (LPWSTR)url;
2286 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2287 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2290 ok(size == sizeof(distPointWithUrl), "Expected size %d, got %ld\n",
2291 sizeof(distPointWithUrl), size);
2292 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n");
2295 /* A dist point with (just) reason flags */
2296 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME;
2297 point.ReasonFlags.cbData = sizeof(crlReason);
2298 point.ReasonFlags.pbData = (LPBYTE)&crlReason;
2299 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2300 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2303 ok(size == sizeof(distPointWithReason), "Expected size %d, got %ld\n",
2304 sizeof(distPointWithReason), size);
2305 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n");
2308 /* A dist point with just an issuer */
2309 point.ReasonFlags.cbData = 0;
2310 point.CRLIssuer.cAltEntry = 1;
2311 point.CRLIssuer.rgAltEntry = &entry;
2312 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2313 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2316 ok(size == sizeof(distPointWithIssuer), "Expected size %d, got %ld\n",
2317 sizeof(distPointWithIssuer), size);
2318 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n");
2321 /* A dist point with both a name and an issuer */
2322 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME;
2323 ret = CryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info,
2324 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2327 ok(size == sizeof(distPointWithUrlAndIssuer),
2328 "Expected size %d, got %ld\n", sizeof(distPointWithUrlAndIssuer),
2330 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n");
2335 static void test_decodeCRLDistPoints(DWORD dwEncoding)
2340 PCRL_DIST_POINTS_INFO info;
2341 PCRL_DIST_POINT point;
2342 PCERT_ALT_NAME_ENTRY entry;
2344 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2345 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2346 (BYTE *)&buf, &size);
2349 info = (PCRL_DIST_POINTS_INFO)buf;
2350 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2351 "Expected size at least %d, got %ld\n",
2352 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2353 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2355 point = info->rgDistPoint;
2356 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME,
2357 "Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
2358 point->DistPointName.dwDistPointNameChoice);
2359 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2360 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2363 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2364 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2365 (BYTE *)&buf, &size);
2368 info = (PCRL_DIST_POINTS_INFO)buf;
2369 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2370 "Expected size at least %d, got %ld\n",
2371 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2372 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2374 point = info->rgDistPoint;
2375 ok(point->DistPointName.dwDistPointNameChoice ==
2376 CRL_DIST_POINT_FULL_NAME,
2377 "Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
2378 point->DistPointName.dwDistPointNameChoice);
2379 ok(U(point->DistPointName).FullName.cAltEntry == 1,
2380 "Expected 1 name entry, got %ld\n",
2381 U(point->DistPointName).FullName.cAltEntry);
2382 entry = U(point->DistPointName).FullName.rgAltEntry;
2383 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2384 "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2385 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2386 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2387 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2390 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2391 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG,
2392 NULL, (BYTE *)&buf, &size);
2395 info = (PCRL_DIST_POINTS_INFO)buf;
2396 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2397 "Expected size at least %d, got %ld\n",
2398 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2399 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2401 point = info->rgDistPoint;
2402 ok(point->DistPointName.dwDistPointNameChoice ==
2403 CRL_DIST_POINT_NO_NAME,
2404 "Expected CRL_DIST_POINT_NO_NAME, got %ld\n",
2405 point->DistPointName.dwDistPointNameChoice);
2406 ok(point->ReasonFlags.cbData == sizeof(crlReason),
2407 "Expected reason length\n");
2408 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)),
2409 "Unexpected reason\n");
2410 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n");
2413 ret = CryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS,
2414 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2,
2415 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2418 info = (PCRL_DIST_POINTS_INFO)buf;
2419 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT),
2420 "Expected size at least %d, got %ld\n",
2421 sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), size);
2422 ok(info->cDistPoint == 1, "Expected 1 dist points, got %ld\n",
2424 point = info->rgDistPoint;
2425 ok(point->DistPointName.dwDistPointNameChoice ==
2426 CRL_DIST_POINT_FULL_NAME,
2427 "Expected CRL_DIST_POINT_FULL_NAME, got %ld\n",
2428 point->DistPointName.dwDistPointNameChoice);
2429 ok(U(point->DistPointName).FullName.cAltEntry == 1,
2430 "Expected 1 name entry, got %ld\n",
2431 U(point->DistPointName).FullName.cAltEntry);
2432 entry = U(point->DistPointName).FullName.rgAltEntry;
2433 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2434 "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2435 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2436 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n");
2437 ok(point->CRLIssuer.cAltEntry == 1,
2438 "Expected 1 issuer entry, got %ld\n", point->CRLIssuer.cAltEntry);
2439 entry = point->CRLIssuer.rgAltEntry;
2440 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL,
2441 "Expected CERT_ALT_NAME_URL, got %ld\n", entry->dwAltNameChoice);
2442 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n");
2447 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f,
2448 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2450 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06,
2451 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30,
2452 0x30, 0x30, 0x30, 0x30, 0x5a };
2453 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00,
2454 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a,
2455 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31,
2456 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30,
2458 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02,
2459 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03,
2460 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18,
2461 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30,
2462 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36,
2463 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2464 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06,
2465 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13,
2466 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f,
2467 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30,
2468 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36,
2469 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a };
2470 static const BYTE v1CRLWithExt[] = { 0x30, 0x5a, 0x30, 0x02, 0x06, 0x00, 0x30,
2471 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a,
2472 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31, 0x36,
2473 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a,
2474 0x30, 0x2c, 0x30, 0x2a, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31,
2475 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x14,
2476 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30,
2477 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 };
2479 static void test_encodeCRLToBeSigned(DWORD dwEncoding)
2484 CRL_INFO info = { 0 };
2485 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 };
2487 /* Test with a V1 CRL */
2488 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2489 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2490 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2493 ok(size == sizeof(v1CRL), "Expected size %d, got %ld\n",
2494 sizeof(v1CRL), size);
2495 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n");
2499 info.dwVersion = CRL_V2;
2500 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2501 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2502 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2505 ok(size == v2CRL[1] + 2, "Expected size %d, got %ld\n",
2506 v2CRL[1] + 2, size);
2507 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n");
2510 /* v1 CRL with a name */
2511 info.dwVersion = CRL_V1;
2512 info.Issuer.cbData = sizeof(encodedCommonName);
2513 info.Issuer.pbData = (BYTE *)encodedCommonName;
2514 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2515 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2516 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2519 ok(size == sizeof(v1CRLWithIssuer), "Expected size %d, got %ld\n",
2520 sizeof(v1CRLWithIssuer), size);
2521 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n");
2524 /* v1 CRL with a name and a NULL entry pointer */
2526 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2527 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2528 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION,
2529 "Expected STATUS_ACCESS_VIOLATION, got %08lx\n", GetLastError());
2530 /* now set an empty entry */
2531 info.rgCRLEntry = &entry;
2532 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2533 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2536 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry),
2537 "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEmptyEntry),
2539 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size),
2540 "Got unexpected value\n");
2543 /* an entry with a serial number */
2544 entry.SerialNumber.cbData = sizeof(serialNum);
2545 entry.SerialNumber.pbData = (BYTE *)serialNum;
2546 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2547 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2550 ok(size == sizeof(v1CRLWithIssuerAndEntry),
2551 "Expected size %d, got %ld\n", sizeof(v1CRLWithIssuerAndEntry), size);
2552 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size),
2553 "Got unexpected value\n");
2556 /* and finally, an entry with an extension */
2557 entry.cExtension = 1;
2558 entry.rgExtension = &criticalExt;
2559 ret = CryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info,
2560 CRYPT_ENCODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2561 ok(ret, "CryptEncodeObjectEx failed: %08lx\n", GetLastError());
2564 ok(size == sizeof(v1CRLWithExt), "Expected size %d, got %ld\n",
2565 sizeof(v1CRLWithExt), size);
2566 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n");
2571 static void test_decodeCRLToBeSigned(DWORD dwEncoding)
2573 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL };
2578 for (i = 0; i < sizeof(corruptCRLs) / sizeof(corruptCRLs[0]); i++)
2580 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2581 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2582 (BYTE *)&buf, &size);
2583 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT),
2584 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2586 /* at a minimum, a CRL must contain an issuer: */
2587 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2588 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL,
2589 (BYTE *)&buf, &size);
2590 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2593 CRL_INFO *info = (CRL_INFO *)buf;
2595 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2596 sizeof(CRL_INFO), size);
2597 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %ld\n",
2599 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2600 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2601 info->Issuer.cbData);
2602 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2603 "Unexpected issuer\n");
2606 /* check decoding with an empty CRL entry */
2607 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2608 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2,
2609 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2610 todo_wine ok(!ret && GetLastError() == CRYPT_E_ASN1_CORRUPT,
2611 "Expected CRYPT_E_ASN1_CORRUPT, got %08lx\n", GetLastError());
2612 /* with a real CRL entry */
2613 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2614 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2,
2615 CRYPT_DECODE_ALLOC_FLAG, NULL, (BYTE *)&buf, &size);
2616 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2619 CRL_INFO *info = (CRL_INFO *)buf;
2622 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2623 sizeof(CRL_INFO), size);
2624 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2626 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2627 entry = info->rgCRLEntry;
2628 ok(entry->SerialNumber.cbData == 1,
2629 "Expected serial number size 1, got %ld\n",
2630 entry->SerialNumber.cbData);
2631 ok(*entry->SerialNumber.pbData == *serialNum,
2632 "Expected serial number %d, got %d\n", *serialNum,
2633 *entry->SerialNumber.pbData);
2634 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2635 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2636 info->Issuer.cbData);
2637 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2638 "Unexpected issuer\n");
2640 /* and finally, with an extension */
2641 ret = CryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED,
2642 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG,
2643 NULL, (BYTE *)&buf, &size);
2644 ok(ret, "CryptDecodeObjectEx failed: %08lx\n", GetLastError());
2647 CRL_INFO *info = (CRL_INFO *)buf;
2650 ok(size >= sizeof(CRL_INFO), "Expected size at least %d, got %ld\n",
2651 sizeof(CRL_INFO), size);
2652 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %ld\n",
2654 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n");
2655 entry = info->rgCRLEntry;
2656 ok(entry->SerialNumber.cbData == 1,
2657 "Expected serial number size 1, got %ld\n",
2658 entry->SerialNumber.cbData);
2659 ok(*entry->SerialNumber.pbData == *serialNum,
2660 "Expected serial number %d, got %d\n", *serialNum,
2661 *entry->SerialNumber.pbData);
2662 ok(info->Issuer.cbData == sizeof(encodedCommonName),
2663 "Expected issuer of %d bytes, got %ld\n", sizeof(encodedCommonName),
2664 info->Issuer.cbData);
2665 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData),
2666 "Unexpected issuer\n");
2667 /* Oddly, the extensions don't seem to be decoded. Is this just an MS
2668 * bug, or am I missing something?
2670 ok(info->cExtension == 0, "Expected 0 extensions, got %ld\n",
2675 /* Free *pInfo with HeapFree */
2676 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo)
2683 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL);
2685 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size);
2686 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2687 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2688 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL,
2690 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2691 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2692 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL,
2694 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2695 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2696 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
2697 0, NULL, NULL, &size);
2698 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2699 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2700 /* Test with no key */
2701 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL,
2702 0, NULL, NULL, &size);
2703 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08lx\n",
2705 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key);
2706 ok(ret, "CryptGenKey failed: %08lx\n", GetLastError());
2709 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING,
2710 NULL, 0, NULL, NULL, &size);
2711 ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n", GetLastError());
2712 *pInfo = HeapAlloc(GetProcessHeap(), 0, size);
2715 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE,
2716 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size);
2717 ok(ret, "CryptExportPublicKeyInfoEx failed: %08lx\n",
2721 /* By default (we passed NULL as the OID) the OID is
2724 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA),
2725 "Expected %s, got %s\n", szOID_RSA_RSA,
2726 (*pInfo)->Algorithm.pszObjId);
2732 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info)
2738 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL);
2739 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key);
2740 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL);
2741 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
2744 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key);
2745 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2746 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
2747 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key);
2748 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND,
2749 "Expected ERROR_FILE_NOT_FOUND, got %08lx\n", GetLastError());
2750 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL,
2752 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER,
2753 "Expected ERROR_INVALID_PARAMETER, got %08lx\n", GetLastError());
2754 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL,
2756 ok(ret, "CryptImportPublicKeyInfoEx failed: %08lx\n", GetLastError());
2757 CryptDestroyKey(key);
2760 static const char cspName[] = "WineCryptTemp";
2762 static void testPortPublicKeyInfo(void)
2766 PCERT_PUBLIC_KEY_INFO info = NULL;
2768 /* Just in case a previous run failed, delete this thing */
2769 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
2770 CRYPT_DELETEKEYSET);
2771 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
2774 testExportPublicKey(csp, &info);
2775 testImportPublicKey(csp, info);
2777 HeapFree(GetProcessHeap(), 0, info);
2778 CryptReleaseContext(csp, 0);
2779 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV, PROV_RSA_FULL,
2780 CRYPT_DELETEKEYSET);
2785 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING,
2786 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING };
2789 for (i = 0; i < sizeof(encodings) / sizeof(encodings[0]); i++)
2791 test_encodeInt(encodings[i]);
2792 test_decodeInt(encodings[i]);
2793 test_encodeEnumerated(encodings[i]);
2794 test_decodeEnumerated(encodings[i]);
2795 test_encodeFiletime(encodings[i]);
2796 test_decodeFiletime(encodings[i]);
2797 test_encodeName(encodings[i]);
2798 test_decodeName(encodings[i]);
2799 test_encodeAltName(encodings[i]);
2800 test_decodeAltName(encodings[i]);
2801 test_encodeOctets(encodings[i]);
2802 test_decodeOctets(encodings[i]);
2803 test_encodeBits(encodings[i]);
2804 test_decodeBits(encodings[i]);
2805 test_encodeBasicConstraints(encodings[i]);
2806 test_decodeBasicConstraints(encodings[i]);
2807 test_encodeRsaPublicKey(encodings[i]);
2808 test_decodeRsaPublicKey(encodings[i]);
2809 test_encodeSequenceOfAny(encodings[i]);
2810 test_decodeSequenceOfAny(encodings[i]);
2811 test_encodeExtensions(encodings[i]);
2812 test_decodeExtensions(encodings[i]);
2813 test_encodePublicKeyInfo(encodings[i]);
2814 test_decodePublicKeyInfo(encodings[i]);
2815 test_encodeCertToBeSigned(encodings[i]);
2816 test_decodeCertToBeSigned(encodings[i]);
2817 test_encodeCert(encodings[i]);
2818 test_decodeCert(encodings[i]);
2819 test_encodeCRLDistPoints(encodings[i]);
2820 test_decodeCRLDistPoints(encodings[i]);
2821 test_encodeCRLToBeSigned(encodings[i]);
2822 test_decodeCRLToBeSigned(encodings[i]);
2824 testPortPublicKeyInfo();