1 /* 2 * Unit test suite for crypt32.dll's CryptEncodeObjectEx/CryptDecodeObjectEx 3 * 4 * Copyright 2005 Juan Lang 5 * 6 * This library is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU Lesser General Public 8 * License as published by the Free Software Foundation; either 9 * version 2.1 of the License, or (at your option) any later version. 10 * 11 * This library is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 * Lesser General Public License for more details. 15 * 16 * You should have received a copy of the GNU Lesser General Public 17 * License along with this library; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 19 */ 20 #include <stdio.h> 21 #include <stdarg.h> 22 #include <windef.h> 23 #include <winbase.h> 24 #include <winerror.h> 25 #include <wincrypt.h> 26 #include <snmp.h> 27 28 #include "wine/test.h" 29 30 31 static BOOL (WINAPI *pCryptDecodeObjectEx)(DWORD,LPCSTR,const BYTE*,DWORD,DWORD,PCRYPT_DECODE_PARA,void*,DWORD*); 32 static BOOL (WINAPI *pCryptEncodeObjectEx)(DWORD,LPCSTR,const void*,DWORD,PCRYPT_ENCODE_PARA,void*,DWORD*); 33 34 struct encodedInt 35 { 36 int val; 37 const BYTE *encoded; 38 }; 39 40 static const BYTE bin1[] = {0x02,0x01,0x01}; 41 static const BYTE bin2[] = {0x02,0x01,0x7f}; 42 static const BYTE bin3[] = {0x02,0x02,0x00,0x80}; 43 static const BYTE bin4[] = {0x02,0x02,0x01,0x00}; 44 static const BYTE bin5[] = {0x02,0x01,0x80}; 45 static const BYTE bin6[] = {0x02,0x02,0xff,0x7f}; 46 static const BYTE bin7[] = {0x02,0x04,0xba,0xdd,0xf0,0x0d}; 47 48 static const struct encodedInt ints[] = { 49 { 1, bin1 }, 50 { 127, bin2 }, 51 { 128, bin3 }, 52 { 256, bin4 }, 53 { -128, bin5 }, 54 { -129, bin6 }, 55 { 0xbaddf00d, bin7 }, 56 }; 57 58 struct encodedBigInt 59 { 60 const BYTE *val; 61 const BYTE *encoded; 62 const BYTE *decoded; 63 }; 64 65 static const BYTE bin8[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0}; 66 static const BYTE bin9[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0}; 67 static const BYTE bin10[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0}; 68 69 static const BYTE bin11[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0}; 70 static const BYTE bin12[] = {0x02,0x09,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0}; 71 static const BYTE bin13[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0}; 72 73 static const struct encodedBigInt bigInts[] = { 74 { bin8, bin9, bin10 }, 75 { bin11, bin12, bin13 }, 76 }; 77 78 static const BYTE bin14[] = {0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0}; 79 static const BYTE bin15[] = {0x02,0x0a,0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0}; 80 static const BYTE bin16[] = {0x08,0x07,0x06,0x05,0x04,0x03,0x02,0x01,0xff,0xff,0xff,0}; 81 static const BYTE bin17[] = {0x02,0x0c,0x00,0xff,0xff,0xff,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0}; 82 83 /* Decoded is the same as original, so don't bother storing a separate copy */ 84 static const struct encodedBigInt bigUInts[] = { 85 { bin14, bin15, NULL }, 86 { bin16, bin17, NULL }, 87 }; 88 89 static void test_encodeInt(DWORD dwEncoding) 90 { 91 DWORD bufSize = 0; 92 int i; 93 BOOL ret; 94 CRYPT_INTEGER_BLOB blob; 95 BYTE *buf = NULL; 96 97 /* CryptEncodeObjectEx with NULL bufSize crashes.. 98 ret = pCryptEncodeObjectEx(3, X509_INTEGER, &ints[0].val, 0, NULL, NULL, 99 NULL); 100 */ 101 /* check bogus encoding */ 102 ret = pCryptEncodeObjectEx(0, X509_INTEGER, &ints[0].val, 0, NULL, NULL, 103 &bufSize); 104 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 105 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); 106 if (0) 107 { 108 /* check with NULL integer buffer. Windows XP incorrectly returns an 109 * NTSTATUS (crashes on win9x). 110 */ 111 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, NULL, NULL, 112 &bufSize); 113 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 114 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); 115 } 116 for (i = 0; i < ARRAY_SIZE(ints); i++) 117 { 118 /* encode as normal integer */ 119 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 0, 120 NULL, NULL, &bufSize); 121 ok(ret, "Expected success, got %d\n", GetLastError()); 122 ret = pCryptEncodeObjectEx(dwEncoding, X509_INTEGER, &ints[i].val, 123 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 124 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError()); 125 if (ret) 126 { 127 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n", 128 buf[0]); 129 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n", 130 buf[1], ints[i].encoded[1]); 131 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1), 132 "Encoded value of 0x%08x didn't match expected\n", ints[i].val); 133 LocalFree(buf); 134 } 135 /* encode as multibyte integer */ 136 blob.cbData = sizeof(ints[i].val); 137 blob.pbData = (BYTE *)&ints[i].val; 138 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob, 139 0, NULL, NULL, &bufSize); 140 ok(ret, "Expected success, got %d\n", GetLastError()); 141 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob, 142 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 143 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError()); 144 if (ret) 145 { 146 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n", 147 buf[0]); 148 ok(buf[1] == ints[i].encoded[1], "Got length %d, expected %d\n", 149 buf[1], ints[i].encoded[1]); 150 ok(!memcmp(buf + 1, ints[i].encoded + 1, ints[i].encoded[1] + 1), 151 "Encoded value of 0x%08x didn't match expected\n", ints[i].val); 152 LocalFree(buf); 153 } 154 } 155 /* encode a couple bigger ints, just to show it's little-endian and leading 156 * sign bytes are dropped 157 */ 158 for (i = 0; i < ARRAY_SIZE(bigInts); i++) 159 { 160 blob.cbData = strlen((const char*)bigInts[i].val); 161 blob.pbData = (BYTE *)bigInts[i].val; 162 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob, 163 0, NULL, NULL, &bufSize); 164 ok(ret, "Expected success, got %d\n", GetLastError()); 165 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, &blob, 166 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 167 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError()); 168 if (ret) 169 { 170 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n", 171 buf[0]); 172 ok(buf[1] == bigInts[i].encoded[1], "Got length %d, expected %d\n", 173 buf[1], bigInts[i].encoded[1]); 174 ok(!memcmp(buf + 1, bigInts[i].encoded + 1, 175 bigInts[i].encoded[1] + 1), 176 "Encoded value didn't match expected\n"); 177 LocalFree(buf); 178 } 179 } 180 /* and, encode some uints */ 181 for (i = 0; i < ARRAY_SIZE(bigUInts); i++) 182 { 183 blob.cbData = strlen((const char*)bigUInts[i].val); 184 blob.pbData = (BYTE*)bigUInts[i].val; 185 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob, 186 0, NULL, NULL, &bufSize); 187 ok(ret, "Expected success, got %d\n", GetLastError()); 188 ret = pCryptEncodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, &blob, 189 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 190 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError()); 191 if (ret) 192 { 193 ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n", 194 buf[0]); 195 ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n", 196 buf[1], bigUInts[i].encoded[1]); 197 ok(!memcmp(buf + 1, bigUInts[i].encoded + 1, 198 bigUInts[i].encoded[1] + 1), 199 "Encoded value didn't match expected\n"); 200 LocalFree(buf); 201 } 202 } 203 } 204 205 static void test_decodeInt(DWORD dwEncoding) 206 { 207 static const BYTE bigInt[] = { 2, 5, 0xff, 0xfe, 0xff, 0xfe, 0xff }; 208 static const BYTE testStr[] = { 0x16, 4, 't', 'e', 's', 't' }; 209 static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 }; 210 static const BYTE bigBogus[] = { 0x02, 0x84, 0x01, 0xff, 0xff, 0xf9 }; 211 static const BYTE extraBytes[] = { 2, 1, 1, 0, 0, 0, 0 }; 212 BYTE *buf = NULL; 213 DWORD bufSize = 0; 214 int i; 215 BOOL ret; 216 217 /* CryptDecodeObjectEx with NULL bufSize crashes.. 218 ret = pCryptDecodeObjectEx(3, X509_INTEGER, &ints[0].encoded, 219 ints[0].encoded[1] + 2, 0, NULL, NULL, NULL); 220 */ 221 /* check bogus encoding */ 222 ret = pCryptDecodeObjectEx(3, X509_INTEGER, (BYTE *)&ints[0].encoded, 223 ints[0].encoded[1] + 2, 0, NULL, NULL, &bufSize); 224 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 225 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); 226 /* check with NULL integer buffer */ 227 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, NULL, 0, 0, NULL, NULL, 228 &bufSize); 229 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || 230 GetLastError() == OSS_BAD_ARG /* Win9x */), 231 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError()); 232 /* check with a valid, but too large, integer */ 233 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, bigInt, bigInt[1] + 2, 234 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 235 ok((!ret && GetLastError() == CRYPT_E_ASN1_LARGE) || 236 broken(ret) /* Win9x */, 237 "Expected CRYPT_E_ASN1_LARGE, got %d\n", GetLastError()); 238 /* check with a DER-encoded string */ 239 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, testStr, testStr[1] + 2, 240 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 241 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || 242 GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ), 243 "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n", 244 GetLastError()); 245 for (i = 0; i < ARRAY_SIZE(ints); i++) 246 { 247 /* When the output buffer is NULL, this always succeeds */ 248 SetLastError(0xdeadbeef); 249 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, 250 ints[i].encoded, ints[i].encoded[1] + 2, 0, NULL, NULL, 251 &bufSize); 252 ok(ret && GetLastError() == NOERROR, 253 "Expected success and NOERROR, got %d\n", GetLastError()); 254 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, 255 ints[i].encoded, ints[i].encoded[1] + 2, 256 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 257 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError()); 258 ok(bufSize == sizeof(int), "Wrong size %d\n", bufSize); 259 ok(buf != NULL, "Expected allocated buffer\n"); 260 if (ret) 261 { 262 ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n", 263 ints[i].val, *(int *)buf); 264 LocalFree(buf); 265 } 266 } 267 for (i = 0; i < ARRAY_SIZE(bigInts); i++) 268 { 269 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, 270 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 0, NULL, NULL, 271 &bufSize); 272 ok(ret && GetLastError() == NOERROR, 273 "Expected success and NOERROR, got %d\n", GetLastError()); 274 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, 275 bigInts[i].encoded, bigInts[i].encoded[1] + 2, 276 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 277 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError()); 278 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize); 279 ok(buf != NULL, "Expected allocated buffer\n"); 280 if (ret) 281 { 282 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf; 283 284 ok(blob->cbData == strlen((const char*)bigInts[i].decoded), 285 "Expected len %d, got %d\n", lstrlenA((const char*)bigInts[i].decoded), 286 blob->cbData); 287 ok(!memcmp(blob->pbData, bigInts[i].decoded, blob->cbData), 288 "Unexpected value\n"); 289 LocalFree(buf); 290 } 291 } 292 for (i = 0; i < ARRAY_SIZE(bigUInts); i++) 293 { 294 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, 295 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 0, NULL, NULL, 296 &bufSize); 297 ok(ret && GetLastError() == NOERROR, 298 "Expected success and NOERROR, got %d\n", GetLastError()); 299 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_UINT, 300 bigUInts[i].encoded, bigUInts[i].encoded[1] + 2, 301 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 302 ok(ret, "CryptDecodeObjectEx failed: %d\n", GetLastError()); 303 ok(bufSize >= sizeof(CRYPT_INTEGER_BLOB), "Wrong size %d\n", bufSize); 304 ok(buf != NULL, "Expected allocated buffer\n"); 305 if (ret) 306 { 307 CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf; 308 309 ok(blob->cbData == strlen((const char*)bigUInts[i].val), 310 "Expected len %d, got %d\n", lstrlenA((const char*)bigUInts[i].val), 311 blob->cbData); 312 ok(!memcmp(blob->pbData, bigUInts[i].val, blob->cbData), 313 "Unexpected value\n"); 314 LocalFree(buf); 315 } 316 } 317 /* Decode the value 1 with long-form length */ 318 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, longForm, 319 sizeof(longForm), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 320 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 321 if (ret) 322 { 323 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf); 324 LocalFree(buf); 325 } 326 /* check with extra bytes at the end */ 327 ret = pCryptDecodeObjectEx(dwEncoding, X509_INTEGER, extraBytes, 328 sizeof(extraBytes), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 329 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 330 if (ret) 331 { 332 ok(*(int *)buf == 1, "Expected 1, got %d\n", *(int *)buf); 333 LocalFree(buf); 334 } 335 /* Try to decode some bogus large items */ 336 /* The buffer size is smaller than the encoded length, so this should fail 337 * with CRYPT_E_ASN1_EOD if it's being decoded. 338 * Under XP it fails with CRYPT_E_ASN1_LARGE, which means there's a limit 339 * on the size decoded, but in ME it fails with CRYPT_E_ASN1_EOD or crashes. 340 * So this test unfortunately isn't useful. 341 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, tooBig, 342 0x7fffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 343 ok(!ret && GetLastError() == CRYPT_E_ASN1_LARGE, 344 "Expected CRYPT_E_ASN1_LARGE, got %08x\n", GetLastError()); 345 */ 346 /* This will try to decode the buffer and overflow it, check that it's 347 * caught. 348 */ 349 if (0) 350 { 351 /* a large buffer isn't guaranteed to crash, it depends on memory allocation order */ 352 ret = pCryptDecodeObjectEx(dwEncoding, X509_MULTI_BYTE_INTEGER, bigBogus, 353 0x01ffffff, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 354 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 355 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); 356 } 357 } 358 359 static const BYTE bin18[] = {0x0a,0x01,0x01}; 360 static const BYTE bin19[] = {0x0a,0x05,0x00,0xff,0xff,0xff,0x80}; 361 362 /* These are always encoded unsigned, and aren't constrained to be any 363 * particular value 364 */ 365 static const struct encodedInt enums[] = { 366 { 1, bin18 }, 367 { -128, bin19 }, 368 }; 369 370 /* X509_CRL_REASON_CODE is also an enumerated type, but it's #defined to 371 * X509_ENUMERATED. 372 */ 373 static const LPCSTR enumeratedTypes[] = { X509_ENUMERATED, 374 szOID_CRL_REASON_CODE }; 375 376 static void test_encodeEnumerated(DWORD dwEncoding) 377 { 378 DWORD i, j; 379 380 for (i = 0; i < ARRAY_SIZE(enumeratedTypes); i++) 381 { 382 for (j = 0; j < ARRAY_SIZE(enums); j++) 383 { 384 BOOL ret; 385 BYTE *buf = NULL; 386 DWORD bufSize = 0; 387 388 ret = pCryptEncodeObjectEx(dwEncoding, enumeratedTypes[i], 389 &enums[j].val, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, 390 &bufSize); 391 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError()); 392 if (ret) 393 { 394 ok(buf[0] == 0xa, 395 "Got unexpected type %d for enumerated (expected 0xa)\n", 396 buf[0]); 397 ok(buf[1] == enums[j].encoded[1], 398 "Got length %d, expected %d\n", buf[1], enums[j].encoded[1]); 399 ok(!memcmp(buf + 1, enums[j].encoded + 1, 400 enums[j].encoded[1] + 1), 401 "Encoded value of 0x%08x didn't match expected\n", 402 enums[j].val); 403 LocalFree(buf); 404 } 405 } 406 } 407 } 408 409 static void test_decodeEnumerated(DWORD dwEncoding) 410 { 411 DWORD i, j; 412 413 for (i = 0; i < ARRAY_SIZE(enumeratedTypes); i++) 414 { 415 for (j = 0; j < ARRAY_SIZE(enums); j++) 416 { 417 BOOL ret; 418 DWORD bufSize = sizeof(int); 419 int val; 420 421 ret = pCryptDecodeObjectEx(dwEncoding, enumeratedTypes[i], 422 enums[j].encoded, enums[j].encoded[1] + 2, 0, NULL, 423 &val, &bufSize); 424 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 425 ok(bufSize == sizeof(int), 426 "Got unexpected size %d for enumerated\n", bufSize); 427 ok(val == enums[j].val, "Unexpected value %d, expected %d\n", 428 val, enums[j].val); 429 } 430 } 431 } 432 433 struct encodedFiletime 434 { 435 SYSTEMTIME sysTime; 436 const BYTE *encodedTime; 437 }; 438 439 static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType, 440 const struct encodedFiletime *time) 441 { 442 FILETIME ft = { 0 }; 443 BYTE *buf = NULL; 444 DWORD bufSize = 0; 445 BOOL ret; 446 447 ret = SystemTimeToFileTime(&time->sysTime, &ft); 448 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError()); 449 ret = pCryptEncodeObjectEx(dwEncoding, structType, &ft, 450 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 451 /* years other than 1950-2050 are not allowed for encodings other than 452 * X509_CHOICE_OF_TIME. 453 */ 454 if (structType == X509_CHOICE_OF_TIME || 455 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050)) 456 { 457 ok(ret, "CryptEncodeObjectEx failed: %d (0x%08x)\n", GetLastError(), 458 GetLastError()); 459 ok(buf != NULL, "Expected an allocated buffer\n"); 460 if (ret) 461 { 462 ok(buf[0] == time->encodedTime[0], 463 "Expected type 0x%02x, got 0x%02x\n", time->encodedTime[0], 464 buf[0]); 465 ok(buf[1] == time->encodedTime[1], "Expected %d bytes, got %d\n", 466 time->encodedTime[1], bufSize); 467 ok(!memcmp(time->encodedTime + 2, buf + 2, time->encodedTime[1]), 468 "Got unexpected value for time encoding\n"); 469 LocalFree(buf); 470 } 471 } 472 else 473 ok((!ret && GetLastError() == CRYPT_E_BAD_ENCODE) || 474 broken(GetLastError() == ERROR_SUCCESS), 475 "Expected CRYPT_E_BAD_ENCODE, got 0x%08x\n", GetLastError()); 476 } 477 478 static const char *printSystemTime(const SYSTEMTIME *st) 479 { 480 static char buf[64]; 481 482 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st->wMonth, st->wDay, 483 st->wYear, st->wHour, st->wMinute, st->wSecond, st->wMilliseconds); 484 return buf; 485 } 486 487 static const char *printFileTime(const FILETIME *ft) 488 { 489 static char buf[64]; 490 SYSTEMTIME st; 491 492 FileTimeToSystemTime(ft, &st); 493 sprintf(buf, "%02d-%02d-%04d %02d:%02d:%02d.%03d", st.wMonth, st.wDay, 494 st.wYear, st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); 495 return buf; 496 } 497 498 static void compareTime(const SYSTEMTIME *expected, const FILETIME *got) 499 { 500 SYSTEMTIME st; 501 502 FileTimeToSystemTime(got, &st); 503 ok((expected->wYear == st.wYear && 504 expected->wMonth == st.wMonth && 505 expected->wDay == st.wDay && 506 expected->wHour == st.wHour && 507 expected->wMinute == st.wMinute && 508 expected->wSecond == st.wSecond && 509 abs(expected->wMilliseconds - st.wMilliseconds) <= 1) || 510 /* Some Windows systems only seem to be accurate in their time decoding to 511 * within about an hour. 512 */ 513 broken(expected->wYear == st.wYear && 514 expected->wMonth == st.wMonth && 515 expected->wDay == st.wDay && 516 abs(expected->wHour - st.wHour) <= 1), 517 "Got unexpected value for time decoding:\nexpected %s, got %s\n", 518 printSystemTime(expected), printFileTime(got)); 519 } 520 521 static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType, 522 const struct encodedFiletime *time) 523 { 524 FILETIME ft = { 0 }; 525 DWORD size = sizeof(ft); 526 BOOL ret; 527 528 ret = pCryptDecodeObjectEx(dwEncoding, structType, time->encodedTime, 529 time->encodedTime[1] + 2, 0, NULL, &ft, &size); 530 /* years other than 1950-2050 are not allowed for encodings other than 531 * X509_CHOICE_OF_TIME. 532 */ 533 if (structType == X509_CHOICE_OF_TIME || 534 (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050)) 535 { 536 ok(ret || broken(GetLastError() == OSS_DATA_ERROR), 537 "CryptDecodeObjectEx failed: %d (0x%08x)\n", GetLastError(), 538 GetLastError()); 539 if (ret) 540 compareTime(&time->sysTime, &ft); 541 } 542 else 543 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || 544 GetLastError() == OSS_PDU_MISMATCH /* Win9x */ ), 545 "Expected CRYPT_E_ASN1_BADTAG or OSS_PDU_MISMATCH, got %08x\n", 546 GetLastError()); 547 } 548 549 static const BYTE bin20[] = { 550 0x17,0x0d,'0','5','0','6','0','6','1','6','1','0','0','0','Z'}; 551 static const BYTE bin21[] = { 552 0x18,0x0f,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','Z'}; 553 static const BYTE bin22[] = { 554 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'}; 555 556 static const struct encodedFiletime times[] = { 557 { { 2005, 6, 1, 6, 16, 10, 0, 0 }, bin20 }, 558 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin21 }, 559 { { 2145, 6, 1, 6, 16, 10, 0, 0 }, bin22 }, 560 }; 561 562 static void test_encodeFiletime(DWORD dwEncoding) 563 { 564 DWORD i; 565 566 for (i = 0; i < ARRAY_SIZE(times); i++) 567 { 568 testTimeEncoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]); 569 testTimeEncoding(dwEncoding, PKCS_UTC_TIME, ×[i]); 570 testTimeEncoding(dwEncoding, szOID_RSA_signingTime, ×[i]); 571 } 572 } 573 574 static const BYTE bin23[] = { 575 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'}; 576 static const BYTE bin24[] = { 577 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'}; 578 static const BYTE bin25[] = { 579 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','+','0','1','0','0'}; 580 static const BYTE bin26[] = { 581 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','0','0'}; 582 static const BYTE bin27[] = { 583 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','-','0','1','1','5'}; 584 static const BYTE bin28[] = { 585 0x18,0x0a,'2','1','4','5','0','6','0','6','1','6'}; 586 static const BYTE bin29[] = { 587 0x17,0x0a,'4','5','0','6','0','6','1','6','1','0'}; 588 static const BYTE bin30[] = { 589 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'}; 590 static const BYTE bin31[] = { 591 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','+','0','1'}; 592 static const BYTE bin32[] = { 593 0x17,0x0d,'4','5','0','6','0','6','1','6','1','0','-','0','1'}; 594 static const BYTE bin33[] = { 595 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','+','0','1','0','0'}; 596 static const BYTE bin34[] = { 597 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'}; 598 static const BYTE bin35[] = { 599 0x17,0x08, '4','5','0','6','0','6','1','6'}; 600 static const BYTE bin36[] = { 601 0x18,0x0f, 'a','a','a','a','a','a','a','a','a','a','a','a','a','a','Z'}; 602 static const BYTE bin37[] = { 603 0x18,0x04, '2','1','4','5'}; 604 static const BYTE bin38[] = { 605 0x18,0x08, '2','1','4','5','0','6','0','6'}; 606 607 static void test_decodeFiletime(DWORD dwEncoding) 608 { 609 static const struct encodedFiletime otherTimes[] = { 610 { { 1945, 6, 1, 6, 16, 10, 0, 0 }, bin23 }, 611 { { 1945, 6, 1, 6, 16, 10, 0, 999 }, bin24 }, 612 { { 1945, 6, 1, 6, 17, 10, 0, 0 }, bin25 }, 613 { { 1945, 6, 1, 6, 15, 10, 0, 0 }, bin26 }, 614 { { 1945, 6, 1, 6, 14, 55, 0, 0 }, bin27 }, 615 { { 2145, 6, 1, 6, 16, 0, 0, 0 }, bin28 }, 616 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin29 }, 617 { { 2045, 6, 1, 6, 16, 10, 0, 0 }, bin30 }, 618 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin31 }, 619 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin32 }, 620 { { 2045, 6, 1, 6, 17, 10, 0, 0 }, bin33 }, 621 { { 2045, 6, 1, 6, 15, 10, 0, 0 }, bin34 }, 622 }; 623 /* An oddball case that succeeds in Windows, but doesn't seem correct 624 { { 2145, 6, 1, 2, 11, 31, 0, 0 }, "\x18" "\x13" "21450606161000-9999" }, 625 */ 626 static const unsigned char *bogusTimes[] = { 627 /* oddly, this succeeds on Windows, with year 2765 628 "\x18" "\x0f" "21r50606161000Z", 629 */ 630 bin35, 631 bin36, 632 bin37, 633 bin38, 634 }; 635 DWORD i, size; 636 FILETIME ft1 = { 0 }, ft2 = { 0 }; 637 BOOL ret; 638 639 /* Check bogus length with non-NULL buffer */ 640 ret = SystemTimeToFileTime(×[0].sysTime, &ft1); 641 ok(ret, "SystemTimeToFileTime failed: %d\n", GetLastError()); 642 size = 1; 643 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME, 644 times[0].encodedTime, times[0].encodedTime[1] + 2, 0, NULL, &ft2, &size); 645 ok(!ret && GetLastError() == ERROR_MORE_DATA, 646 "Expected ERROR_MORE_DATA, got %d\n", GetLastError()); 647 /* Normal tests */ 648 for (i = 0; i < ARRAY_SIZE(times); i++) 649 { 650 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, ×[i]); 651 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, ×[i]); 652 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, ×[i]); 653 } 654 for (i = 0; i < ARRAY_SIZE(otherTimes); i++) 655 { 656 testTimeDecoding(dwEncoding, X509_CHOICE_OF_TIME, &otherTimes[i]); 657 testTimeDecoding(dwEncoding, PKCS_UTC_TIME, &otherTimes[i]); 658 testTimeDecoding(dwEncoding, szOID_RSA_signingTime, &otherTimes[i]); 659 } 660 for (i = 0; i < ARRAY_SIZE(bogusTimes); i++) 661 { 662 size = sizeof(ft1); 663 ret = pCryptDecodeObjectEx(dwEncoding, X509_CHOICE_OF_TIME, 664 bogusTimes[i], bogusTimes[i][1] + 2, 0, NULL, &ft1, &size); 665 ok((!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT || 666 GetLastError() == OSS_DATA_ERROR /* Win9x */)) || 667 broken(ret), /* Win9x and NT4 for bin38 */ 668 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n", 669 GetLastError()); 670 } 671 } 672 673 static const char commonName[] = "Juan Lang"; 674 static const char surName[] = "Lang"; 675 676 static const BYTE emptySequence[] = { 0x30, 0 }; 677 static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 }; 678 static const BYTE twoRDNs[] = { 679 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04, 680 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03, 681 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0}; 682 static const BYTE encodedTwoRDNs[] = { 683 0x30,0x2e,0x31,0x2c,0x30,0x2a,0x06,0x03,0x55,0x04,0x03,0x30,0x23,0x31,0x21, 684 0x30,0x0c,0x06,0x03,0x55,0x04,0x04,0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30, 685 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61, 686 0x6e,0x67,0x00, 687 }; 688 689 static const BYTE us[] = { 0x55, 0x53 }; 690 static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f, 691 0x74, 0x61 }; 692 static const BYTE minneapolis[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x61, 0x70, 693 0x6f, 0x6c, 0x69, 0x73 }; 694 static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61, 695 0x76, 0x65, 0x72, 0x73 }; 696 static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76, 697 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 }; 698 static const BYTE localhostAttr[] = { 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x68, 0x6f, 699 0x73, 0x74 }; 700 static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64, 701 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d }; 702 703 #define RDNA(arr) oid_ ## arr, CERT_RDN_PRINTABLE_STRING, { sizeof(arr), (LPBYTE)arr } 704 #define RDNIA5(arr) oid_ ## arr, CERT_RDN_IA5_STRING, { sizeof(arr), (LPBYTE)arr } 705 706 static CHAR oid_us[] = "2.5.4.6", 707 oid_minnesota[] = "2.5.4.8", 708 oid_minneapolis[] = "2.5.4.7", 709 oid_codeweavers[] = "2.5.4.10", 710 oid_wine[] = "2.5.4.11", 711 oid_localhostAttr[] = "2.5.4.3", 712 oid_aric[] = "1.2.840.113549.1.9.1"; 713 static CERT_RDN_ATTR rdnAttrs[] = { { RDNA(us) }, 714 { RDNA(minnesota) }, 715 { RDNA(minneapolis) }, 716 { RDNA(codeweavers) }, 717 { RDNA(wine) }, 718 { RDNA(localhostAttr) }, 719 { RDNIA5(aric) } }; 720 static CERT_RDN_ATTR decodedRdnAttrs[] = { { RDNA(us) }, 721 { RDNA(localhostAttr) }, 722 { RDNA(minnesota) }, 723 { RDNA(minneapolis) }, 724 { RDNA(codeweavers) }, 725 { RDNA(wine) }, 726 { RDNIA5(aric) } }; 727 728 #undef RDNIA5 729 #undef RDNA 730 731 static const BYTE encodedRDNAttrs[] = { 732 0x30,0x81,0x96,0x31,0x81,0x93,0x30,0x09,0x06,0x03,0x55,0x04,0x06,0x13,0x02,0x55, 733 0x53,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x6c,0x6f,0x63,0x61,0x6c,0x68, 734 0x6f,0x73,0x74,0x30,0x10,0x06,0x03,0x55,0x04,0x08,0x13,0x09,0x4d,0x69,0x6e,0x6e, 735 0x65,0x73,0x6f,0x74,0x61,0x30,0x12,0x06,0x03,0x55,0x04,0x07,0x13,0x0b,0x4d,0x69, 736 0x6e,0x6e,0x65,0x61,0x70,0x6f,0x6c,0x69,0x73,0x30,0x12,0x06,0x03,0x55,0x04,0x0a, 737 0x13,0x0b,0x43,0x6f,0x64,0x65,0x57,0x65,0x61,0x76,0x65,0x72,0x73,0x30,0x17,0x06, 738 0x03,0x55,0x04,0x0b,0x13,0x10,0x57,0x69,0x6e,0x65,0x20,0x44,0x65,0x76,0x65,0x6c, 739 0x6f,0x70,0x6d,0x65,0x6e,0x74,0x30,0x21,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d, 740 0x01,0x09,0x01,0x16,0x14,0x61,0x72,0x69,0x63,0x40,0x63,0x6f,0x64,0x65,0x77,0x65, 741 0x61,0x76,0x65,0x72,0x73,0x2e,0x63,0x6f,0x6d 742 }; 743 744 static void test_encodeName(DWORD dwEncoding) 745 { 746 CERT_RDN_ATTR attrs[2]; 747 CERT_RDN rdn; 748 CERT_NAME_INFO info; 749 static CHAR oid_common_name[] = szOID_COMMON_NAME, 750 oid_sur_name[] = szOID_SUR_NAME; 751 BYTE *buf = NULL; 752 DWORD size = 0; 753 BOOL ret; 754 755 if (0) 756 { 757 /* Test with NULL pvStructInfo (crashes on win9x) */ 758 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, NULL, 759 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 760 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 761 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); 762 } 763 /* Test with empty CERT_NAME_INFO */ 764 info.cRDN = 0; 765 info.rgRDN = NULL; 766 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info, 767 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 768 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 769 if (ret) 770 { 771 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)), 772 "Got unexpected encoding for empty name\n"); 773 LocalFree(buf); 774 } 775 if (0) 776 { 777 /* Test with bogus CERT_RDN (crashes on win9x) */ 778 info.cRDN = 1; 779 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info, 780 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 781 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 782 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); 783 } 784 /* Test with empty CERT_RDN */ 785 rdn.cRDNAttr = 0; 786 rdn.rgRDNAttr = NULL; 787 info.cRDN = 1; 788 info.rgRDN = &rdn; 789 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info, 790 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 791 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 792 if (ret) 793 { 794 ok(!memcmp(buf, emptyRDNs, sizeof(emptyRDNs)), 795 "Got unexpected encoding for empty RDN array\n"); 796 LocalFree(buf); 797 } 798 if (0) 799 { 800 /* Test with bogus attr array (crashes on win9x) */ 801 rdn.cRDNAttr = 1; 802 rdn.rgRDNAttr = NULL; 803 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info, 804 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 805 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 806 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); 807 } 808 /* oddly, a bogus OID is accepted by Windows XP; not testing. 809 attrs[0].pszObjId = "bogus"; 810 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING; 811 attrs[0].Value.cbData = sizeof(commonName); 812 attrs[0].Value.pbData = commonName; 813 rdn.cRDNAttr = 1; 814 rdn.rgRDNAttr = attrs; 815 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info, 816 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 817 ok(!ret, "Expected failure, got success\n"); 818 */ 819 /* Check with two CERT_RDN_ATTRs. Note DER encoding forces the order of 820 * the encoded attributes to be swapped. 821 */ 822 attrs[0].pszObjId = oid_common_name; 823 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING; 824 attrs[0].Value.cbData = sizeof(commonName); 825 attrs[0].Value.pbData = (BYTE *)commonName; 826 attrs[1].pszObjId = oid_sur_name; 827 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING; 828 attrs[1].Value.cbData = sizeof(surName); 829 attrs[1].Value.pbData = (BYTE *)surName; 830 rdn.cRDNAttr = 2; 831 rdn.rgRDNAttr = attrs; 832 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info, 833 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 834 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 835 if (ret) 836 { 837 ok(!memcmp(buf, twoRDNs, sizeof(twoRDNs)), 838 "Got unexpected encoding for two RDN array\n"); 839 LocalFree(buf); 840 } 841 /* A name can be "encoded" with previously encoded RDN attrs. */ 842 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB; 843 attrs[0].Value.pbData = (LPBYTE)twoRDNs; 844 attrs[0].Value.cbData = sizeof(twoRDNs); 845 rdn.cRDNAttr = 1; 846 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info, 847 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 848 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 849 if (ret) 850 { 851 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size); 852 ok(!memcmp(buf, encodedTwoRDNs, size), 853 "Unexpected value for re-encoded two RDN array\n"); 854 LocalFree(buf); 855 } 856 /* CERT_RDN_ANY_TYPE is too vague for X509_NAMEs, check the return */ 857 rdn.cRDNAttr = 1; 858 attrs[0].dwValueType = CERT_RDN_ANY_TYPE; 859 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME, &info, 860 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 861 ok(!ret && GetLastError() == E_INVALIDARG, 862 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 863 /* Test a more complex name */ 864 rdn.cRDNAttr = ARRAY_SIZE(rdnAttrs); 865 rdn.rgRDNAttr = rdnAttrs; 866 info.cRDN = 1; 867 info.rgRDN = &rdn; 868 buf = NULL; 869 size = 0; 870 ret = pCryptEncodeObjectEx(X509_ASN_ENCODING, X509_NAME, &info, 871 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 872 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 873 if (ret) 874 { 875 ok(size == sizeof(encodedRDNAttrs), "Wrong size %d\n", size); 876 ok(!memcmp(buf, encodedRDNAttrs, size), "Unexpected value\n"); 877 LocalFree(buf); 878 } 879 } 880 881 static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 }; 882 static WCHAR surNameW[] = { 'L','a','n','g',0 }; 883 884 static const BYTE twoRDNsNoNull[] = { 885 0x30,0x21,0x31,0x1f,0x30,0x0b,0x06,0x03,0x55,0x04,0x04,0x13,0x04,0x4c,0x61, 886 0x6e,0x67,0x30,0x10,0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e, 887 0x20,0x4c,0x61,0x6e,0x67 }; 888 static const BYTE anyType[] = { 889 0x30,0x2f,0x31,0x2d,0x30,0x2b,0x06,0x03,0x55,0x04,0x03,0x1e,0x24,0x23,0x30, 890 0x21,0x31,0x0c,0x30,0x03,0x06,0x04,0x55,0x13,0x04,0x4c,0x05,0x6e,0x61,0x00, 891 0x67,0x11,0x30,0x03,0x06,0x04,0x55,0x13,0x03,0x4a,0x0a,0x61,0x75,0x20,0x6e, 892 0x61,0x4c,0x67,0x6e }; 893 894 static void test_encodeUnicodeName(DWORD dwEncoding) 895 { 896 CERT_RDN_ATTR attrs[2]; 897 CERT_RDN rdn; 898 CERT_NAME_INFO info; 899 static CHAR oid_common_name[] = szOID_COMMON_NAME, 900 oid_sur_name[] = szOID_SUR_NAME; 901 BYTE *buf = NULL; 902 DWORD size = 0; 903 BOOL ret; 904 905 if (0) 906 { 907 /* Test with NULL pvStructInfo (crashes on win9x) */ 908 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, NULL, 909 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 910 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 911 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); 912 } 913 /* Test with empty CERT_NAME_INFO */ 914 info.cRDN = 0; 915 info.rgRDN = NULL; 916 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info, 917 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 918 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 919 if (ret) 920 { 921 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)), 922 "Got unexpected encoding for empty name\n"); 923 LocalFree(buf); 924 } 925 /* Check with one CERT_RDN_ATTR, that has an invalid character for the 926 * encoding (the NULL). 927 */ 928 attrs[0].pszObjId = oid_common_name; 929 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING; 930 attrs[0].Value.cbData = sizeof(commonNameW); 931 attrs[0].Value.pbData = (BYTE *)commonNameW; 932 rdn.cRDNAttr = 1; 933 rdn.rgRDNAttr = attrs; 934 info.cRDN = 1; 935 info.rgRDN = &rdn; 936 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info, 937 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 938 ok(!ret && GetLastError() == CRYPT_E_INVALID_PRINTABLE_STRING, 939 "Expected CRYPT_E_INVALID_PRINTABLE_STRING, got %08x\n", GetLastError()); 940 ok(size == 9, "Unexpected error index %08x\n", size); 941 /* Check with two NULL-terminated CERT_RDN_ATTRs. Note DER encoding 942 * forces the order of the encoded attributes to be swapped. 943 */ 944 attrs[0].pszObjId = oid_common_name; 945 attrs[0].dwValueType = CERT_RDN_PRINTABLE_STRING; 946 attrs[0].Value.cbData = 0; 947 attrs[0].Value.pbData = (BYTE *)commonNameW; 948 attrs[1].pszObjId = oid_sur_name; 949 attrs[1].dwValueType = CERT_RDN_PRINTABLE_STRING; 950 attrs[1].Value.cbData = 0; 951 attrs[1].Value.pbData = (BYTE *)surNameW; 952 rdn.cRDNAttr = 2; 953 rdn.rgRDNAttr = attrs; 954 info.cRDN = 1; 955 info.rgRDN = &rdn; 956 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info, 957 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 958 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 959 if (ret) 960 { 961 ok(!memcmp(buf, twoRDNsNoNull, sizeof(twoRDNsNoNull)), 962 "Got unexpected encoding for two RDN array\n"); 963 LocalFree(buf); 964 } 965 /* A name can be "encoded" with previously encoded RDN attrs. */ 966 attrs[0].dwValueType = CERT_RDN_ENCODED_BLOB; 967 attrs[0].Value.pbData = (LPBYTE)twoRDNs; 968 attrs[0].Value.cbData = sizeof(twoRDNs); 969 rdn.cRDNAttr = 1; 970 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info, 971 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 972 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 973 if (ret) 974 { 975 ok(size == sizeof(encodedTwoRDNs), "Unexpected size %d\n", size); 976 ok(!memcmp(buf, encodedTwoRDNs, size), 977 "Unexpected value for re-encoded two RDN array\n"); 978 LocalFree(buf); 979 } 980 /* Unicode names infer the type for CERT_RDN_ANY_TYPE */ 981 rdn.cRDNAttr = 1; 982 attrs[0].dwValueType = CERT_RDN_ANY_TYPE; 983 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME, &info, 984 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 985 todo_wine ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 986 if (ret) 987 { 988 ok(size == sizeof(anyType), "Unexpected size %d\n", size); 989 ok(!memcmp(buf, anyType, size), "Unexpected value\n"); 990 LocalFree(buf); 991 } 992 } 993 994 static void compareNameValues(const CERT_NAME_VALUE *expected, 995 const CERT_NAME_VALUE *got) 996 { 997 if (expected->dwValueType == CERT_RDN_UTF8_STRING && 998 got->dwValueType == CERT_RDN_ENCODED_BLOB) 999 { 1000 win_skip("Can't handle CERT_RDN_UTF8_STRING\n"); 1001 return; 1002 } 1003 1004 ok(got->dwValueType == expected->dwValueType, 1005 "Expected string type %d, got %d\n", expected->dwValueType, 1006 got->dwValueType); 1007 ok(got->Value.cbData == expected->Value.cbData || 1008 got->Value.cbData == expected->Value.cbData - sizeof(WCHAR) /* Win8 */, 1009 "String type %d: unexpected data size, got %d, expected %d\n", 1010 expected->dwValueType, got->Value.cbData, expected->Value.cbData); 1011 if (got->Value.cbData && got->Value.pbData) 1012 ok(!memcmp(got->Value.pbData, expected->Value.pbData, 1013 min(got->Value.cbData, expected->Value.cbData)), 1014 "String type %d: unexpected value\n", expected->dwValueType); 1015 } 1016 1017 static void compareRDNAttrs(const CERT_RDN_ATTR *expected, 1018 const CERT_RDN_ATTR *got) 1019 { 1020 if (expected->pszObjId && *expected->pszObjId) 1021 { 1022 ok(got->pszObjId != NULL, "Expected OID %s, got NULL\n", 1023 expected->pszObjId); 1024 if (got->pszObjId) 1025 { 1026 ok(!strcmp(got->pszObjId, expected->pszObjId), 1027 "Got unexpected OID %s, expected %s\n", got->pszObjId, 1028 expected->pszObjId); 1029 } 1030 } 1031 compareNameValues((const CERT_NAME_VALUE *)&expected->dwValueType, 1032 (const CERT_NAME_VALUE *)&got->dwValueType); 1033 } 1034 1035 static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got) 1036 { 1037 ok(got->cRDNAttr == expected->cRDNAttr, 1038 "Expected %d RDN attrs, got %d\n", expected->cRDNAttr, got->cRDNAttr); 1039 if (got->cRDNAttr) 1040 { 1041 DWORD i; 1042 1043 for (i = 0; i < got->cRDNAttr; i++) 1044 compareRDNAttrs(&expected->rgRDNAttr[i], &got->rgRDNAttr[i]); 1045 } 1046 } 1047 1048 static void compareNames(const CERT_NAME_INFO *expected, 1049 const CERT_NAME_INFO *got) 1050 { 1051 ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n", 1052 expected->cRDN, got->cRDN); 1053 if (got->cRDN) 1054 { 1055 DWORD i; 1056 1057 for (i = 0; i < got->cRDN; i++) 1058 compareRDNs(&expected->rgRDN[i], &got->rgRDN[i]); 1059 } 1060 } 1061 1062 static const BYTE emptyIndefiniteSequence[] = { 0x30,0x80,0x00,0x00 }; 1063 static const BYTE twoRDNsExtraBytes[] = { 1064 0x30,0x23,0x31,0x21,0x30,0x0c,0x06,0x03,0x55,0x04,0x04, 1065 0x13,0x05,0x4c,0x61,0x6e,0x67,0x00,0x30,0x11,0x06,0x03,0x55,0x04,0x03, 1066 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0,0,0,0,0,0}; 1067 1068 static void test_decodeName(DWORD dwEncoding) 1069 { 1070 BYTE *buf = NULL; 1071 DWORD bufSize = 0; 1072 BOOL ret; 1073 CERT_RDN rdn; 1074 CERT_NAME_INFO info = { 1, &rdn }; 1075 1076 /* test empty name */ 1077 bufSize = 0; 1078 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptySequence, 1079 emptySequence[1] + 2, 1080 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL, 1081 &buf, &bufSize); 1082 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1083 /* Interestingly, in Windows, if cRDN is 0, rgRGN may not be NULL. My 1084 * decoder works the same way, so only test the count. 1085 */ 1086 if (ret) 1087 { 1088 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize); 1089 ok(((CERT_NAME_INFO *)buf)->cRDN == 0, 1090 "Expected 0 RDNs in empty info, got %d\n", 1091 ((CERT_NAME_INFO *)buf)->cRDN); 1092 LocalFree(buf); 1093 } 1094 /* test empty name with indefinite-length encoding */ 1095 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyIndefiniteSequence, 1096 sizeof(emptyIndefiniteSequence), CRYPT_DECODE_ALLOC_FLAG, NULL, 1097 &buf, &bufSize); 1098 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1099 if (ret) 1100 { 1101 ok(bufSize == sizeof(CERT_NAME_INFO), "Wrong bufSize %d\n", bufSize); 1102 ok(((CERT_NAME_INFO *)buf)->cRDN == 0, 1103 "Expected 0 RDNs in empty info, got %d\n", 1104 ((CERT_NAME_INFO *)buf)->cRDN); 1105 LocalFree(buf); 1106 } 1107 /* test empty RDN */ 1108 bufSize = 0; 1109 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, emptyRDNs, 1110 emptyRDNs[1] + 2, 1111 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL, 1112 &buf, &bufSize); 1113 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1114 if (ret) 1115 { 1116 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf; 1117 1118 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) && 1119 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0, 1120 "Got unexpected value for empty RDN\n"); 1121 LocalFree(buf); 1122 } 1123 /* test two RDN attrs */ 1124 bufSize = 0; 1125 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNs, 1126 twoRDNs[1] + 2, 1127 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL, 1128 &buf, &bufSize); 1129 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1130 if (ret) 1131 { 1132 static CHAR oid_sur_name[] = szOID_SUR_NAME, 1133 oid_common_name[] = szOID_COMMON_NAME; 1134 1135 CERT_RDN_ATTR attrs[] = { 1136 { oid_sur_name, CERT_RDN_PRINTABLE_STRING, { sizeof(surName), 1137 (BYTE *)surName } }, 1138 { oid_common_name, CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), 1139 (BYTE *)commonName } }, 1140 }; 1141 1142 rdn.cRDNAttr = ARRAY_SIZE(attrs); 1143 rdn.rgRDNAttr = attrs; 1144 compareNames(&info, (CERT_NAME_INFO *)buf); 1145 LocalFree(buf); 1146 } 1147 /* test that two RDN attrs with extra bytes succeeds */ 1148 bufSize = 0; 1149 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME, twoRDNsExtraBytes, 1150 sizeof(twoRDNsExtraBytes), 0, NULL, NULL, &bufSize); 1151 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1152 /* And, a slightly more complicated name */ 1153 buf = NULL; 1154 bufSize = 0; 1155 ret = pCryptDecodeObjectEx(X509_ASN_ENCODING, X509_NAME, encodedRDNAttrs, 1156 sizeof(encodedRDNAttrs), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 1157 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1158 if (ret) 1159 { 1160 rdn.cRDNAttr = ARRAY_SIZE(decodedRdnAttrs); 1161 rdn.rgRDNAttr = decodedRdnAttrs; 1162 compareNames(&info, (CERT_NAME_INFO *)buf); 1163 LocalFree(buf); 1164 } 1165 } 1166 1167 static void test_decodeUnicodeName(DWORD dwEncoding) 1168 { 1169 BYTE *buf = NULL; 1170 DWORD bufSize = 0; 1171 BOOL ret; 1172 CERT_RDN rdn; 1173 CERT_NAME_INFO info = { 1, &rdn }; 1174 1175 /* test empty name */ 1176 bufSize = 0; 1177 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptySequence, 1178 emptySequence[1] + 2, 1179 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL, 1180 &buf, &bufSize); 1181 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1182 if (ret) 1183 { 1184 ok(bufSize == sizeof(CERT_NAME_INFO), 1185 "Got wrong bufSize %d\n", bufSize); 1186 ok(((CERT_NAME_INFO *)buf)->cRDN == 0, 1187 "Expected 0 RDNs in empty info, got %d\n", 1188 ((CERT_NAME_INFO *)buf)->cRDN); 1189 LocalFree(buf); 1190 } 1191 /* test empty RDN */ 1192 bufSize = 0; 1193 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, emptyRDNs, 1194 emptyRDNs[1] + 2, 1195 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL, 1196 &buf, &bufSize); 1197 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1198 if (ret) 1199 { 1200 CERT_NAME_INFO *info = (CERT_NAME_INFO *)buf; 1201 1202 ok(bufSize == sizeof(CERT_NAME_INFO) + sizeof(CERT_RDN) && 1203 info->cRDN == 1 && info->rgRDN && info->rgRDN[0].cRDNAttr == 0, 1204 "Got unexpected value for empty RDN\n"); 1205 LocalFree(buf); 1206 } 1207 /* test two RDN attrs */ 1208 bufSize = 0; 1209 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME, twoRDNsNoNull, 1210 sizeof(twoRDNsNoNull), 1211 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL, 1212 &buf, &bufSize); 1213 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1214 if (ret) 1215 { 1216 static CHAR oid_sur_name[] = szOID_SUR_NAME, 1217 oid_common_name[] = szOID_COMMON_NAME; 1218 1219 CERT_RDN_ATTR attrs[] = { 1220 { oid_sur_name, CERT_RDN_PRINTABLE_STRING, 1221 { lstrlenW(surNameW) * sizeof(WCHAR), (BYTE *)surNameW } }, 1222 { oid_common_name, CERT_RDN_PRINTABLE_STRING, 1223 { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } }, 1224 }; 1225 1226 rdn.cRDNAttr = ARRAY_SIZE(attrs); 1227 rdn.rgRDNAttr = attrs; 1228 compareNames(&info, (CERT_NAME_INFO *)buf); 1229 LocalFree(buf); 1230 } 1231 } 1232 1233 struct EncodedNameValue 1234 { 1235 CERT_NAME_VALUE value; 1236 const BYTE *encoded; 1237 DWORD encodedSize; 1238 }; 1239 1240 static const char bogusIA5[] = "\x80"; 1241 static const char bogusPrintable[] = "~"; 1242 static const char bogusNumeric[] = "A"; 1243 static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 }; 1244 static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 }; 1245 static const BYTE bin44[] = { 0x12,0x02,0x41,0x00 }; 1246 static BYTE octetCommonNameValue[] = { 1247 0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; 1248 static BYTE numericCommonNameValue[] = { 1249 0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; 1250 static BYTE printableCommonNameValue[] = { 1251 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; 1252 static BYTE t61CommonNameValue[] = { 1253 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; 1254 static BYTE videotexCommonNameValue[] = { 1255 0x15,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; 1256 static BYTE ia5CommonNameValue[] = { 1257 0x16,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; 1258 static BYTE graphicCommonNameValue[] = { 1259 0x19,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; 1260 static BYTE visibleCommonNameValue[] = { 1261 0x1a,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; 1262 static BYTE generalCommonNameValue[] = { 1263 0x1b,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; 1264 static BYTE bmpCommonNameValue[] = { 1265 0x1e,0x14,0x00,0x4a,0x00,0x75,0x00,0x61,0x00,0x6e,0x00,0x20,0x00,0x4c,0x00, 1266 0x61,0x00,0x6e,0x00,0x67,0x00,0x00 }; 1267 static BYTE utf8CommonNameValue[] = { 1268 0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; 1269 static char embedded_null[] = "foo\0com"; 1270 static BYTE ia5EmbeddedNull[] = { 1271 0x16,0x07,0x66,0x6f,0x6f,0x00,0x63,0x6f,0x6d }; 1272 1273 static struct EncodedNameValue nameValues[] = { 1274 { { CERT_RDN_OCTET_STRING, { sizeof(commonName), (BYTE *)commonName } }, 1275 octetCommonNameValue, sizeof(octetCommonNameValue) }, 1276 { { CERT_RDN_NUMERIC_STRING, { sizeof(commonName), (BYTE *)commonName } }, 1277 numericCommonNameValue, sizeof(numericCommonNameValue) }, 1278 { { CERT_RDN_PRINTABLE_STRING, { sizeof(commonName), (BYTE *)commonName } }, 1279 printableCommonNameValue, sizeof(printableCommonNameValue) }, 1280 { { CERT_RDN_T61_STRING, { sizeof(commonName), (BYTE *)commonName } }, 1281 t61CommonNameValue, sizeof(t61CommonNameValue) }, 1282 { { CERT_RDN_VIDEOTEX_STRING, { sizeof(commonName), (BYTE *)commonName } }, 1283 videotexCommonNameValue, sizeof(videotexCommonNameValue) }, 1284 { { CERT_RDN_IA5_STRING, { sizeof(commonName), (BYTE *)commonName } }, 1285 ia5CommonNameValue, sizeof(ia5CommonNameValue) }, 1286 { { CERT_RDN_GRAPHIC_STRING, { sizeof(commonName), (BYTE *)commonName } }, 1287 graphicCommonNameValue, sizeof(graphicCommonNameValue) }, 1288 { { CERT_RDN_VISIBLE_STRING, { sizeof(commonName), (BYTE *)commonName } }, 1289 visibleCommonNameValue, sizeof(visibleCommonNameValue) }, 1290 { { CERT_RDN_GENERAL_STRING, { sizeof(commonName), (BYTE *)commonName } }, 1291 generalCommonNameValue, sizeof(generalCommonNameValue) }, 1292 { { CERT_RDN_BMP_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } }, 1293 bmpCommonNameValue, sizeof(bmpCommonNameValue) }, 1294 { { CERT_RDN_UTF8_STRING, { sizeof(commonNameW), (BYTE *)commonNameW } }, 1295 utf8CommonNameValue, sizeof(utf8CommonNameValue) }, 1296 /* The following tests succeed under Windows, but really should fail, 1297 * they contain characters that are illegal for the encoding. I'm 1298 * including them to justify my lazy encoding. 1299 */ 1300 { { CERT_RDN_IA5_STRING, { sizeof(bogusIA5), (BYTE *)bogusIA5 } }, bin42, 1301 sizeof(bin42) }, 1302 { { CERT_RDN_PRINTABLE_STRING, { sizeof(bogusPrintable), 1303 (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) }, 1304 { { CERT_RDN_NUMERIC_STRING, { sizeof(bogusNumeric), (BYTE *)bogusNumeric } }, 1305 bin44, sizeof(bin44) }, 1306 }; 1307 /* This is kept separate, because the decoding doesn't return to the original 1308 * value. 1309 */ 1310 static struct EncodedNameValue embeddedNullNameValue = { 1311 { CERT_RDN_IA5_STRING, { sizeof(embedded_null) - 1, (BYTE *)embedded_null } }, 1312 ia5EmbeddedNull, sizeof(ia5EmbeddedNull) }; 1313 1314 static void test_encodeNameValue(DWORD dwEncoding) 1315 { 1316 BYTE *buf = NULL; 1317 DWORD size = 0, i; 1318 BOOL ret; 1319 CERT_NAME_VALUE value = { 0, { 0, NULL } }; 1320 1321 value.dwValueType = CERT_RDN_ENCODED_BLOB; 1322 value.Value.pbData = printableCommonNameValue; 1323 value.Value.cbData = sizeof(printableCommonNameValue); 1324 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, &value, 1325 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1326 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 1327 if (ret) 1328 { 1329 ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n", 1330 size); 1331 ok(!memcmp(buf, printableCommonNameValue, size), 1332 "Unexpected encoding\n"); 1333 LocalFree(buf); 1334 } 1335 for (i = 0; i < ARRAY_SIZE(nameValues); i++) 1336 { 1337 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, 1338 &nameValues[i].value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1339 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */, 1340 "Type %d: CryptEncodeObjectEx failed: %08x\n", 1341 nameValues[i].value.dwValueType, GetLastError()); 1342 if (ret) 1343 { 1344 ok(size == nameValues[i].encodedSize, 1345 "Expected size %d, got %d\n", nameValues[i].encodedSize, size); 1346 ok(!memcmp(buf, nameValues[i].encoded, size), 1347 "Got unexpected encoding\n"); 1348 LocalFree(buf); 1349 } 1350 } 1351 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_VALUE, 1352 &embeddedNullNameValue.value, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1353 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH) /* NT4/Win9x */, 1354 "Type %d: CryptEncodeObjectEx failed: %08x\n", 1355 embeddedNullNameValue.value.dwValueType, GetLastError()); 1356 if (ret) 1357 { 1358 ok(size == embeddedNullNameValue.encodedSize, 1359 "Expected size %d, got %d\n", embeddedNullNameValue.encodedSize, size); 1360 ok(!memcmp(buf, embeddedNullNameValue.encoded, size), 1361 "Got unexpected encoding\n"); 1362 LocalFree(buf); 1363 } 1364 } 1365 1366 static void test_decodeNameValue(DWORD dwEncoding) 1367 { 1368 int i; 1369 BYTE *buf = NULL; 1370 DWORD bufSize = 0; 1371 BOOL ret; 1372 1373 for (i = 0; i < ARRAY_SIZE(nameValues); i++) 1374 { 1375 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE, 1376 nameValues[i].encoded, nameValues[i].encoded[1] + 2, 1377 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL, 1378 &buf, &bufSize); 1379 ok(ret, "Value type %d: CryptDecodeObjectEx failed: %08x\n", 1380 nameValues[i].value.dwValueType, GetLastError()); 1381 if (ret) 1382 { 1383 compareNameValues(&nameValues[i].value, 1384 (const CERT_NAME_VALUE *)buf); 1385 LocalFree(buf); 1386 } 1387 } 1388 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_VALUE, 1389 embeddedNullNameValue.encoded, embeddedNullNameValue.encodedSize, 1390 CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_SHARE_OID_STRING_FLAG, NULL, 1391 &buf, &bufSize); 1392 /* Some Windows versions disallow name values with embedded NULLs, so 1393 * either success or failure is acceptable. 1394 */ 1395 if (ret) 1396 { 1397 CERT_NAME_VALUE rdnEncodedValue = { CERT_RDN_ENCODED_BLOB, 1398 { sizeof(ia5EmbeddedNull), ia5EmbeddedNull } }; 1399 CERT_NAME_VALUE embeddedNullValue = { CERT_RDN_IA5_STRING, 1400 { sizeof(embedded_null) - 1, (BYTE *)embedded_null } }; 1401 const CERT_NAME_VALUE *got = (const CERT_NAME_VALUE *)buf, 1402 *expected = NULL; 1403 1404 /* Some Windows versions decode name values with embedded NULLs, 1405 * others leave them encoded, even with the same version of crypt32. 1406 * Accept either. 1407 */ 1408 ok(got->dwValueType == CERT_RDN_ENCODED_BLOB || 1409 got->dwValueType == CERT_RDN_IA5_STRING, 1410 "Expected CERT_RDN_ENCODED_BLOB or CERT_RDN_IA5_STRING, got %d\n", 1411 got->dwValueType); 1412 if (got->dwValueType == CERT_RDN_ENCODED_BLOB) 1413 expected = &rdnEncodedValue; 1414 else if (got->dwValueType == CERT_RDN_IA5_STRING) 1415 expected = &embeddedNullValue; 1416 if (expected) 1417 { 1418 ok(got->Value.cbData == expected->Value.cbData, 1419 "String type %d: unexpected data size, got %d, expected %d\n", 1420 got->dwValueType, got->Value.cbData, expected->Value.cbData); 1421 if (got->Value.cbData && got->Value.pbData) 1422 ok(!memcmp(got->Value.pbData, expected->Value.pbData, 1423 min(got->Value.cbData, expected->Value.cbData)), 1424 "String type %d: unexpected value\n", expected->dwValueType); 1425 } 1426 LocalFree(buf); 1427 } 1428 } 1429 1430 static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 }; 1431 static const BYTE emptyURLExtraBytes[] = { 0x30, 0x02, 0x86, 0x00, 0, 0, 0 }; 1432 static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e', 1433 'h','q','.','o','r','g',0 }; 1434 static const BYTE encodedURL[] = { 0x30, 0x13, 0x86, 0x11, 0x68, 0x74, 1435 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 1436 0x6f, 0x72, 0x67 }; 1437 static const WCHAR nihongoURL[] = { 'h','t','t','p',':','/','/',0x226f, 1438 0x575b, 0 }; 1439 static const WCHAR dnsName[] = { 'w','i','n','e','h','q','.','o','r','g',0 }; 1440 static const BYTE encodedDnsName[] = { 0x30, 0x0c, 0x82, 0x0a, 0x77, 0x69, 1441 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 }; 1442 static const BYTE localhost[] = { 127, 0, 0, 1 }; 1443 static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00, 1444 0x01 }; 1445 static const unsigned char encodedCommonName[] = { 1446 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0}; 1447 static const BYTE encodedOidName[] = { 0x30,0x04,0x88,0x02,0x2a,0x03 }; 1448 static const BYTE encodedDirectoryName[] = { 1449 0x30,0x19,0xa4,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03, 1450 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; 1451 1452 static void test_encodeAltName(DWORD dwEncoding) 1453 { 1454 CERT_ALT_NAME_INFO info = { 0 }; 1455 CERT_ALT_NAME_ENTRY entry = { 0 }; 1456 BYTE *buf = NULL; 1457 DWORD size = 0; 1458 BOOL ret; 1459 char oid[] = "1.2.3"; 1460 1461 /* Test with empty info */ 1462 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info, 1463 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1464 if (ret) 1465 { 1466 ok(size == sizeof(emptySequence), "Wrong size %d\n", size); 1467 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n"); 1468 LocalFree(buf); 1469 } 1470 /* Test with an empty entry */ 1471 info.cAltEntry = 1; 1472 info.rgAltEntry = &entry; 1473 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info, 1474 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1475 ok(!ret && GetLastError() == E_INVALIDARG, 1476 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 1477 /* Test with an empty pointer */ 1478 entry.dwAltNameChoice = CERT_ALT_NAME_URL; 1479 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info, 1480 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1481 if (ret) 1482 { 1483 ok(size == sizeof(emptyURL), "Wrong size %d\n", size); 1484 ok(!memcmp(buf, emptyURL, size), "Unexpected value\n"); 1485 LocalFree(buf); 1486 } 1487 /* Test with a real URL */ 1488 U(entry).pwszURL = (LPWSTR)url; 1489 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info, 1490 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1491 if (ret) 1492 { 1493 ok(size == sizeof(encodedURL), "Wrong size %d\n", size); 1494 ok(!memcmp(buf, encodedURL, size), "Unexpected value\n"); 1495 LocalFree(buf); 1496 } 1497 /* Now with the URL containing an invalid IA5 char */ 1498 U(entry).pwszURL = (LPWSTR)nihongoURL; 1499 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info, 1500 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1501 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING, 1502 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError()); 1503 /* The first invalid character is at index 7 */ 1504 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7, 1505 "Expected invalid char at index 7, got %d\n", 1506 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size)); 1507 /* Now with the URL missing a scheme */ 1508 U(entry).pwszURL = (LPWSTR)dnsName; 1509 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info, 1510 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1511 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 1512 if (ret) 1513 { 1514 /* This succeeds, but it shouldn't, so don't worry about conforming */ 1515 LocalFree(buf); 1516 } 1517 /* Now with a DNS name */ 1518 entry.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME; 1519 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info, 1520 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1521 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 1522 if (ret) 1523 { 1524 ok(size == sizeof(encodedDnsName), "Wrong size %d\n", size); 1525 ok(!memcmp(buf, encodedDnsName, size), "Unexpected value\n"); 1526 LocalFree(buf); 1527 } 1528 /* Test with an IP address */ 1529 entry.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS; 1530 U(entry).IPAddress.cbData = sizeof(localhost); 1531 U(entry).IPAddress.pbData = (LPBYTE)localhost; 1532 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info, 1533 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1534 if (ret) 1535 { 1536 ok(size == sizeof(encodedIPAddr), "Wrong size %d\n", size); 1537 ok(!memcmp(buf, encodedIPAddr, size), "Unexpected value\n"); 1538 LocalFree(buf); 1539 } 1540 /* Test with OID */ 1541 entry.dwAltNameChoice = CERT_ALT_NAME_REGISTERED_ID; 1542 U(entry).pszRegisteredID = oid; 1543 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info, 1544 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1545 if (ret) 1546 { 1547 ok(size == sizeof(encodedOidName), "Wrong size %d\n", size); 1548 ok(!memcmp(buf, encodedOidName, size), "Unexpected value\n"); 1549 LocalFree(buf); 1550 } 1551 /* Test with directory name */ 1552 entry.dwAltNameChoice = CERT_ALT_NAME_DIRECTORY_NAME; 1553 U(entry).DirectoryName.cbData = sizeof(encodedCommonName); 1554 U(entry).DirectoryName.pbData = (LPBYTE)encodedCommonName; 1555 ret = pCryptEncodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, &info, 1556 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1557 if (ret) 1558 { 1559 ok(size == sizeof(encodedDirectoryName), "Wrong size %d\n", size); 1560 ok(!memcmp(buf, encodedDirectoryName, size), "Unexpected value\n"); 1561 LocalFree(buf); 1562 } 1563 } 1564 1565 static void test_decodeAltName(DWORD dwEncoding) 1566 { 1567 static const BYTE unimplementedType[] = { 0x30, 0x06, 0x85, 0x04, 0x7f, 1568 0x00, 0x00, 0x01 }; 1569 static const BYTE bogusType[] = { 0x30, 0x06, 0x89, 0x04, 0x7f, 0x00, 0x00, 1570 0x01 }; 1571 static const BYTE dns_embedded_null[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f, 1572 0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 }; 1573 static const BYTE dns_embedded_bell[] = { 0x30,0x10,0x82,0x0e,0x66,0x6f, 1574 0x6f,0x2e,0x63,0x6f,0x6d,0x07,0x62,0x61,0x64,0x64,0x69,0x65 }; 1575 static const BYTE url_embedded_null[] = { 0x30,0x10,0x86,0x0e,0x66,0x6f, 1576 0x6f,0x2e,0x63,0x6f,0x6d,0x00,0x62,0x61,0x64,0x64,0x69,0x65 }; 1577 BOOL ret; 1578 BYTE *buf = NULL; 1579 DWORD bufSize = 0; 1580 CERT_ALT_NAME_INFO *info; 1581 1582 /* Test some bogus ones first */ 1583 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, 1584 unimplementedType, sizeof(unimplementedType), CRYPT_DECODE_ALLOC_FLAG, 1585 NULL, &buf, &bufSize); 1586 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || 1587 GetLastError() == OSS_DATA_ERROR /* Win9x */), 1588 "Expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n", 1589 GetLastError()); 1590 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, 1591 bogusType, sizeof(bogusType), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, 1592 &bufSize); 1593 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT || 1594 GetLastError() == OSS_DATA_ERROR /* Win9x */), 1595 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n", 1596 GetLastError()); 1597 /* Now expected cases */ 1598 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptySequence, 1599 emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 1600 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1601 if (ret) 1602 { 1603 info = (CERT_ALT_NAME_INFO *)buf; 1604 1605 ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n", 1606 info->cAltEntry); 1607 LocalFree(buf); 1608 } 1609 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, emptyURL, 1610 emptyURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 1611 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1612 if (ret) 1613 { 1614 info = (CERT_ALT_NAME_INFO *)buf; 1615 1616 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n", 1617 info->cAltEntry); 1618 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL, 1619 "Expected CERT_ALT_NAME_URL, got %d\n", 1620 info->rgAltEntry[0].dwAltNameChoice); 1621 ok(U(info->rgAltEntry[0]).pwszURL == NULL || !*U(info->rgAltEntry[0]).pwszURL, 1622 "Expected empty URL\n"); 1623 LocalFree(buf); 1624 } 1625 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, 1626 emptyURLExtraBytes, sizeof(emptyURLExtraBytes), 0, NULL, NULL, &bufSize); 1627 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1628 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedURL, 1629 encodedURL[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 1630 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1631 if (ret) 1632 { 1633 info = (CERT_ALT_NAME_INFO *)buf; 1634 1635 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n", 1636 info->cAltEntry); 1637 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_URL, 1638 "Expected CERT_ALT_NAME_URL, got %d\n", 1639 info->rgAltEntry[0].dwAltNameChoice); 1640 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszURL, url), "Unexpected URL\n"); 1641 LocalFree(buf); 1642 } 1643 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedDnsName, 1644 encodedDnsName[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 1645 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1646 if (ret) 1647 { 1648 info = (CERT_ALT_NAME_INFO *)buf; 1649 1650 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n", 1651 info->cAltEntry); 1652 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME, 1653 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n", 1654 info->rgAltEntry[0].dwAltNameChoice); 1655 ok(!lstrcmpW(U(info->rgAltEntry[0]).pwszDNSName, dnsName), 1656 "Unexpected DNS name\n"); 1657 LocalFree(buf); 1658 } 1659 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedIPAddr, 1660 encodedIPAddr[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 1661 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1662 if (ret) 1663 { 1664 info = (CERT_ALT_NAME_INFO *)buf; 1665 1666 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n", 1667 info->cAltEntry); 1668 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_IP_ADDRESS, 1669 "Expected CERT_ALT_NAME_IP_ADDRESS, got %d\n", 1670 info->rgAltEntry[0].dwAltNameChoice); 1671 ok(U(info->rgAltEntry[0]).IPAddress.cbData == sizeof(localhost), 1672 "Unexpected IP address length %d\n", 1673 U(info->rgAltEntry[0]).IPAddress.cbData); 1674 ok(!memcmp(U(info->rgAltEntry[0]).IPAddress.pbData, localhost, 1675 sizeof(localhost)), "Unexpected IP address value\n"); 1676 LocalFree(buf); 1677 } 1678 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, encodedOidName, 1679 sizeof(encodedOidName), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 1680 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1681 if (ret) 1682 { 1683 info = (CERT_ALT_NAME_INFO *)buf; 1684 1685 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n", 1686 info->cAltEntry); 1687 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_REGISTERED_ID, 1688 "Expected CERT_ALT_NAME_REGISTERED_ID, got %d\n", 1689 info->rgAltEntry[0].dwAltNameChoice); 1690 ok(!strcmp(U(info->rgAltEntry[0]).pszRegisteredID, "1.2.3"), 1691 "Expected OID 1.2.3, got %s\n", U(info->rgAltEntry[0]).pszRegisteredID); 1692 LocalFree(buf); 1693 } 1694 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, 1695 encodedDirectoryName, sizeof(encodedDirectoryName), 1696 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 1697 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1698 if (ret) 1699 { 1700 info = (CERT_ALT_NAME_INFO *)buf; 1701 1702 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n", 1703 info->cAltEntry); 1704 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DIRECTORY_NAME, 1705 "Expected CERT_ALT_NAME_DIRECTORY_NAME, got %d\n", 1706 info->rgAltEntry[0].dwAltNameChoice); 1707 ok(U(info->rgAltEntry[0]).DirectoryName.cbData == 1708 sizeof(encodedCommonName), "Unexpected directory name length %d\n", 1709 U(info->rgAltEntry[0]).DirectoryName.cbData); 1710 ok(!memcmp(U(info->rgAltEntry[0]).DirectoryName.pbData, 1711 encodedCommonName, sizeof(encodedCommonName)), 1712 "Unexpected directory name value\n"); 1713 LocalFree(buf); 1714 } 1715 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, 1716 dns_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG, 1717 NULL, &buf, &bufSize); 1718 /* Fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned about the 1719 * particular failure, just that it doesn't decode. 1720 * It succeeds on (broken) Windows versions that haven't addressed 1721 * embedded NULLs in alternate names. 1722 */ 1723 ok(!ret || broken(ret), "expected failure\n"); 1724 /* An embedded bell character is allowed, however. */ 1725 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, 1726 dns_embedded_bell, sizeof(dns_embedded_bell), CRYPT_DECODE_ALLOC_FLAG, 1727 NULL, &buf, &bufSize); 1728 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1729 if (ret) 1730 { 1731 info = (CERT_ALT_NAME_INFO *)buf; 1732 1733 ok(info->cAltEntry == 1, "Expected 1 entries, got %d\n", 1734 info->cAltEntry); 1735 ok(info->rgAltEntry[0].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME, 1736 "Expected CERT_ALT_NAME_DNS_NAME, got %d\n", 1737 info->rgAltEntry[0].dwAltNameChoice); 1738 LocalFree(buf); 1739 } 1740 ret = pCryptDecodeObjectEx(dwEncoding, X509_ALTERNATE_NAME, 1741 url_embedded_null, sizeof(dns_embedded_null), CRYPT_DECODE_ALLOC_FLAG, 1742 NULL, &buf, &bufSize); 1743 /* Again, fails on WinXP with CRYPT_E_ASN1_RULE. I'm not too concerned 1744 * about the particular failure, just that it doesn't decode. 1745 * It succeeds on (broken) Windows versions that haven't addressed 1746 * embedded NULLs in alternate names. 1747 */ 1748 ok(!ret || broken(ret), "expected failure\n"); 1749 } 1750 1751 struct UnicodeExpectedError 1752 { 1753 DWORD valueType; 1754 LPCWSTR str; 1755 DWORD errorIndex; 1756 DWORD error; 1757 }; 1758 1759 static const WCHAR oneW[] = { '1',0 }; 1760 static const WCHAR aW[] = { 'a',0 }; 1761 static const WCHAR quoteW[] = { '"', 0 }; 1762 1763 static struct UnicodeExpectedError unicodeErrors[] = { 1764 { CERT_RDN_ANY_TYPE, oneW, 0, CRYPT_E_NOT_CHAR_STRING }, 1765 { CERT_RDN_ENCODED_BLOB, oneW, 0, CRYPT_E_NOT_CHAR_STRING }, 1766 { CERT_RDN_OCTET_STRING, oneW, 0, CRYPT_E_NOT_CHAR_STRING }, 1767 { CERT_RDN_NUMERIC_STRING, aW, 0, CRYPT_E_INVALID_NUMERIC_STRING }, 1768 { CERT_RDN_PRINTABLE_STRING, quoteW, 0, CRYPT_E_INVALID_PRINTABLE_STRING }, 1769 { CERT_RDN_IA5_STRING, nihongoURL, 7, CRYPT_E_INVALID_IA5_STRING }, 1770 }; 1771 1772 struct UnicodeExpectedResult 1773 { 1774 DWORD valueType; 1775 LPCWSTR str; 1776 CRYPT_DATA_BLOB encoded; 1777 }; 1778 1779 static BYTE oneNumeric[] = { 0x12, 0x01, 0x31 }; 1780 static BYTE onePrintable[] = { 0x13, 0x01, 0x31 }; 1781 static BYTE oneTeletex[] = { 0x14, 0x01, 0x31 }; 1782 static BYTE oneVideotex[] = { 0x15, 0x01, 0x31 }; 1783 static BYTE oneIA5[] = { 0x16, 0x01, 0x31 }; 1784 static BYTE oneGraphic[] = { 0x19, 0x01, 0x31 }; 1785 static BYTE oneVisible[] = { 0x1a, 0x01, 0x31 }; 1786 static BYTE oneUniversal[] = { 0x1c, 0x04, 0x00, 0x00, 0x00, 0x31 }; 1787 static BYTE oneGeneral[] = { 0x1b, 0x01, 0x31 }; 1788 static BYTE oneBMP[] = { 0x1e, 0x02, 0x00, 0x31 }; 1789 static BYTE oneUTF8[] = { 0x0c, 0x01, 0x31 }; 1790 static BYTE nihongoT61[] = { 0x14,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x6f, 1791 0x5b }; 1792 static BYTE nihongoGeneral[] = { 0x1b,0x09,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, 1793 0x6f,0x5b }; 1794 static BYTE nihongoBMP[] = { 0x1e,0x12,0x00,0x68,0x00,0x74,0x00,0x74,0x00,0x70, 1795 0x00,0x3a,0x00,0x2f,0x00,0x2f,0x22,0x6f,0x57,0x5b }; 1796 static BYTE nihongoUTF8[] = { 0x0c,0x0d,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, 1797 0xe2,0x89,0xaf,0xe5,0x9d,0x9b }; 1798 1799 static struct UnicodeExpectedResult unicodeResults[] = { 1800 { CERT_RDN_NUMERIC_STRING, oneW, { sizeof(oneNumeric), oneNumeric } }, 1801 { CERT_RDN_PRINTABLE_STRING, oneW, { sizeof(onePrintable), onePrintable } }, 1802 { CERT_RDN_TELETEX_STRING, oneW, { sizeof(oneTeletex), oneTeletex } }, 1803 { CERT_RDN_VIDEOTEX_STRING, oneW, { sizeof(oneVideotex), oneVideotex } }, 1804 { CERT_RDN_IA5_STRING, oneW, { sizeof(oneIA5), oneIA5 } }, 1805 { CERT_RDN_GRAPHIC_STRING, oneW, { sizeof(oneGraphic), oneGraphic } }, 1806 { CERT_RDN_VISIBLE_STRING, oneW, { sizeof(oneVisible), oneVisible } }, 1807 { CERT_RDN_UNIVERSAL_STRING, oneW, { sizeof(oneUniversal), oneUniversal } }, 1808 { CERT_RDN_GENERAL_STRING, oneW, { sizeof(oneGeneral), oneGeneral } }, 1809 { CERT_RDN_BMP_STRING, oneW, { sizeof(oneBMP), oneBMP } }, 1810 { CERT_RDN_UTF8_STRING, oneW, { sizeof(oneUTF8), oneUTF8 } }, 1811 { CERT_RDN_BMP_STRING, nihongoURL, { sizeof(nihongoBMP), nihongoBMP } }, 1812 { CERT_RDN_UTF8_STRING, nihongoURL, { sizeof(nihongoUTF8), nihongoUTF8 } }, 1813 }; 1814 1815 static struct UnicodeExpectedResult unicodeWeirdness[] = { 1816 { CERT_RDN_TELETEX_STRING, nihongoURL, { sizeof(nihongoT61), nihongoT61 } }, 1817 { CERT_RDN_GENERAL_STRING, nihongoURL, { sizeof(nihongoGeneral), nihongoGeneral } }, 1818 }; 1819 1820 static void test_encodeUnicodeNameValue(DWORD dwEncoding) 1821 { 1822 BYTE *buf = NULL; 1823 DWORD size = 0, i; 1824 BOOL ret; 1825 CERT_NAME_VALUE value; 1826 1827 if (0) 1828 { 1829 /* Crashes on win9x */ 1830 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, NULL, 1831 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1832 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 1833 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); 1834 } 1835 /* Have to have a string of some sort */ 1836 value.dwValueType = 0; /* aka CERT_RDN_ANY_TYPE */ 1837 value.Value.pbData = NULL; 1838 value.Value.cbData = 0; 1839 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value, 1840 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1841 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING, 1842 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError()); 1843 value.dwValueType = CERT_RDN_ENCODED_BLOB; 1844 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value, 1845 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1846 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING, 1847 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError()); 1848 value.dwValueType = CERT_RDN_ANY_TYPE; 1849 value.Value.pbData = (LPBYTE)oneW; 1850 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value, 1851 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1852 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING, 1853 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError()); 1854 value.Value.cbData = sizeof(oneW); 1855 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value, 1856 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1857 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING, 1858 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError()); 1859 /* An encoded string with specified length isn't good enough either */ 1860 value.dwValueType = CERT_RDN_ENCODED_BLOB; 1861 value.Value.pbData = oneUniversal; 1862 value.Value.cbData = sizeof(oneUniversal); 1863 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value, 1864 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1865 ok(!ret && GetLastError() == CRYPT_E_NOT_CHAR_STRING, 1866 "Expected CRYPT_E_NOT_CHAR_STRING, got %08x\n", GetLastError()); 1867 /* More failure checking */ 1868 value.Value.cbData = 0; 1869 for (i = 0; i < ARRAY_SIZE(unicodeErrors); i++) 1870 { 1871 value.Value.pbData = (LPBYTE)unicodeErrors[i].str; 1872 value.dwValueType = unicodeErrors[i].valueType; 1873 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value, 1874 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1875 ok(!ret && GetLastError() == unicodeErrors[i].error, 1876 "Value type %d: expected %08x, got %08x\n", value.dwValueType, 1877 unicodeErrors[i].error, GetLastError()); 1878 ok(size == unicodeErrors[i].errorIndex, 1879 "Expected error index %d, got %d\n", unicodeErrors[i].errorIndex, 1880 size); 1881 } 1882 /* cbData can be zero if the string is NULL-terminated */ 1883 value.Value.cbData = 0; 1884 for (i = 0; i < ARRAY_SIZE(unicodeResults); i++) 1885 { 1886 value.Value.pbData = (LPBYTE)unicodeResults[i].str; 1887 value.dwValueType = unicodeResults[i].valueType; 1888 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value, 1889 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1890 ok(ret || broken(GetLastError() == OSS_PDU_MISMATCH /* Win9x */), 1891 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 1892 if (ret) 1893 { 1894 ok(size == unicodeResults[i].encoded.cbData, 1895 "Value type %d: expected size %d, got %d\n", 1896 value.dwValueType, unicodeResults[i].encoded.cbData, size); 1897 ok(!memcmp(unicodeResults[i].encoded.pbData, buf, size), 1898 "Value type %d: unexpected value\n", value.dwValueType); 1899 LocalFree(buf); 1900 } 1901 } 1902 /* These "encode," but they do so by truncating each unicode character 1903 * rather than properly encoding it. Kept separate from the proper results, 1904 * because the encoded forms won't decode to their original strings. 1905 */ 1906 for (i = 0; i < ARRAY_SIZE(unicodeWeirdness); i++) 1907 { 1908 value.Value.pbData = (LPBYTE)unicodeWeirdness[i].str; 1909 value.dwValueType = unicodeWeirdness[i].valueType; 1910 ret = pCryptEncodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, &value, 1911 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 1912 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 1913 if (ret) 1914 { 1915 ok(size == unicodeWeirdness[i].encoded.cbData, 1916 "Value type %d: expected size %d, got %d\n", 1917 value.dwValueType, unicodeWeirdness[i].encoded.cbData, size); 1918 ok(!memcmp(unicodeWeirdness[i].encoded.pbData, buf, size), 1919 "Value type %d: unexpected value\n", value.dwValueType); 1920 LocalFree(buf); 1921 } 1922 } 1923 } 1924 1925 static inline int strncmpW( const WCHAR *str1, const WCHAR *str2, int n ) 1926 { 1927 if (n <= 0) return 0; 1928 while ((--n > 0) && *str1 && (*str1 == *str2)) { str1++; str2++; } 1929 return *str1 - *str2; 1930 } 1931 1932 static void test_decodeUnicodeNameValue(DWORD dwEncoding) 1933 { 1934 DWORD i; 1935 1936 for (i = 0; i < ARRAY_SIZE(unicodeResults); i++) 1937 { 1938 BYTE *buf = NULL; 1939 BOOL ret; 1940 DWORD size = 0; 1941 1942 ret = pCryptDecodeObjectEx(dwEncoding, X509_UNICODE_NAME_VALUE, 1943 unicodeResults[i].encoded.pbData, unicodeResults[i].encoded.cbData, 1944 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 1945 ok(ret || broken(GetLastError() == CRYPT_E_NOT_CHAR_STRING /* Win9x */), 1946 "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 1947 if (ret && buf) 1948 { 1949 PCERT_NAME_VALUE value = (PCERT_NAME_VALUE)buf; 1950 1951 ok(value->dwValueType == unicodeResults[i].valueType, 1952 "Expected value type %d, got %d\n", unicodeResults[i].valueType, 1953 value->dwValueType); 1954 ok(!strncmpW((LPWSTR)value->Value.pbData, unicodeResults[i].str, 1955 value->Value.cbData / sizeof(WCHAR)), 1956 "Unexpected decoded value for index %d (value type %d)\n", i, 1957 unicodeResults[i].valueType); 1958 LocalFree(buf); 1959 } 1960 } 1961 } 1962 1963 static const unsigned char decoded_hi_octet[] = { 'h','i' }; 1964 static const unsigned char encoded_hi_octet[] = { ASN_OCTETSTRING,2,'h','i' }; 1965 static const unsigned char decoded_something_long_octet[] = { 1966 's','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g' }; 1967 static const unsigned char encoded_something_long_octet[] = { 1968 ASN_OCTETSTRING,15,'s','o','m','e','l','o','n','g',0xff,'s','t','r','i','n','g' }; 1969 static const unsigned char encoded_empty_octet[] = { ASN_OCTETSTRING,0 }; 1970 1971 static void test_encodeOctets(DWORD dwEncoding) 1972 { 1973 CRYPT_DATA_BLOB blob; 1974 DWORD i; 1975 1976 static const struct { 1977 const BYTE *decoded; 1978 UINT decoded_size; 1979 const BYTE *encoded; 1980 UINT encoded_size; 1981 } tests[] = { 1982 { 1983 decoded_hi_octet, sizeof(decoded_hi_octet), 1984 encoded_hi_octet, sizeof(encoded_hi_octet) 1985 },{ 1986 decoded_something_long_octet, sizeof(decoded_something_long_octet), 1987 encoded_something_long_octet, sizeof(encoded_something_long_octet) 1988 },{ 1989 encoded_empty_octet, 0, 1990 encoded_empty_octet, sizeof(encoded_empty_octet) 1991 } 1992 }; 1993 1994 for (i = 0; i < ARRAY_SIZE(tests); i++) 1995 { 1996 BYTE *buf = NULL; 1997 BOOL ret; 1998 DWORD bufSize = 0; 1999 2000 blob.cbData = tests[i].decoded_size; 2001 blob.pbData = (BYTE*)tests[i].decoded; 2002 ret = pCryptEncodeObjectEx(dwEncoding, X509_OCTET_STRING, &blob, 2003 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2004 ok(ret, "CryptEncodeObjectEx failed: %d\n", GetLastError()); 2005 if (ret) 2006 { 2007 ok(bufSize == tests[i].encoded_size, "[%u] buf size %u expected %u\n", 2008 i, bufSize, tests[i].encoded_size); 2009 ok(buf[0] == 4, "Got unexpected type %d for octet string (expected 4)\n", buf[0]); 2010 ok(buf[1] == tests[i].decoded_size, "[%u] Got length %d, expected %d\n", 2011 i, buf[1], tests[i].decoded_size); 2012 ok(!memcmp(buf, tests[i].encoded, tests[i].encoded_size), "[%u] Got unexpected value\n", i); 2013 LocalFree(buf); 2014 } 2015 } 2016 } 2017 2018 static const unsigned char encoded_constructed_hi_octet[] = 2019 { ASN_CONSTRUCTOR|ASN_OCTETSTRING,0x80, ASN_OCTETSTRING,2,'h','i', 0,0 }; 2020 static const unsigned char encoded_constructed_hi_octet2[] = 2021 { ASN_CONSTRUCTOR|ASN_OCTETSTRING,4, ASN_OCTETSTRING,2,'h','i', 1,2,3 }; 2022 static const unsigned char encoded_constructed_hi_octet3[] = 2023 { ASN_CONSTRUCTOR|ASN_OCTETSTRING,8, ASN_CONSTRUCTOR|ASN_OCTETSTRING,0x80, ASN_OCTETSTRING,2,'h','i', 0,0, 0,0 }; 2024 static const unsigned char encoded_constructed_hi_octet_invalid_end[] = 2025 { ASN_CONSTRUCTOR|ASN_OCTETSTRING,0x80, ASN_OCTETSTRING,2,'h','i', 0,1 }; 2026 2027 static void test_decodeOctets(DWORD dwEncoding) 2028 { 2029 DWORD i; 2030 2031 static const struct { 2032 const BYTE *encoded; 2033 UINT encoded_size; 2034 const BYTE *decoded; 2035 UINT decoded_size; 2036 DWORD error; 2037 } tests[] = { 2038 { 2039 encoded_hi_octet, sizeof(encoded_hi_octet), 2040 decoded_hi_octet, sizeof(decoded_hi_octet) 2041 },{ 2042 encoded_something_long_octet, sizeof(encoded_something_long_octet), 2043 decoded_something_long_octet, sizeof(decoded_something_long_octet) 2044 },{ 2045 encoded_constructed_hi_octet, sizeof(encoded_constructed_hi_octet), 2046 decoded_hi_octet, sizeof(decoded_hi_octet) 2047 },{ 2048 encoded_constructed_hi_octet2, sizeof(encoded_constructed_hi_octet2), 2049 decoded_hi_octet, sizeof(decoded_hi_octet) 2050 },{ 2051 encoded_constructed_hi_octet3, sizeof(encoded_constructed_hi_octet3), 2052 decoded_hi_octet, sizeof(decoded_hi_octet) 2053 },{ 2054 encoded_empty_octet, sizeof(encoded_empty_octet), 2055 encoded_empty_octet, 0 2056 },{ 2057 encoded_hi_octet, sizeof(encoded_hi_octet) - 1, 2058 NULL, 0, CRYPT_E_ASN1_EOD 2059 },{ 2060 encoded_constructed_hi_octet, sizeof(encoded_constructed_hi_octet) - 1, 2061 NULL, 0, CRYPT_E_ASN1_EOD 2062 },{ 2063 encoded_constructed_hi_octet_invalid_end, sizeof(encoded_constructed_hi_octet_invalid_end), 2064 NULL, 0, CRYPT_E_ASN1_CORRUPT 2065 } 2066 }; 2067 2068 for (i = 0; i < ARRAY_SIZE(tests); i++) 2069 { 2070 BYTE *buf = NULL; 2071 BOOL ret; 2072 DWORD bufSize = 0; 2073 2074 ret = pCryptDecodeObjectEx(dwEncoding, X509_OCTET_STRING, 2075 tests[i].encoded, tests[i].encoded_size, 2076 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2077 if (tests[i].error) 2078 { 2079 ok(!ret && GetLastError() == tests[i].error, 2080 "[%u] CryptDecodeObjectEx returned %x(%x)\n", i, ret, GetLastError()); 2081 continue; 2082 } 2083 ok(ret, "[%u] CryptDecodeObjectEx failed: %08x\n", i, GetLastError()); 2084 ok(bufSize >= sizeof(CRYPT_DATA_BLOB) + tests[i].decoded_size, 2085 "[%u] Expected size >= %d, got %d\n", i, 2086 (int)sizeof(CRYPT_DATA_BLOB) + tests[i].decoded_size, bufSize); 2087 ok(buf != NULL, "Expected allocated buffer\n"); 2088 if (ret) 2089 { 2090 CRYPT_DATA_BLOB *blob = (CRYPT_DATA_BLOB *)buf; 2091 2092 ok (blob->cbData == tests[i].decoded_size, "[%u] cbData = %u\n", i, blob->cbData); 2093 if (blob->cbData) 2094 ok(!memcmp(blob->pbData, tests[i].decoded, blob->cbData), 2095 "Unexpected value\n"); 2096 LocalFree(buf); 2097 } 2098 } 2099 } 2100 2101 static const BYTE bytesToEncode[] = { 0xff, 0xff }; 2102 2103 struct encodedBits 2104 { 2105 DWORD cUnusedBits; 2106 const BYTE *encoded; 2107 DWORD cbDecoded; 2108 const BYTE *decoded; 2109 }; 2110 2111 static const unsigned char bin52[] = { 0x03,0x03,0x00,0xff,0xff }; 2112 static const unsigned char bin53[] = { 0xff,0xff }; 2113 static const unsigned char bin54[] = { 0x03,0x03,0x01,0xff,0xfe }; 2114 static const unsigned char bin55[] = { 0xff,0xfe }; 2115 static const unsigned char bin56[] = { 0x03,0x02,0x01,0xfe }; 2116 static const unsigned char bin57[] = { 0xfe }; 2117 2118 static const struct encodedBits bits[] = { 2119 /* normal test cases */ 2120 { 0, bin52, 2, bin53 }, 2121 { 1, bin54, 2, bin55 }, 2122 /* strange test case, showing cUnusedBits >= 8 is allowed */ 2123 { 9, bin56, 1, bin57 }, 2124 }; 2125 2126 static void test_encodeBits(DWORD dwEncoding) 2127 { 2128 DWORD i; 2129 2130 for (i = 0; i < ARRAY_SIZE(bits); i++) 2131 { 2132 CRYPT_BIT_BLOB blob; 2133 BOOL ret; 2134 BYTE *buf = NULL; 2135 DWORD bufSize = 0; 2136 2137 blob.cbData = sizeof(bytesToEncode); 2138 blob.pbData = (BYTE *)bytesToEncode; 2139 blob.cUnusedBits = bits[i].cUnusedBits; 2140 ret = pCryptEncodeObjectEx(dwEncoding, X509_BITS, &blob, 2141 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2142 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 2143 if (ret) 2144 { 2145 ok(bufSize == bits[i].encoded[1] + 2, 2146 "%d: Got unexpected size %d, expected %d\n", i, bufSize, 2147 bits[i].encoded[1] + 2); 2148 ok(!memcmp(buf, bits[i].encoded, bits[i].encoded[1] + 2), 2149 "%d: Unexpected value\n", i); 2150 LocalFree(buf); 2151 } 2152 } 2153 } 2154 2155 static void test_decodeBits(DWORD dwEncoding) 2156 { 2157 static const BYTE ber[] = "\x03\x02\x01\xff"; 2158 static const BYTE berDecoded = 0xfe; 2159 DWORD i; 2160 BOOL ret; 2161 BYTE *buf = NULL; 2162 DWORD bufSize = 0; 2163 2164 /* normal cases */ 2165 for (i = 0; i < ARRAY_SIZE(bits); i++) 2166 { 2167 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, bits[i].encoded, 2168 bits[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, 2169 &bufSize); 2170 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2171 if (ret) 2172 { 2173 CRYPT_BIT_BLOB *blob; 2174 2175 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + bits[i].cbDecoded, 2176 "Got unexpected size %d\n", bufSize); 2177 blob = (CRYPT_BIT_BLOB *)buf; 2178 ok(blob->cbData == bits[i].cbDecoded, 2179 "Got unexpected length %d, expected %d\n", blob->cbData, 2180 bits[i].cbDecoded); 2181 if (blob->cbData && bits[i].cbDecoded) 2182 ok(!memcmp(blob->pbData, bits[i].decoded, bits[i].cbDecoded), 2183 "Unexpected value\n"); 2184 LocalFree(buf); 2185 } 2186 } 2187 /* special case: check that something that's valid in BER but not in DER 2188 * decodes successfully 2189 */ 2190 ret = pCryptDecodeObjectEx(dwEncoding, X509_BITS, ber, ber[1] + 2, 2191 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2192 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2193 if (ret) 2194 { 2195 CRYPT_BIT_BLOB *blob; 2196 2197 ok(bufSize >= sizeof(CRYPT_BIT_BLOB) + sizeof(berDecoded), 2198 "Got unexpected size %d\n", bufSize); 2199 blob = (CRYPT_BIT_BLOB *)buf; 2200 ok(blob->cbData == sizeof(berDecoded), 2201 "Got unexpected length %d\n", blob->cbData); 2202 if (blob->cbData) 2203 ok(*blob->pbData == berDecoded, "Unexpected value\n"); 2204 LocalFree(buf); 2205 } 2206 } 2207 2208 struct Constraints2 2209 { 2210 CERT_BASIC_CONSTRAINTS2_INFO info; 2211 const BYTE *encoded; 2212 }; 2213 2214 static const unsigned char bin59[] = { 0x30,0x00 }; 2215 static const unsigned char bin60[] = { 0x30,0x03,0x01,0x01,0xff }; 2216 static const unsigned char bin61[] = { 0x30,0x03,0x02,0x01,0x00 }; 2217 static const unsigned char bin62[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; 2218 static const struct Constraints2 constraints2[] = { 2219 /* empty constraints */ 2220 { { FALSE, FALSE, 0}, bin59 }, 2221 /* can be a CA */ 2222 { { TRUE, FALSE, 0}, bin60 }, 2223 /* has path length constraints set (MSDN implies fCA needs to be TRUE as well, 2224 * but that's not the case 2225 */ 2226 { { FALSE, TRUE, 0}, bin61 }, 2227 /* can be a CA and has path length constraints set */ 2228 { { TRUE, TRUE, 1}, bin62 }, 2229 }; 2230 2231 static const BYTE emptyConstraint[] = { 0x30, 0x03, 0x03, 0x01, 0x00 }; 2232 static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 2233 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 2234 0x03, 0x6f, 0x72, 0x67, 0x30, 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 2235 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 }; 2236 static const BYTE constraintWithDomainName[] = { 0x30, 0x32, 0x03, 0x01, 0x00, 2237 0x30, 0x2d, 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, 0x06, 0x0a, 0x09, 0x92, 0x26, 2238 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 0x16, 0x03, 0x6f, 0x72, 0x67, 0x30, 2239 0x14, 0x06, 0x0a, 0x09, 0x92, 0x26, 0x89, 0x93, 0xf2, 0x2c, 0x64, 0x01, 0x19, 2240 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 }; 2241 2242 static void test_encodeBasicConstraints(DWORD dwEncoding) 2243 { 2244 DWORD i, bufSize = 0; 2245 CERT_BASIC_CONSTRAINTS_INFO info = { { 0 } }; 2246 CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName), 2247 (LPBYTE)encodedDomainName }; 2248 BOOL ret; 2249 BYTE *buf = NULL; 2250 2251 /* First test with the simpler info2 */ 2252 for (i = 0; i < ARRAY_SIZE(constraints2); i++) 2253 { 2254 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2, 2255 &constraints2[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, 2256 &bufSize); 2257 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 2258 if (ret) 2259 { 2260 ok(bufSize == constraints2[i].encoded[1] + 2, 2261 "Expected %d bytes, got %d\n", constraints2[i].encoded[1] + 2, 2262 bufSize); 2263 ok(!memcmp(buf, constraints2[i].encoded, 2264 constraints2[i].encoded[1] + 2), "Unexpected value\n"); 2265 LocalFree(buf); 2266 } 2267 } 2268 /* Now test with more complex basic constraints */ 2269 info.SubjectType.cbData = 0; 2270 info.fPathLenConstraint = FALSE; 2271 info.cSubtreesConstraint = 0; 2272 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info, 2273 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2274 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */, 2275 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 2276 if (ret) 2277 { 2278 ok(bufSize == sizeof(emptyConstraint), "Wrong size %d\n", bufSize); 2279 ok(!memcmp(buf, emptyConstraint, sizeof(emptyConstraint)), 2280 "Unexpected value\n"); 2281 LocalFree(buf); 2282 } 2283 /* None of the certs I examined had any subtree constraint, but I test one 2284 * anyway just in case. 2285 */ 2286 info.cSubtreesConstraint = 1; 2287 info.rgSubtreesConstraint = &nameBlob; 2288 ret = pCryptEncodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, &info, 2289 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2290 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */, 2291 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 2292 if (ret) 2293 { 2294 ok(bufSize == sizeof(constraintWithDomainName), "Wrong size %d\n", bufSize); 2295 ok(!memcmp(buf, constraintWithDomainName, 2296 sizeof(constraintWithDomainName)), "Unexpected value\n"); 2297 LocalFree(buf); 2298 } 2299 /* FIXME: test encoding with subject type. */ 2300 } 2301 2302 static const unsigned char bin63[] = { 0x30,0x06,0x01,0x01,0x01,0x02,0x01,0x01 }; 2303 2304 static void test_decodeBasicConstraints(DWORD dwEncoding) 2305 { 2306 static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01, 2307 0xff }; 2308 static const struct Constraints2 badBool = { { TRUE, TRUE, 1 }, bin63 }; 2309 DWORD i; 2310 BOOL ret; 2311 BYTE *buf = NULL; 2312 DWORD bufSize = 0; 2313 2314 /* First test with simpler info2 */ 2315 for (i = 0; i < ARRAY_SIZE(constraints2); i++) 2316 { 2317 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2, 2318 constraints2[i].encoded, constraints2[i].encoded[1] + 2, 2319 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2320 ok(ret, "CryptDecodeObjectEx failed for item %d: %08x\n", i, 2321 GetLastError()); 2322 if (ret) 2323 { 2324 CERT_BASIC_CONSTRAINTS2_INFO *info = 2325 (CERT_BASIC_CONSTRAINTS2_INFO *)buf; 2326 2327 ok(!memcmp(info, &constraints2[i].info, sizeof(*info)), 2328 "Unexpected value for item %d\n", i); 2329 LocalFree(buf); 2330 } 2331 } 2332 /* Check with the order of encoded elements inverted */ 2333 buf = (PBYTE)1; 2334 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2, 2335 inverted, inverted[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, 2336 &bufSize); 2337 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT || 2338 GetLastError() == OSS_DATA_ERROR /* Win9x */), 2339 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n", 2340 GetLastError()); 2341 ok(!buf, "Expected buf to be set to NULL\n"); 2342 /* Check with a non-DER bool */ 2343 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2, 2344 badBool.encoded, badBool.encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, 2345 &buf, &bufSize); 2346 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2347 if (ret) 2348 { 2349 CERT_BASIC_CONSTRAINTS2_INFO *info = 2350 (CERT_BASIC_CONSTRAINTS2_INFO *)buf; 2351 2352 ok(!memcmp(info, &badBool.info, sizeof(*info)), "Unexpected value\n"); 2353 LocalFree(buf); 2354 } 2355 /* Check with a non-basic constraints value */ 2356 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS2, 2357 encodedCommonName, encodedCommonName[1] + 2, 2358 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2359 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT || 2360 GetLastError() == OSS_DATA_ERROR /* Win9x */), 2361 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n", 2362 GetLastError()); 2363 /* Now check with the more complex CERT_BASIC_CONSTRAINTS_INFO */ 2364 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, 2365 emptyConstraint, sizeof(emptyConstraint), CRYPT_DECODE_ALLOC_FLAG, NULL, 2366 &buf, &bufSize); 2367 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2368 if (ret) 2369 { 2370 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf; 2371 2372 ok(info->SubjectType.cbData == 0, "Expected no subject type\n"); 2373 ok(!info->fPathLenConstraint, "Expected no path length constraint\n"); 2374 ok(info->cSubtreesConstraint == 0, "Expected no subtree constraints\n"); 2375 LocalFree(buf); 2376 } 2377 ret = pCryptDecodeObjectEx(dwEncoding, X509_BASIC_CONSTRAINTS, 2378 constraintWithDomainName, sizeof(constraintWithDomainName), 2379 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2380 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2381 if (ret) 2382 { 2383 CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf; 2384 2385 ok(info->SubjectType.cbData == 0, "Expected no subject type\n"); 2386 ok(!info->fPathLenConstraint, "Expected no path length constraint\n"); 2387 ok(info->cSubtreesConstraint == 1, "Expected a subtree constraint\n"); 2388 if (info->cSubtreesConstraint && info->rgSubtreesConstraint) 2389 { 2390 ok(info->rgSubtreesConstraint[0].cbData == 2391 sizeof(encodedDomainName), "Wrong size %d\n", 2392 info->rgSubtreesConstraint[0].cbData); 2393 ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName, 2394 sizeof(encodedDomainName)), "Unexpected value\n"); 2395 } 2396 LocalFree(buf); 2397 } 2398 } 2399 2400 /* These are terrible public keys of course, I'm just testing encoding */ 2401 static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 }; 2402 static const BYTE modulus2[] = { 1,1,1,1,1,0,0,0 }; 2403 static const BYTE modulus3[] = { 0x80,1,1,1,1,0,0,0 }; 2404 static const BYTE modulus4[] = { 1,1,1,1,1,0,0,0x80 }; 2405 static const BYTE mod1_encoded[] = { 0x30,0x0f,0x02,0x08,0x01,0x01,0x01,0x01,0x01,0x00,0x00,0x00,0x02,0x03,0x01,0x00,0x01 }; 2406 static const BYTE mod2_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 }; 2407 static const BYTE mod3_encoded[] = { 0x30,0x0c,0x02,0x05,0x01,0x01,0x01,0x01,0x80,0x02,0x03,0x01,0x00,0x01 }; 2408 static const BYTE mod4_encoded[] = { 0x30,0x10,0x02,0x09,0x00,0x80,0x00,0x00,0x01,0x01,0x01,0x01,0x01,0x02,0x03,0x01,0x00,0x01 }; 2409 2410 struct EncodedRSAPubKey 2411 { 2412 const BYTE *modulus; 2413 size_t modulusLen; 2414 const BYTE *encoded; 2415 size_t decodedModulusLen; 2416 }; 2417 2418 static const struct EncodedRSAPubKey rsaPubKeys[] = { 2419 { modulus1, sizeof(modulus1), mod1_encoded, sizeof(modulus1) }, 2420 { modulus2, sizeof(modulus2), mod2_encoded, 5 }, 2421 { modulus3, sizeof(modulus3), mod3_encoded, 5 }, 2422 { modulus4, sizeof(modulus4), mod4_encoded, 8 }, 2423 }; 2424 2425 static void test_encodeRsaPublicKey(DWORD dwEncoding) 2426 { 2427 BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)]; 2428 BLOBHEADER *hdr = (BLOBHEADER *)toEncode; 2429 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER)); 2430 BOOL ret; 2431 BYTE *buf = NULL; 2432 DWORD bufSize = 0, i; 2433 2434 /* Try with a bogus blob type */ 2435 hdr->bType = 2; 2436 hdr->bVersion = CUR_BLOB_VERSION; 2437 hdr->reserved = 0; 2438 hdr->aiKeyAlg = CALG_RSA_KEYX; 2439 rsaPubKey->magic = 0x31415352; 2440 rsaPubKey->bitlen = sizeof(modulus1) * 8; 2441 rsaPubKey->pubexp = 65537; 2442 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), modulus1, 2443 sizeof(modulus1)); 2444 2445 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB, 2446 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2447 ok(!ret && GetLastError() == E_INVALIDARG, 2448 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 2449 /* Now with a bogus reserved field */ 2450 hdr->bType = PUBLICKEYBLOB; 2451 hdr->reserved = 1; 2452 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB, 2453 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2454 if (ret) 2455 { 2456 ok(bufSize == rsaPubKeys[0].encoded[1] + 2, 2457 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize); 2458 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n"); 2459 LocalFree(buf); 2460 } 2461 /* Now with a bogus blob version */ 2462 hdr->reserved = 0; 2463 hdr->bVersion = 0; 2464 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB, 2465 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2466 if (ret) 2467 { 2468 ok(bufSize == rsaPubKeys[0].encoded[1] + 2, 2469 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize); 2470 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n"); 2471 LocalFree(buf); 2472 } 2473 /* And with a bogus alg ID */ 2474 hdr->bVersion = CUR_BLOB_VERSION; 2475 hdr->aiKeyAlg = CALG_DES; 2476 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB, 2477 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2478 if (ret) 2479 { 2480 ok(bufSize == rsaPubKeys[0].encoded[1] + 2, 2481 "Expected size %d, got %d\n", rsaPubKeys[0].encoded[1] + 2, bufSize); 2482 ok(!memcmp(buf, rsaPubKeys[0].encoded, bufSize), "Unexpected value\n"); 2483 LocalFree(buf); 2484 } 2485 /* Check a couple of RSA-related OIDs */ 2486 hdr->aiKeyAlg = CALG_RSA_KEYX; 2487 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_RSA, 2488 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2489 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 2490 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 2491 ret = pCryptEncodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA, 2492 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2493 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 2494 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 2495 /* Finally, all valid */ 2496 hdr->aiKeyAlg = CALG_RSA_KEYX; 2497 for (i = 0; i < ARRAY_SIZE(rsaPubKeys); i++) 2498 { 2499 memcpy(toEncode + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), 2500 rsaPubKeys[i].modulus, rsaPubKeys[i].modulusLen); 2501 ret = pCryptEncodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB, 2502 toEncode, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2503 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 2504 if (ret) 2505 { 2506 ok(bufSize == rsaPubKeys[i].encoded[1] + 2, 2507 "Expected size %d, got %d\n", rsaPubKeys[i].encoded[1] + 2, 2508 bufSize); 2509 ok(!memcmp(buf, rsaPubKeys[i].encoded, bufSize), 2510 "Unexpected value\n"); 2511 LocalFree(buf); 2512 } 2513 } 2514 } 2515 2516 static void test_decodeRsaPublicKey(DWORD dwEncoding) 2517 { 2518 DWORD i; 2519 LPBYTE buf = NULL; 2520 DWORD bufSize = 0; 2521 BOOL ret; 2522 2523 /* Try with a bad length */ 2524 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB, 2525 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1], 2526 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2527 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || 2528 GetLastError() == OSS_MORE_INPUT /* Win9x/NT4 */), 2529 "Expected CRYPT_E_ASN1_EOD or OSS_MORE_INPUT, got %08x\n", 2530 GetLastError()); 2531 /* Try with a couple of RSA-related OIDs */ 2532 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_RSA, 2533 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2, 2534 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2535 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 2536 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 2537 ret = pCryptDecodeObjectEx(dwEncoding, szOID_RSA_SHA1RSA, 2538 rsaPubKeys[0].encoded, rsaPubKeys[0].encoded[1] + 2, 2539 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2540 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 2541 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 2542 /* Now try success cases */ 2543 for (i = 0; i < ARRAY_SIZE(rsaPubKeys); i++) 2544 { 2545 bufSize = 0; 2546 ret = pCryptDecodeObjectEx(dwEncoding, RSA_CSP_PUBLICKEYBLOB, 2547 rsaPubKeys[i].encoded, rsaPubKeys[i].encoded[1] + 2, 2548 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2549 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2550 if (ret) 2551 { 2552 BLOBHEADER *hdr = (BLOBHEADER *)buf; 2553 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER)); 2554 2555 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + 2556 rsaPubKeys[i].decodedModulusLen, 2557 "Wrong size %d\n", bufSize); 2558 ok(hdr->bType == PUBLICKEYBLOB, 2559 "Expected type PUBLICKEYBLOB (%d), got %d\n", PUBLICKEYBLOB, 2560 hdr->bType); 2561 ok(hdr->bVersion == CUR_BLOB_VERSION, 2562 "Expected version CUR_BLOB_VERSION (%d), got %d\n", 2563 CUR_BLOB_VERSION, hdr->bVersion); 2564 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n", 2565 hdr->reserved); 2566 ok(hdr->aiKeyAlg == CALG_RSA_KEYX, 2567 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg); 2568 ok(rsaPubKey->magic == 0x31415352, 2569 "Expected magic RSA1, got %08x\n", rsaPubKey->magic); 2570 ok(rsaPubKey->bitlen == rsaPubKeys[i].decodedModulusLen * 8, 2571 "Wrong bit len %d\n", rsaPubKey->bitlen); 2572 ok(rsaPubKey->pubexp == 65537, "Expected pubexp 65537, got %d\n", 2573 rsaPubKey->pubexp); 2574 ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), 2575 rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen), 2576 "Unexpected modulus\n"); 2577 LocalFree(buf); 2578 } 2579 } 2580 } 2581 2582 static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01, 2583 0x7f, 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 2584 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d }; 2585 2586 static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30, 2587 0x36, 0x30, 0x36, 0x31, 0x36, 0x31, 0x30, 0x30, 0x30, 0x5a, 0x02, 0x01, 0x7f, 2588 0x02, 0x02, 0x00, 0x80, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x80, 0x02, 0x02, 2589 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d }; 2590 2591 static void test_encodeSequenceOfAny(DWORD dwEncoding) 2592 { 2593 CRYPT_DER_BLOB blobs[ARRAY_SIZE(ints)]; 2594 CRYPT_SEQUENCE_OF_ANY seq; 2595 DWORD i; 2596 BOOL ret; 2597 BYTE *buf = NULL; 2598 DWORD bufSize = 0; 2599 2600 /* Encode a homogeneous sequence */ 2601 for (i = 0; i < ARRAY_SIZE(ints); i++) 2602 { 2603 blobs[i].cbData = ints[i].encoded[1] + 2; 2604 blobs[i].pbData = (BYTE *)ints[i].encoded; 2605 } 2606 seq.cValue = ARRAY_SIZE(ints); 2607 seq.rgValue = blobs; 2608 2609 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq, 2610 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2611 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 2612 if (ret) 2613 { 2614 ok(bufSize == sizeof(intSequence), "Wrong size %d\n", bufSize); 2615 ok(!memcmp(buf, intSequence, intSequence[1] + 2), "Unexpected value\n"); 2616 LocalFree(buf); 2617 } 2618 /* Change the type of the first element in the sequence, and give it 2619 * another go 2620 */ 2621 blobs[0].cbData = times[0].encodedTime[1] + 2; 2622 blobs[0].pbData = (BYTE *)times[0].encodedTime; 2623 ret = pCryptEncodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, &seq, 2624 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2625 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 2626 if (ret) 2627 { 2628 ok(bufSize == sizeof(mixedSequence), "Wrong size %d\n", bufSize); 2629 ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2), 2630 "Unexpected value\n"); 2631 LocalFree(buf); 2632 } 2633 } 2634 2635 static void test_decodeSequenceOfAny(DWORD dwEncoding) 2636 { 2637 BOOL ret; 2638 BYTE *buf = NULL; 2639 DWORD bufSize = 0; 2640 2641 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, intSequence, 2642 intSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2643 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2644 if (ret) 2645 { 2646 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf; 2647 DWORD i; 2648 2649 ok(seq->cValue == ARRAY_SIZE(ints), "Wrong elements %d\n", seq->cValue); 2650 for (i = 0; i < min(seq->cValue, ARRAY_SIZE(ints)); i++) 2651 { 2652 ok(seq->rgValue[i].cbData == ints[i].encoded[1] + 2, 2653 "Expected %d bytes, got %d\n", ints[i].encoded[1] + 2, 2654 seq->rgValue[i].cbData); 2655 ok(!memcmp(seq->rgValue[i].pbData, ints[i].encoded, 2656 ints[i].encoded[1] + 2), "Unexpected value\n"); 2657 } 2658 LocalFree(buf); 2659 } 2660 ret = pCryptDecodeObjectEx(dwEncoding, X509_SEQUENCE_OF_ANY, mixedSequence, 2661 mixedSequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, 2662 &bufSize); 2663 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2664 if (ret) 2665 { 2666 CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf; 2667 2668 ok(seq->cValue == ARRAY_SIZE(ints), "Wrong elements %d\n", seq->cValue); 2669 /* Just check the first element since it's all that changed */ 2670 ok(seq->rgValue[0].cbData == times[0].encodedTime[1] + 2, 2671 "Expected %d bytes, got %d\n", times[0].encodedTime[1] + 2, 2672 seq->rgValue[0].cbData); 2673 ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime, 2674 times[0].encodedTime[1] + 2), "Unexpected value\n"); 2675 LocalFree(buf); 2676 } 2677 } 2678 2679 struct encodedExtensions 2680 { 2681 CERT_EXTENSIONS exts; 2682 const BYTE *encoded; 2683 }; 2684 2685 static BYTE crit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; 2686 static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; 2687 static CHAR oid_basic_constraints2[] = szOID_BASIC_CONSTRAINTS2; 2688 static CERT_EXTENSION criticalExt = 2689 { oid_basic_constraints2, TRUE, { 8, crit_ext_data } }; 2690 static CERT_EXTENSION nonCriticalExt = 2691 { oid_basic_constraints2, FALSE, { 8, noncrit_ext_data } }; 2692 static CHAR oid_short[] = "1.1"; 2693 static CERT_EXTENSION extWithShortOid = 2694 { oid_short, FALSE, { 0, NULL } }; 2695 2696 static const BYTE ext0[] = { 0x30,0x00 }; 2697 static const BYTE ext1[] = { 0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01, 2698 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; 2699 static const BYTE ext2[] = { 0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d,0x13,0x04, 2700 0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; 2701 static const BYTE ext3[] = { 0x30,0x07,0x30,0x05,0x06,0x01,0x29,0x04,0x00 }; 2702 2703 static const struct encodedExtensions exts[] = { 2704 { { 0, NULL }, ext0 }, 2705 { { 1, &criticalExt }, ext1 }, 2706 { { 1, &nonCriticalExt }, ext2 }, 2707 { { 1, &extWithShortOid }, ext3 } 2708 }; 2709 2710 static void test_encodeExtensions(DWORD dwEncoding) 2711 { 2712 DWORD i; 2713 2714 for (i = 0; i < ARRAY_SIZE(exts); i++) 2715 { 2716 BOOL ret; 2717 BYTE *buf = NULL; 2718 DWORD bufSize = 0; 2719 2720 ret = pCryptEncodeObjectEx(dwEncoding, X509_EXTENSIONS, &exts[i].exts, 2721 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2722 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 2723 if (ret) 2724 { 2725 ok(bufSize == exts[i].encoded[1] + 2, 2726 "Expected %d bytes, got %d\n", exts[i].encoded[1] + 2, bufSize); 2727 ok(!memcmp(buf, exts[i].encoded, exts[i].encoded[1] + 2), 2728 "Unexpected value\n"); 2729 LocalFree(buf); 2730 } 2731 } 2732 } 2733 2734 static void test_decodeExtensions(DWORD dwEncoding) 2735 { 2736 DWORD i; 2737 2738 for (i = 0; i < ARRAY_SIZE(exts); i++) 2739 { 2740 BOOL ret; 2741 BYTE *buf = NULL; 2742 DWORD bufSize = 0; 2743 2744 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS, 2745 exts[i].encoded, exts[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, 2746 NULL, &buf, &bufSize); 2747 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2748 if (ret) 2749 { 2750 CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf; 2751 DWORD j; 2752 2753 ok(ext->cExtension == exts[i].exts.cExtension, 2754 "Expected %d extensions, see %d\n", exts[i].exts.cExtension, 2755 ext->cExtension); 2756 for (j = 0; j < min(ext->cExtension, exts[i].exts.cExtension); j++) 2757 { 2758 ok(!strcmp(ext->rgExtension[j].pszObjId, 2759 exts[i].exts.rgExtension[j].pszObjId), 2760 "Expected OID %s, got %s\n", 2761 exts[i].exts.rgExtension[j].pszObjId, 2762 ext->rgExtension[j].pszObjId); 2763 ok(!memcmp(ext->rgExtension[j].Value.pbData, 2764 exts[i].exts.rgExtension[j].Value.pbData, 2765 exts[i].exts.rgExtension[j].Value.cbData), 2766 "Unexpected value\n"); 2767 } 2768 LocalFree(buf); 2769 } 2770 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS, 2771 exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, NULL, &bufSize); 2772 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2773 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, bufSize); 2774 if (buf) 2775 { 2776 ret = pCryptDecodeObjectEx(dwEncoding, X509_EXTENSIONS, 2777 exts[i].encoded, exts[i].encoded[1] + 2, 0, NULL, buf, &bufSize); 2778 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2779 HeapFree(GetProcessHeap(), 0, buf); 2780 } 2781 } 2782 } 2783 2784 /* MS encodes public key info with a NULL if the algorithm identifier's 2785 * parameters are empty. However, when encoding an algorithm in a CERT_INFO, 2786 * it encodes them by omitting the algorithm parameters. It accepts either 2787 * form for decoding. 2788 */ 2789 struct encodedPublicKey 2790 { 2791 CERT_PUBLIC_KEY_INFO info; 2792 const BYTE *encoded; 2793 const BYTE *encodedNoNull; 2794 CERT_PUBLIC_KEY_INFO decoded; 2795 }; 2796 2797 static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 2798 0xe, 0xf }; 2799 static const BYTE params[] = { 0x02, 0x01, 0x01 }; 2800 2801 static const unsigned char bin64[] = { 2802 0x30,0x0b,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x03,0x01,0x00}; 2803 static const unsigned char bin65[] = { 2804 0x30,0x09,0x30,0x04,0x06,0x02,0x2a,0x03,0x03,0x01,0x00}; 2805 static const unsigned char bin66[] = { 2806 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00}; 2807 static const unsigned char bin67[] = { 2808 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00}; 2809 static const unsigned char bin68[] = { 2810 0x30,0x1f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x11,0x00,0x00,0x01, 2811 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; 2812 static const unsigned char bin69[] = { 2813 0x30,0x1d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x11,0x00,0x00,0x01, 2814 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f}; 2815 static const unsigned char bin70[] = { 2816 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01, 2817 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, 2818 0x0f}; 2819 static const unsigned char bin71[] = { 2820 0x30,0x20,0x30,0x0b,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x01,0x01, 2821 0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e, 2822 0x0f}; 2823 static unsigned char bin72[] = { 0x05,0x00}; 2824 2825 static CHAR oid_bogus[] = "1.2.3", 2826 oid_rsa[] = szOID_RSA; 2827 2828 static const struct encodedPublicKey pubKeys[] = { 2829 /* with a bogus OID */ 2830 { { { oid_bogus, { 0, NULL } }, { 0, NULL, 0 } }, 2831 bin64, bin65, 2832 { { oid_bogus, { 2, bin72 } }, { 0, NULL, 0 } } }, 2833 /* some normal keys */ 2834 { { { oid_rsa, { 0, NULL } }, { 0, NULL, 0} }, 2835 bin66, bin67, 2836 { { oid_rsa, { 2, bin72 } }, { 0, NULL, 0 } } }, 2837 { { { oid_rsa, { 0, NULL } }, { sizeof(aKey), (BYTE *)aKey, 0} }, 2838 bin68, bin69, 2839 { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } }, 2840 /* with add'l parameters--note they must be DER-encoded */ 2841 { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey), 2842 (BYTE *)aKey, 0 } }, 2843 bin70, bin71, 2844 { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey), 2845 (BYTE *)aKey, 0 } } }, 2846 }; 2847 2848 static void test_encodePublicKeyInfo(DWORD dwEncoding) 2849 { 2850 DWORD i; 2851 2852 for (i = 0; i < ARRAY_SIZE(pubKeys); i++) 2853 { 2854 BOOL ret; 2855 BYTE *buf = NULL; 2856 DWORD bufSize = 0; 2857 2858 ret = pCryptEncodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO, 2859 &pubKeys[i].info, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, 2860 &bufSize); 2861 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */, 2862 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 2863 if (ret) 2864 { 2865 ok(bufSize == pubKeys[i].encoded[1] + 2, 2866 "Expected %d bytes, got %d\n", pubKeys[i].encoded[1] + 2, bufSize); 2867 if (bufSize == pubKeys[i].encoded[1] + 2) 2868 ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2), 2869 "Unexpected value\n"); 2870 LocalFree(buf); 2871 } 2872 } 2873 } 2874 2875 static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected, 2876 const CERT_PUBLIC_KEY_INFO *got) 2877 { 2878 ok(!strcmp(expected->Algorithm.pszObjId, got->Algorithm.pszObjId), 2879 "Expected OID %s, got %s\n", expected->Algorithm.pszObjId, 2880 got->Algorithm.pszObjId); 2881 ok(expected->Algorithm.Parameters.cbData == 2882 got->Algorithm.Parameters.cbData, 2883 "Expected parameters of %d bytes, got %d\n", 2884 expected->Algorithm.Parameters.cbData, got->Algorithm.Parameters.cbData); 2885 if (expected->Algorithm.Parameters.cbData) 2886 ok(!memcmp(expected->Algorithm.Parameters.pbData, 2887 got->Algorithm.Parameters.pbData, got->Algorithm.Parameters.cbData), 2888 "Unexpected algorithm parameters\n"); 2889 ok(expected->PublicKey.cbData == got->PublicKey.cbData, 2890 "Expected public key of %d bytes, got %d\n", 2891 expected->PublicKey.cbData, got->PublicKey.cbData); 2892 if (expected->PublicKey.cbData) 2893 ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData, 2894 got->PublicKey.cbData), "Unexpected public key value\n"); 2895 } 2896 2897 static void test_decodePublicKeyInfo(DWORD dwEncoding) 2898 { 2899 static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06, 2900 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01, 0x01, 0x01, 0x03, 2901 0x11, 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 2902 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; 2903 DWORD i; 2904 BOOL ret; 2905 BYTE *buf = NULL; 2906 DWORD bufSize = 0; 2907 2908 for (i = 0; i < ARRAY_SIZE(pubKeys); i++) 2909 { 2910 /* The NULL form decodes to the decoded member */ 2911 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO, 2912 pubKeys[i].encoded, pubKeys[i].encoded[1] + 2, CRYPT_DECODE_ALLOC_FLAG, 2913 NULL, &buf, &bufSize); 2914 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2915 if (ret) 2916 { 2917 comparePublicKeyInfo(&pubKeys[i].decoded, 2918 (CERT_PUBLIC_KEY_INFO *)buf); 2919 LocalFree(buf); 2920 } 2921 /* The non-NULL form decodes to the original */ 2922 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO, 2923 pubKeys[i].encodedNoNull, pubKeys[i].encodedNoNull[1] + 2, 2924 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 2925 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 2926 if (ret) 2927 { 2928 comparePublicKeyInfo(&pubKeys[i].info, (CERT_PUBLIC_KEY_INFO *)buf); 2929 LocalFree(buf); 2930 } 2931 } 2932 /* Test with bogus (not valid DER) parameters */ 2933 ret = pCryptDecodeObjectEx(dwEncoding, X509_PUBLIC_KEY_INFO, 2934 bogusPubKeyInfo, bogusPubKeyInfo[1] + 2, CRYPT_DECODE_ALLOC_FLAG, 2935 NULL, &buf, &bufSize); 2936 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT || 2937 GetLastError() == OSS_DATA_ERROR /* Win9x */), 2938 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n", 2939 GetLastError()); 2940 } 2941 2942 static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00, 2943 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 2944 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 2945 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x07, 0x30, 2946 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 }; 2947 static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02, 2948 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 2949 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 2950 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 2951 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 }; 2952 static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 2953 0x00, 0x30, 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 2954 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 2955 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 2956 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 }; 2957 static const BYTE v4Cert[] = { 2958 0x30,0x38,0xa0,0x03,0x02,0x01,0x03,0x02,0x00,0x30,0x02,0x06,0x00,0x30,0x22, 2959 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30, 2960 0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30, 2961 0x30,0x30,0x30,0x5a,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00 }; 2962 static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30, 2963 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 2964 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 2965 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 2966 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 2967 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 2968 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 }; 2969 static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30, 2970 0x02, 0x06, 0x00, 0x30, 0x22, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 2971 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 2972 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 2973 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00, 0xa3, 0x16, 0x30, 0x14, 2974 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 0x01, 0xff, 0x04, 0x08, 0x30, 2975 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 }; 2976 static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 2977 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 2978 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x22, 2979 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 2980 0x30, 0x30, 0x30, 0x5a, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 2981 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x15, 0x31, 0x13, 0x30, 2982 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 2983 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 2984 0x00, 0xa3, 0x16, 0x30, 0x14, 0x30, 0x12, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x01, 2985 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 }; 2986 static const BYTE v1CertWithPubKey[] = { 2987 0x30,0x81,0x95,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30, 2988 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61, 2989 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31, 2990 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31, 2991 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11, 2992 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, 2993 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, 2994 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 2995 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06, 2996 0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02, 2997 0x01,0x01 }; 2998 static const BYTE v1CertWithPubKeyNoNull[] = { 2999 0x30,0x81,0x93,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30, 3000 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61, 3001 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31, 3002 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31, 3003 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11, 3004 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, 3005 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, 3006 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 3007 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55, 3008 0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; 3009 static const BYTE v1CertWithSubjectKeyId[] = { 3010 0x30,0x7b,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11, 3011 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, 3012 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30, 3013 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30, 3014 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06, 3015 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67, 3016 0x00,0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0xa3,0x17,0x30,0x15,0x30, 3017 0x13,0x06,0x03,0x55,0x1d,0x0e,0x04,0x0c,0x04,0x0a,0x4a,0x75,0x61,0x6e,0x20, 3018 0x4c,0x61,0x6e,0x67,0x00 }; 3019 static const BYTE v1CertWithIssuerUniqueId[] = { 3020 0x30,0x38,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x22,0x18,0x0f,0x31,0x36, 3021 0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f, 3022 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a, 3023 0x30,0x07,0x30,0x02,0x06,0x00,0x03,0x01,0x00,0x81,0x02,0x00,0x01 }; 3024 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueId[] = { 3025 0x30,0x81,0x99,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30, 3026 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61, 3027 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31, 3028 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31, 3029 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11, 3030 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, 3031 0x67,0x00,0x30,0x22,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, 3032 0x01,0x01,0x05,0x00,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07, 3033 0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30, 3034 0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06, 3035 0x01,0x01,0xff,0x02,0x01,0x01 }; 3036 static const BYTE v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull[] = { 3037 0x30,0x81,0x97,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30, 3038 0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61, 3039 0x6e,0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31, 3040 0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31, 3041 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11, 3042 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, 3043 0x67,0x00,0x30,0x20,0x30,0x0b,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01, 3044 0x01,0x01,0x03,0x11,0x00,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 3045 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f,0x81,0x02,0x00,0x01,0xa3,0x16,0x30,0x14,0x30, 3046 0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01, 3047 0xff,0x02,0x01,0x01 }; 3048 3049 static const BYTE serialNum[] = { 0x01 }; 3050 3051 static void test_encodeCertToBeSigned(DWORD dwEncoding) 3052 { 3053 BOOL ret; 3054 BYTE *buf = NULL; 3055 DWORD size = 0; 3056 CERT_INFO info = { 0 }; 3057 static char oid_rsa_rsa[] = szOID_RSA_RSA; 3058 static char oid_subject_key_identifier[] = szOID_SUBJECT_KEY_IDENTIFIER; 3059 CERT_EXTENSION ext; 3060 3061 if (0) 3062 { 3063 /* Test with NULL pvStructInfo (crashes on win9x) */ 3064 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 3065 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3066 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 3067 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); 3068 } 3069 /* Test with a V1 cert */ 3070 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info, 3071 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3072 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */, 3073 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3074 if (ret) 3075 { 3076 ok(size == v1Cert[1] + 2, "Expected size %d, got %d\n", 3077 v1Cert[1] + 2, size); 3078 ok(!memcmp(buf, v1Cert, size), "Got unexpected value\n"); 3079 LocalFree(buf); 3080 } 3081 /* Test v2 cert */ 3082 info.dwVersion = CERT_V2; 3083 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info, 3084 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3085 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */, 3086 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3087 if (ret) 3088 { 3089 ok(size == sizeof(v2Cert), "Wrong size %d\n", size); 3090 ok(!memcmp(buf, v2Cert, size), "Got unexpected value\n"); 3091 LocalFree(buf); 3092 } 3093 /* Test v3 cert */ 3094 info.dwVersion = CERT_V3; 3095 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info, 3096 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3097 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */, 3098 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3099 if (ret) 3100 { 3101 ok(size == sizeof(v3Cert), "Wrong size %d\n", size); 3102 ok(!memcmp(buf, v3Cert, size), "Got unexpected value\n"); 3103 LocalFree(buf); 3104 } 3105 /* A v4 cert? */ 3106 info.dwVersion = 3; /* Not a typo, CERT_V3 is 2 */ 3107 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info, 3108 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3109 if (ret) 3110 { 3111 ok(size == sizeof(v4Cert), "Wrong size %d\n", size); 3112 ok(!memcmp(buf, v4Cert, size), "Unexpected value\n"); 3113 LocalFree(buf); 3114 } 3115 /* see if a V1 cert can have basic constraints set (RFC3280 says no, but 3116 * API doesn't prevent it) 3117 */ 3118 info.dwVersion = CERT_V1; 3119 info.cExtension = 1; 3120 info.rgExtension = &criticalExt; 3121 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info, 3122 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3123 ok(ret || GetLastError() == OSS_BAD_PTR /* Win9x */, 3124 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3125 if (ret) 3126 { 3127 ok(size == sizeof(v1CertWithConstraints), "Wrong size %d\n", size); 3128 ok(!memcmp(buf, v1CertWithConstraints, size), "Got unexpected value\n"); 3129 LocalFree(buf); 3130 } 3131 /* test v1 cert with a serial number */ 3132 info.SerialNumber.cbData = sizeof(serialNum); 3133 info.SerialNumber.pbData = (BYTE *)serialNum; 3134 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info, 3135 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3136 if (ret) 3137 { 3138 ok(size == sizeof(v1CertWithSerial), "Wrong size %d\n", size); 3139 ok(!memcmp(buf, v1CertWithSerial, size), "Got unexpected value\n"); 3140 LocalFree(buf); 3141 } 3142 /* Test v1 cert with an issuer name, serial number, and issuer unique id */ 3143 info.dwVersion = CERT_V1; 3144 info.cExtension = 0; 3145 info.IssuerUniqueId.cbData = sizeof(serialNum); 3146 info.IssuerUniqueId.pbData = (BYTE *)serialNum; 3147 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info, 3148 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3149 ok(ret || broken(GetLastError() == OSS_BAD_PTR /* Win98 */), 3150 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3151 if (ret) 3152 { 3153 ok(size == sizeof(v1CertWithIssuerUniqueId), "Wrong size %d\n", size); 3154 ok(!memcmp(buf, v1CertWithIssuerUniqueId, size), 3155 "Got unexpected value\n"); 3156 LocalFree(buf); 3157 } 3158 /* Test v1 cert with an issuer name, a subject name, and a serial number */ 3159 info.IssuerUniqueId.cbData = 0; 3160 info.IssuerUniqueId.pbData = NULL; 3161 info.cExtension = 1; 3162 info.rgExtension = &criticalExt; 3163 info.Issuer.cbData = sizeof(encodedCommonName); 3164 info.Issuer.pbData = (BYTE *)encodedCommonName; 3165 info.Subject.cbData = sizeof(encodedCommonName); 3166 info.Subject.pbData = (BYTE *)encodedCommonName; 3167 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info, 3168 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3169 if (ret) 3170 { 3171 ok(size == sizeof(bigCert), "Wrong size %d\n", size); 3172 ok(!memcmp(buf, bigCert, size), "Got unexpected value\n"); 3173 LocalFree(buf); 3174 } 3175 /* Add a public key */ 3176 info.SubjectPublicKeyInfo.Algorithm.pszObjId = oid_rsa_rsa; 3177 info.SubjectPublicKeyInfo.PublicKey.cbData = sizeof(aKey); 3178 info.SubjectPublicKeyInfo.PublicKey.pbData = (LPBYTE)aKey; 3179 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info, 3180 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3181 if (ret) 3182 { 3183 ok(size == sizeof(v1CertWithPubKey) || 3184 size == sizeof(v1CertWithPubKeyNoNull), "Wrong size %d\n", size); 3185 if (size == sizeof(v1CertWithPubKey)) 3186 ok(!memcmp(buf, v1CertWithPubKey, size), "Got unexpected value\n"); 3187 else if (size == sizeof(v1CertWithPubKeyNoNull)) 3188 ok(!memcmp(buf, v1CertWithPubKeyNoNull, size), 3189 "Got unexpected value\n"); 3190 LocalFree(buf); 3191 } 3192 /* Again add an issuer unique id */ 3193 info.IssuerUniqueId.cbData = sizeof(serialNum); 3194 info.IssuerUniqueId.pbData = (BYTE *)serialNum; 3195 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info, 3196 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3197 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3198 if (ret) 3199 { 3200 ok(size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId) || 3201 size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull), 3202 "Wrong size %d\n", size); 3203 if (size == sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId)) 3204 ok(!memcmp(buf, v1CertWithSubjectIssuerSerialAndIssuerUniqueId, 3205 size), "unexpected value\n"); 3206 else if (size == 3207 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull)) 3208 ok(!memcmp(buf, 3209 v1CertWithSubjectIssuerSerialAndIssuerUniqueIdNoNull, size), 3210 "unexpected value\n"); 3211 LocalFree(buf); 3212 } 3213 /* Remove the public key, and add a subject key identifier extension */ 3214 info.IssuerUniqueId.cbData = 0; 3215 info.IssuerUniqueId.pbData = NULL; 3216 info.SubjectPublicKeyInfo.Algorithm.pszObjId = NULL; 3217 info.SubjectPublicKeyInfo.PublicKey.cbData = 0; 3218 info.SubjectPublicKeyInfo.PublicKey.pbData = NULL; 3219 ext.pszObjId = oid_subject_key_identifier; 3220 ext.fCritical = FALSE; 3221 ext.Value.cbData = sizeof(octetCommonNameValue); 3222 ext.Value.pbData = octetCommonNameValue; 3223 info.cExtension = 1; 3224 info.rgExtension = &ext; 3225 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, &info, 3226 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3227 if (ret) 3228 { 3229 ok(size == sizeof(v1CertWithSubjectKeyId), "Wrong size %d\n", size); 3230 ok(!memcmp(buf, v1CertWithSubjectKeyId, size), "Unexpected value\n"); 3231 LocalFree(buf); 3232 } 3233 } 3234 3235 static void test_decodeCertToBeSigned(DWORD dwEncoding) 3236 { 3237 static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, v4Cert, 3238 v1CertWithConstraints, v1CertWithSerial, v1CertWithIssuerUniqueId }; 3239 BOOL ret; 3240 BYTE *buf = NULL; 3241 DWORD size = 0, i; 3242 3243 /* Test with NULL pbEncoded */ 3244 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 0, 3245 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 3246 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || 3247 GetLastError() == OSS_BAD_ARG /* Win9x */), 3248 "Expected CRYPT_E_ASN1_EOD or OSS_BAD_ARG, got %08x\n", GetLastError()); 3249 if (0) 3250 { 3251 /* Crashes on win9x */ 3252 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, NULL, 1, 3253 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 3254 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 3255 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); 3256 } 3257 /* The following certs all fail with CRYPT_E_ASN1_CORRUPT or 3258 * CRYPT_E_ASN1_BADTAG, because at a minimum a cert must have a non-zero 3259 * serial number, an issuer, a subject, and a public key. 3260 */ 3261 for (i = 0; i < ARRAY_SIZE(corruptCerts); i++) 3262 { 3263 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, 3264 corruptCerts[i], corruptCerts[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, 3265 &buf, &size); 3266 ok(!ret, "Expected failure\n"); 3267 } 3268 /* The following succeeds, even though v1 certs are not allowed to have 3269 * extensions. 3270 */ 3271 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, 3272 v1CertWithSubjectKeyId, sizeof(v1CertWithSubjectKeyId), 3273 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 3274 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3275 if (ret) 3276 { 3277 CERT_INFO *info = (CERT_INFO *)buf; 3278 3279 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size); 3280 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n", 3281 info->dwVersion); 3282 ok(info->cExtension == 1, "expected 1 extension, got %d\n", 3283 info->cExtension); 3284 LocalFree(buf); 3285 } 3286 /* The following also succeeds, even though V1 certs are not allowed to 3287 * have issuer unique ids. 3288 */ 3289 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, 3290 v1CertWithSubjectIssuerSerialAndIssuerUniqueId, 3291 sizeof(v1CertWithSubjectIssuerSerialAndIssuerUniqueId), 3292 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 3293 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3294 if (ret) 3295 { 3296 CERT_INFO *info = (CERT_INFO *)buf; 3297 3298 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size); 3299 ok(info->dwVersion == CERT_V1, "expected CERT_V1, got %d\n", 3300 info->dwVersion); 3301 ok(info->IssuerUniqueId.cbData == sizeof(serialNum), 3302 "unexpected issuer unique id size %d\n", info->IssuerUniqueId.cbData); 3303 ok(!memcmp(info->IssuerUniqueId.pbData, serialNum, sizeof(serialNum)), 3304 "unexpected issuer unique id value\n"); 3305 LocalFree(buf); 3306 } 3307 /* Now check with serial number, subject and issuer specified */ 3308 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, bigCert, 3309 sizeof(bigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 3310 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3311 if (ret) 3312 { 3313 CERT_INFO *info = (CERT_INFO *)buf; 3314 3315 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size); 3316 ok(info->SerialNumber.cbData == 1, 3317 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData); 3318 ok(*info->SerialNumber.pbData == *serialNum, 3319 "Expected serial number %d, got %d\n", *serialNum, 3320 *info->SerialNumber.pbData); 3321 ok(info->Issuer.cbData == sizeof(encodedCommonName), 3322 "Wrong size %d\n", info->Issuer.cbData); 3323 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData), 3324 "Unexpected issuer\n"); 3325 ok(info->Subject.cbData == sizeof(encodedCommonName), 3326 "Wrong size %d\n", info->Subject.cbData); 3327 ok(!memcmp(info->Subject.pbData, encodedCommonName, 3328 info->Subject.cbData), "Unexpected subject\n"); 3329 LocalFree(buf); 3330 } 3331 /* Check again with pub key specified */ 3332 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, 3333 v1CertWithPubKey, sizeof(v1CertWithPubKey), CRYPT_DECODE_ALLOC_FLAG, NULL, 3334 &buf, &size); 3335 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3336 if (ret) 3337 { 3338 CERT_INFO *info = (CERT_INFO *)buf; 3339 3340 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size); 3341 ok(info->SerialNumber.cbData == 1, 3342 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData); 3343 ok(*info->SerialNumber.pbData == *serialNum, 3344 "Expected serial number %d, got %d\n", *serialNum, 3345 *info->SerialNumber.pbData); 3346 ok(info->Issuer.cbData == sizeof(encodedCommonName), 3347 "Wrong size %d\n", info->Issuer.cbData); 3348 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData), 3349 "Unexpected issuer\n"); 3350 ok(info->Subject.cbData == sizeof(encodedCommonName), 3351 "Wrong size %d\n", info->Subject.cbData); 3352 ok(!memcmp(info->Subject.pbData, encodedCommonName, 3353 info->Subject.cbData), "Unexpected subject\n"); 3354 ok(!strcmp(info->SubjectPublicKeyInfo.Algorithm.pszObjId, 3355 szOID_RSA_RSA), "Expected szOID_RSA_RSA, got %s\n", 3356 info->SubjectPublicKeyInfo.Algorithm.pszObjId); 3357 ok(info->SubjectPublicKeyInfo.PublicKey.cbData == sizeof(aKey), 3358 "Wrong size %d\n", info->SubjectPublicKeyInfo.PublicKey.cbData); 3359 ok(!memcmp(info->SubjectPublicKeyInfo.PublicKey.pbData, aKey, 3360 sizeof(aKey)), "Unexpected public key\n"); 3361 LocalFree(buf); 3362 } 3363 } 3364 3365 static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, 3366 0xe, 0xf }; 3367 3368 static const BYTE signedBigCert[] = { 3369 ASN_SEQUENCE,0x81,147, 3370 ASN_SEQUENCE,122, 3371 ASN_INTEGER,1, 0x01, 3372 ASN_SEQUENCE,2, 3373 ASN_OBJECTIDENTIFIER,0, 3374 ASN_SEQUENCE,21, 3375 0x31,19, 3376 ASN_SEQUENCE,17, 3377 ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03, 3378 0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00, 3379 ASN_SEQUENCE,34, 3380 0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a, 3381 0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a, 3382 ASN_SEQUENCE,21, 3383 0x31,19, 3384 ASN_SEQUENCE,17, 3385 ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03, 3386 0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00, 3387 ASN_SEQUENCE,7, 3388 ASN_SEQUENCE,2, 3389 ASN_OBJECTIDENTIFIER,0, 3390 ASN_BITS,1, 0x00, 3391 0xa3,22, 3392 ASN_SEQUENCE,20, 3393 ASN_SEQUENCE,18, 3394 ASN_OBJECTIDENTIFIER,3, 0x55,0x1d,0x13, 3395 0x01,1, 0xff, 3396 ASN_OCTETSTRING,8, 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01, 3397 ASN_SEQUENCE,2, 3398 ASN_OBJECTIDENTIFIER,0, 3399 ASN_BITS,17, 0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08, 3400 0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00 3401 }; 3402 3403 static const BYTE signedBigCertWithIndefiniteSeq[] = { 3404 ASN_SEQUENCE,0x81,151, 3405 ASN_SEQUENCE,126, 3406 ASN_INTEGER,1, 0x01, 3407 ASN_SEQUENCE,2, 3408 ASN_OBJECTIDENTIFIER,0, 3409 ASN_SEQUENCE,21, 3410 0x31,19, 3411 ASN_SEQUENCE,17, 3412 ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03, 3413 0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00, 3414 ASN_SEQUENCE,0x80, 3415 0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a, 3416 0x18,15, 0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a, 3417 0,0, 3418 ASN_SEQUENCE,21, 3419 0x31,19, 3420 ASN_SEQUENCE,17, 3421 ASN_OBJECTIDENTIFIER,3, 0x55,0x04,0x03, 3422 0x13,10, 0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00, 3423 ASN_SEQUENCE,0x80, 3424 ASN_SEQUENCE,2, 3425 ASN_OBJECTIDENTIFIER,0, 3426 ASN_BITS,1, 0x00, 3427 0,0, 3428 0xa3,22, 3429 ASN_SEQUENCE,20, 3430 ASN_SEQUENCE,18, 3431 ASN_OBJECTIDENTIFIER,3, 0x55,0x1d,0x13, 3432 0x01,1, 0xff, 3433 ASN_OCTETSTRING,8, 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01, 3434 ASN_SEQUENCE,2, 3435 ASN_OBJECTIDENTIFIER,0, 3436 ASN_BITS,17, 0x00,0x0f,0x0e,0x0d,0x0c,0x0b,0x0a,0x09,0x08, 3437 0x07,0x06,0x05,0x04,0x03,0x02,0x01,0x00 3438 }; 3439 3440 static void test_encodeCert(DWORD dwEncoding) 3441 { 3442 /* Note the SignatureAlgorithm must match that in the encoded cert. Note 3443 * also that bigCert is a NULL-terminated string, so don't count its 3444 * last byte (otherwise the signed cert won't decode.) 3445 */ 3446 CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert }, 3447 { NULL, { 0, NULL } }, { sizeof(hash), (BYTE *)hash, 0 } }; 3448 BOOL ret; 3449 BYTE *buf = NULL; 3450 DWORD bufSize = 0; 3451 3452 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT, &info, 3453 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &bufSize); 3454 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3455 if (ret) 3456 { 3457 ok(bufSize == sizeof(signedBigCert), "Wrong size %d\n", bufSize); 3458 ok(!memcmp(buf, signedBigCert, bufSize), "Unexpected cert\n"); 3459 LocalFree(buf); 3460 } 3461 } 3462 3463 static void test_decodeCert(DWORD dwEncoding) 3464 { 3465 BOOL ret; 3466 BYTE *buf = NULL; 3467 DWORD size = 0; 3468 3469 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT, signedBigCert, 3470 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 3471 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3472 if (ret) 3473 { 3474 CERT_SIGNED_CONTENT_INFO *info = (CERT_SIGNED_CONTENT_INFO *)buf; 3475 3476 ok(info->ToBeSigned.cbData == sizeof(bigCert), 3477 "Wrong cert size %d\n", info->ToBeSigned.cbData); 3478 ok(!memcmp(info->ToBeSigned.pbData, bigCert, info->ToBeSigned.cbData), 3479 "Unexpected cert\n"); 3480 ok(info->Signature.cbData == sizeof(hash), 3481 "Wrong signature size %d\n", info->Signature.cbData); 3482 ok(!memcmp(info->Signature.pbData, hash, info->Signature.cbData), 3483 "Unexpected signature\n"); 3484 LocalFree(buf); 3485 } 3486 /* A signed cert decodes as a CERT_INFO too */ 3487 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCert, 3488 sizeof(signedBigCert), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 3489 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3490 if (ret) 3491 { 3492 CERT_INFO *info = (CERT_INFO *)buf; 3493 3494 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size); 3495 ok(info->SerialNumber.cbData == 1, 3496 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData); 3497 ok(*info->SerialNumber.pbData == *serialNum, 3498 "Expected serial number %d, got %d\n", *serialNum, 3499 *info->SerialNumber.pbData); 3500 ok(info->Issuer.cbData == sizeof(encodedCommonName), 3501 "Wrong size %d\n", info->Issuer.cbData); 3502 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData), 3503 "Unexpected issuer\n"); 3504 ok(info->Subject.cbData == sizeof(encodedCommonName), 3505 "Wrong size %d\n", info->Subject.cbData); 3506 ok(!memcmp(info->Subject.pbData, encodedCommonName, 3507 info->Subject.cbData), "Unexpected subject\n"); 3508 LocalFree(buf); 3509 } 3510 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_TO_BE_SIGNED, signedBigCertWithIndefiniteSeq, 3511 sizeof(signedBigCertWithIndefiniteSeq), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 3512 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3513 if (ret) 3514 { 3515 CERT_INFO *info = (CERT_INFO *)buf; 3516 3517 ok(size >= sizeof(CERT_INFO), "Wrong size %d\n", size); 3518 ok(info->SerialNumber.cbData == 1, 3519 "Expected serial number size 1, got %d\n", info->SerialNumber.cbData); 3520 ok(*info->SerialNumber.pbData == *serialNum, 3521 "Expected serial number %d, got %d\n", *serialNum, 3522 *info->SerialNumber.pbData); 3523 ok(info->Issuer.cbData == sizeof(encodedCommonName), 3524 "Wrong size %d\n", info->Issuer.cbData); 3525 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData), 3526 "Unexpected issuer\n"); 3527 ok(info->Subject.cbData == sizeof(encodedCommonName), 3528 "Wrong size %d\n", info->Subject.cbData); 3529 ok(!memcmp(info->Subject.pbData, encodedCommonName, 3530 info->Subject.cbData), "Unexpected subject\n"); 3531 LocalFree(buf); 3532 } 3533 } 3534 3535 static const BYTE emptyDistPoint[] = { 0x30, 0x02, 0x30, 0x00 }; 3536 static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15, 3537 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 3538 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 }; 3539 static const BYTE distPointWithReason[] = { 0x30, 0x06, 0x30, 0x04, 0x81, 0x02, 3540 0x00, 0x03 }; 3541 static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13, 3542 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 3543 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 }; 3544 static const BYTE distPointWithUrlAndIssuer[] = { 0x30, 0x2e, 0x30, 0x2c, 0xa0, 3545 0x15, 0xa0, 0x13, 0x86, 0x11, 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 3546 0x69, 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67, 0xa2, 0x13, 0x86, 0x11, 3547 0x68, 0x74, 0x74, 0x70, 0x3a, 0x2f, 0x2f, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71, 3548 0x2e, 0x6f, 0x72, 0x67 }; 3549 static const BYTE crlReason = CRL_REASON_KEY_COMPROMISE | 3550 CRL_REASON_AFFILIATION_CHANGED; 3551 3552 static void test_encodeCRLDistPoints(DWORD dwEncoding) 3553 { 3554 CRL_DIST_POINTS_INFO info = { 0 }; 3555 CRL_DIST_POINT point = { { 0 } }; 3556 CERT_ALT_NAME_ENTRY entry = { 0 }; 3557 BOOL ret; 3558 BYTE *buf = NULL; 3559 DWORD size = 0; 3560 3561 /* Test with an empty info */ 3562 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info, 3563 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3564 ok(!ret && GetLastError() == E_INVALIDARG, 3565 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 3566 /* Test with one empty dist point */ 3567 info.cDistPoint = 1; 3568 info.rgDistPoint = &point; 3569 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info, 3570 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3571 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3572 if (ret) 3573 { 3574 ok(size == sizeof(emptyDistPoint), "Wrong size %d\n", size); 3575 ok(!memcmp(buf, emptyDistPoint, size), "Unexpected value\n"); 3576 LocalFree(buf); 3577 } 3578 /* A dist point with an invalid name */ 3579 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME; 3580 entry.dwAltNameChoice = CERT_ALT_NAME_URL; 3581 U(entry).pwszURL = (LPWSTR)nihongoURL; 3582 U(point.DistPointName).FullName.cAltEntry = 1; 3583 U(point.DistPointName).FullName.rgAltEntry = &entry; 3584 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info, 3585 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3586 ok(!ret && GetLastError() == CRYPT_E_INVALID_IA5_STRING, 3587 "Expected CRYPT_E_INVALID_IA5_STRING, got %08x\n", GetLastError()); 3588 /* The first invalid character is at index 7 */ 3589 ok(GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size) == 7, 3590 "Expected invalid char at index 7, got %d\n", 3591 GET_CERT_ALT_NAME_VALUE_ERR_INDEX(size)); 3592 /* A dist point with (just) a valid name */ 3593 U(entry).pwszURL = (LPWSTR)url; 3594 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info, 3595 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3596 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3597 if (ret) 3598 { 3599 ok(size == sizeof(distPointWithUrl), "Wrong size %d\n", size); 3600 ok(!memcmp(buf, distPointWithUrl, size), "Unexpected value\n"); 3601 LocalFree(buf); 3602 } 3603 /* A dist point with (just) reason flags */ 3604 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_NO_NAME; 3605 point.ReasonFlags.cbData = sizeof(crlReason); 3606 point.ReasonFlags.pbData = (LPBYTE)&crlReason; 3607 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info, 3608 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3609 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3610 if (ret) 3611 { 3612 ok(size == sizeof(distPointWithReason), "Wrong size %d\n", size); 3613 ok(!memcmp(buf, distPointWithReason, size), "Unexpected value\n"); 3614 LocalFree(buf); 3615 } 3616 /* A dist point with just an issuer */ 3617 point.ReasonFlags.cbData = 0; 3618 point.CRLIssuer.cAltEntry = 1; 3619 point.CRLIssuer.rgAltEntry = &entry; 3620 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info, 3621 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3622 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3623 if (ret) 3624 { 3625 ok(size == sizeof(distPointWithIssuer), "Wrong size %d\n", size); 3626 ok(!memcmp(buf, distPointWithIssuer, size), "Unexpected value\n"); 3627 LocalFree(buf); 3628 } 3629 /* A dist point with both a name and an issuer */ 3630 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME; 3631 ret = pCryptEncodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, &info, 3632 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3633 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3634 if (ret) 3635 { 3636 ok(size == sizeof(distPointWithUrlAndIssuer), 3637 "Wrong size %d\n", size); 3638 ok(!memcmp(buf, distPointWithUrlAndIssuer, size), "Unexpected value\n"); 3639 LocalFree(buf); 3640 } 3641 } 3642 3643 static void test_decodeCRLDistPoints(DWORD dwEncoding) 3644 { 3645 BOOL ret; 3646 BYTE *buf = NULL; 3647 DWORD size = 0; 3648 PCRL_DIST_POINTS_INFO info; 3649 PCRL_DIST_POINT point; 3650 PCERT_ALT_NAME_ENTRY entry; 3651 3652 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, 3653 emptyDistPoint, emptyDistPoint[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, 3654 &buf, &size); 3655 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3656 if (ret) 3657 { 3658 info = (PCRL_DIST_POINTS_INFO)buf; 3659 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), 3660 "Wrong size %d\n", size); 3661 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n", 3662 info->cDistPoint); 3663 point = info->rgDistPoint; 3664 ok(point->DistPointName.dwDistPointNameChoice == CRL_DIST_POINT_NO_NAME, 3665 "Expected CRL_DIST_POINT_NO_NAME, got %d\n", 3666 point->DistPointName.dwDistPointNameChoice); 3667 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n"); 3668 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n"); 3669 LocalFree(buf); 3670 } 3671 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, 3672 distPointWithUrl, distPointWithUrl[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, 3673 &buf, &size); 3674 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3675 if (ret) 3676 { 3677 info = (PCRL_DIST_POINTS_INFO)buf; 3678 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), 3679 "Wrong size %d\n", size); 3680 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n", 3681 info->cDistPoint); 3682 point = info->rgDistPoint; 3683 ok(point->DistPointName.dwDistPointNameChoice == 3684 CRL_DIST_POINT_FULL_NAME, 3685 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n", 3686 point->DistPointName.dwDistPointNameChoice); 3687 ok(U(point->DistPointName).FullName.cAltEntry == 1, 3688 "Expected 1 name entry, got %d\n", 3689 U(point->DistPointName).FullName.cAltEntry); 3690 entry = U(point->DistPointName).FullName.rgAltEntry; 3691 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL, 3692 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice); 3693 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n"); 3694 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n"); 3695 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n"); 3696 LocalFree(buf); 3697 } 3698 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, 3699 distPointWithReason, distPointWithReason[1] + 2, CRYPT_DECODE_ALLOC_FLAG, 3700 NULL, &buf, &size); 3701 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3702 if (ret) 3703 { 3704 info = (PCRL_DIST_POINTS_INFO)buf; 3705 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), 3706 "Wrong size %d\n", size); 3707 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n", 3708 info->cDistPoint); 3709 point = info->rgDistPoint; 3710 ok(point->DistPointName.dwDistPointNameChoice == 3711 CRL_DIST_POINT_NO_NAME, 3712 "Expected CRL_DIST_POINT_NO_NAME, got %d\n", 3713 point->DistPointName.dwDistPointNameChoice); 3714 ok(point->ReasonFlags.cbData == sizeof(crlReason), 3715 "Expected reason length\n"); 3716 ok(!memcmp(point->ReasonFlags.pbData, &crlReason, sizeof(crlReason)), 3717 "Unexpected reason\n"); 3718 ok(point->CRLIssuer.cAltEntry == 0, "Expected no issuer\n"); 3719 LocalFree(buf); 3720 } 3721 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, 3722 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 3723 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 3724 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3725 if (ret) 3726 { 3727 info = (PCRL_DIST_POINTS_INFO)buf; 3728 ok(size >= sizeof(CRL_DIST_POINTS_INFO) + sizeof(CRL_DIST_POINT), 3729 "Wrong size %d\n", size); 3730 ok(info->cDistPoint == 1, "Expected 1 dist points, got %d\n", 3731 info->cDistPoint); 3732 point = info->rgDistPoint; 3733 ok(point->DistPointName.dwDistPointNameChoice == 3734 CRL_DIST_POINT_FULL_NAME, 3735 "Expected CRL_DIST_POINT_FULL_NAME, got %d\n", 3736 point->DistPointName.dwDistPointNameChoice); 3737 ok(U(point->DistPointName).FullName.cAltEntry == 1, 3738 "Expected 1 name entry, got %d\n", 3739 U(point->DistPointName).FullName.cAltEntry); 3740 entry = U(point->DistPointName).FullName.rgAltEntry; 3741 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL, 3742 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice); 3743 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n"); 3744 ok(point->ReasonFlags.cbData == 0, "Expected no reason\n"); 3745 ok(point->CRLIssuer.cAltEntry == 1, 3746 "Expected 1 issuer entry, got %d\n", point->CRLIssuer.cAltEntry); 3747 entry = point->CRLIssuer.rgAltEntry; 3748 ok(entry->dwAltNameChoice == CERT_ALT_NAME_URL, 3749 "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice); 3750 ok(!lstrcmpW(U(*entry).pwszURL, url), "Unexpected name\n"); 3751 LocalFree(buf); 3752 } 3753 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, 3754 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0, 3755 NULL, NULL, &size); 3756 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3757 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 3758 if (buf) 3759 { 3760 ret = pCryptDecodeObjectEx(dwEncoding, X509_CRL_DIST_POINTS, 3761 distPointWithUrlAndIssuer, distPointWithUrlAndIssuer[1] + 2, 0, 3762 NULL, buf, &size); 3763 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3764 HeapFree(GetProcessHeap(), 0, buf); 3765 } 3766 } 3767 3768 static const BYTE badFlagsIDP[] = { 0x30,0x06,0x81,0x01,0xff,0x82,0x01,0xff }; 3769 static const BYTE emptyNameIDP[] = { 0x30,0x04,0xa0,0x02,0xa0,0x00 }; 3770 static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68, 3771 0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72, 3772 0x67 }; 3773 3774 static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding) 3775 { 3776 BOOL ret; 3777 BYTE *buf = NULL; 3778 DWORD size = 0; 3779 CRL_ISSUING_DIST_POINT point = { { 0 } }; 3780 CERT_ALT_NAME_ENTRY entry; 3781 3782 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, NULL, 3783 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3784 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 3785 { 3786 skip("no X509_ISSUING_DIST_POINT encode support\n"); 3787 return; 3788 } 3789 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 3790 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); 3791 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point, 3792 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3793 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3794 if (ret) 3795 { 3796 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size); 3797 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n"); 3798 LocalFree(buf); 3799 } 3800 /* nonsensical flags */ 3801 point.fOnlyContainsUserCerts = TRUE; 3802 point.fOnlyContainsCACerts = TRUE; 3803 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point, 3804 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3805 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3806 if (ret) 3807 { 3808 ok(size == sizeof(badFlagsIDP), "Unexpected size %d\n", size); 3809 ok(!memcmp(buf, badFlagsIDP, size), "Unexpected value\n"); 3810 LocalFree(buf); 3811 } 3812 /* unimplemented name type */ 3813 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE; 3814 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_ISSUER_RDN_NAME; 3815 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point, 3816 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3817 ok(!ret && GetLastError() == E_INVALIDARG, 3818 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 3819 /* empty name */ 3820 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME; 3821 U(point.DistPointName).FullName.cAltEntry = 0; 3822 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point, 3823 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3824 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3825 if (ret) 3826 { 3827 ok(size == sizeof(emptyNameIDP), "Unexpected size %d\n", size); 3828 ok(!memcmp(buf, emptyNameIDP, size), "Unexpected value\n"); 3829 LocalFree(buf); 3830 } 3831 /* name with URL entry */ 3832 entry.dwAltNameChoice = CERT_ALT_NAME_URL; 3833 U(entry).pwszURL = (LPWSTR)url; 3834 U(point.DistPointName).FullName.cAltEntry = 1; 3835 U(point.DistPointName).FullName.rgAltEntry = &entry; 3836 ret = pCryptEncodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, &point, 3837 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 3838 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 3839 if (ret) 3840 { 3841 ok(size == sizeof(urlIDP), "Unexpected size %d\n", size); 3842 ok(!memcmp(buf, urlIDP, size), "Unexpected value\n"); 3843 LocalFree(buf); 3844 } 3845 } 3846 3847 static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected, 3848 const CERT_ALT_NAME_ENTRY *got) 3849 { 3850 ok(expected->dwAltNameChoice == got->dwAltNameChoice, 3851 "Expected name choice %d, got %d\n", expected->dwAltNameChoice, 3852 got->dwAltNameChoice); 3853 if (expected->dwAltNameChoice == got->dwAltNameChoice) 3854 { 3855 switch (got->dwAltNameChoice) 3856 { 3857 case CERT_ALT_NAME_RFC822_NAME: 3858 case CERT_ALT_NAME_DNS_NAME: 3859 case CERT_ALT_NAME_EDI_PARTY_NAME: 3860 case CERT_ALT_NAME_URL: 3861 case CERT_ALT_NAME_REGISTERED_ID: 3862 ok((!U(*expected).pwszURL && !U(*got).pwszURL) || 3863 (!U(*expected).pwszURL && !lstrlenW(U(*got).pwszURL)) || 3864 (!U(*got).pwszURL && !lstrlenW(U(*expected).pwszURL)) || 3865 !lstrcmpW(U(*expected).pwszURL, U(*got).pwszURL), 3866 "Unexpected name\n"); 3867 break; 3868 case CERT_ALT_NAME_X400_ADDRESS: 3869 case CERT_ALT_NAME_DIRECTORY_NAME: 3870 case CERT_ALT_NAME_IP_ADDRESS: 3871 ok(U(*got).IPAddress.cbData == U(*expected).IPAddress.cbData, 3872 "Unexpected IP address length %d\n", U(*got).IPAddress.cbData); 3873 ok(!memcmp(U(*got).IPAddress.pbData, U(*expected).IPAddress.pbData, 3874 U(*got).IPAddress.cbData), "Unexpected value\n"); 3875 break; 3876 } 3877 } 3878 } 3879 3880 static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected, 3881 const CERT_ALT_NAME_INFO *got) 3882 { 3883 DWORD i; 3884 3885 ok(expected->cAltEntry == got->cAltEntry, "Expected %d entries, got %d\n", 3886 expected->cAltEntry, got->cAltEntry); 3887 for (i = 0; i < min(expected->cAltEntry, got->cAltEntry); i++) 3888 compareAltNameEntry(&expected->rgAltEntry[i], &got->rgAltEntry[i]); 3889 } 3890 3891 static void compareDistPointName(const CRL_DIST_POINT_NAME *expected, 3892 const CRL_DIST_POINT_NAME *got) 3893 { 3894 ok(got->dwDistPointNameChoice == expected->dwDistPointNameChoice, 3895 "Unexpected name choice %d\n", got->dwDistPointNameChoice); 3896 if (got->dwDistPointNameChoice == CRL_DIST_POINT_FULL_NAME) 3897 compareAltNameInfo(&(U(*expected).FullName), &(U(*got).FullName)); 3898 } 3899 3900 static void compareCRLIssuingDistPoints(const CRL_ISSUING_DIST_POINT *expected, 3901 const CRL_ISSUING_DIST_POINT *got) 3902 { 3903 compareDistPointName(&expected->DistPointName, &got->DistPointName); 3904 ok(got->fOnlyContainsUserCerts == expected->fOnlyContainsUserCerts, 3905 "Unexpected fOnlyContainsUserCerts\n"); 3906 ok(got->fOnlyContainsCACerts == expected->fOnlyContainsCACerts, 3907 "Unexpected fOnlyContainsCACerts\n"); 3908 ok(got->OnlySomeReasonFlags.cbData == expected->OnlySomeReasonFlags.cbData, 3909 "Unexpected reason flags\n"); 3910 ok(got->fIndirectCRL == expected->fIndirectCRL, 3911 "Unexpected fIndirectCRL\n"); 3912 } 3913 3914 static void test_decodeCRLIssuingDistPoint(DWORD dwEncoding) 3915 { 3916 BOOL ret; 3917 BYTE *buf = NULL; 3918 DWORD size = 0; 3919 CRL_ISSUING_DIST_POINT point = { { 0 } }; 3920 3921 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, 3922 emptySequence, emptySequence[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, 3923 &buf, &size); 3924 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 3925 { 3926 skip("no X509_ISSUING_DIST_POINT decode support\n"); 3927 return; 3928 } 3929 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3930 if (ret) 3931 { 3932 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf); 3933 LocalFree(buf); 3934 } 3935 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, 3936 badFlagsIDP, badFlagsIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, 3937 &buf, &size); 3938 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3939 if (ret) 3940 { 3941 point.fOnlyContainsUserCerts = point.fOnlyContainsCACerts = TRUE; 3942 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf); 3943 LocalFree(buf); 3944 } 3945 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, 3946 emptyNameIDP, emptyNameIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, 3947 &buf, &size); 3948 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3949 if (ret) 3950 { 3951 point.fOnlyContainsCACerts = point.fOnlyContainsUserCerts = FALSE; 3952 point.DistPointName.dwDistPointNameChoice = CRL_DIST_POINT_FULL_NAME; 3953 U(point.DistPointName).FullName.cAltEntry = 0; 3954 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf); 3955 LocalFree(buf); 3956 } 3957 ret = pCryptDecodeObjectEx(dwEncoding, X509_ISSUING_DIST_POINT, 3958 urlIDP, urlIDP[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 3959 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 3960 if (ret) 3961 { 3962 CERT_ALT_NAME_ENTRY entry; 3963 3964 entry.dwAltNameChoice = CERT_ALT_NAME_URL; 3965 U(entry).pwszURL = (LPWSTR)url; 3966 U(point.DistPointName).FullName.cAltEntry = 1; 3967 U(point.DistPointName).FullName.rgAltEntry = &entry; 3968 compareCRLIssuingDistPoints(&point, (PCRL_ISSUING_DIST_POINT)buf); 3969 LocalFree(buf); 3970 } 3971 } 3972 3973 static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f, 3974 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 3975 0x30, 0x5a }; 3976 static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, 3977 0x00, 0x18, 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 3978 0x30, 0x30, 0x30, 0x30, 0x5a }; 3979 static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00, 3980 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x0a, 3981 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 0x31, 3982 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 3983 0x5a }; 3984 static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02, 3985 0x06, 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 3986 0x13, 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 3987 0x0f, 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 3988 0x30, 0x30, 0x5a, 0x30, 0x15, 0x30, 0x13, 0x02, 0x00, 0x18, 0x0f, 0x31, 0x36, 3989 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a }; 3990 static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06, 3991 0x00, 0x30, 0x15, 0x31, 0x13, 0x30, 0x11, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 3992 0x0a, 0x4a, 0x75, 0x61, 0x6e, 0x20, 0x4c, 0x61, 0x6e, 0x67, 0x00, 0x18, 0x0f, 3993 0x31, 0x36, 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 3994 0x30, 0x5a, 0x30, 0x16, 0x30, 0x14, 0x02, 0x01, 0x01, 0x18, 0x0f, 0x31, 0x36, 3995 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a }; 3996 static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30, 3997 0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61, 3998 0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31, 3999 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x2c,0x30,0x2a,0x02,0x01, 4000 0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30, 4001 0x30,0x30,0x5a,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01,0xff, 4002 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; 4003 static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15, 4004 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e, 4005 0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30, 4006 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14,0x02,0x01,0x01, 4007 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30, 4008 0x30,0x5a,0xa0,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d,0x13,0x01,0x01, 4009 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; 4010 static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06, 4011 0x00,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a, 4012 0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x18,0x0f,0x31,0x36,0x30,0x31, 4013 0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x16,0x30,0x14, 4014 0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30, 4015 0x30,0x30,0x30,0x30,0x5a,0xa0,0x13,0x30,0x11,0x30,0x0f,0x06,0x03,0x55,0x1d, 4016 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; 4017 4018 static void test_encodeCRLToBeSigned(DWORD dwEncoding) 4019 { 4020 BOOL ret; 4021 BYTE *buf = NULL; 4022 DWORD size = 0; 4023 CRL_INFO info = { 0 }; 4024 CRL_ENTRY entry = { { 0 }, { 0 }, 0, 0 }; 4025 4026 /* Test with a V1 CRL */ 4027 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info, 4028 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4029 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */), 4030 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4031 if (ret) 4032 { 4033 ok(size == sizeof(v1CRL), "Wrong size %d\n", size); 4034 ok(!memcmp(buf, v1CRL, size), "Got unexpected value\n"); 4035 LocalFree(buf); 4036 } 4037 /* Test v2 CRL */ 4038 info.dwVersion = CRL_V2; 4039 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info, 4040 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4041 ok(ret || broken(GetLastError() == OSS_DATA_ERROR /* Win9x */), 4042 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4043 if (ret) 4044 { 4045 ok(size == v2CRL[1] + 2, "Expected size %d, got %d\n", 4046 v2CRL[1] + 2, size); 4047 ok(!memcmp(buf, v2CRL, size), "Got unexpected value\n"); 4048 LocalFree(buf); 4049 } 4050 /* v1 CRL with a name */ 4051 info.dwVersion = CRL_V1; 4052 info.Issuer.cbData = sizeof(encodedCommonName); 4053 info.Issuer.pbData = (BYTE *)encodedCommonName; 4054 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info, 4055 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4056 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4057 if (ret) 4058 { 4059 ok(size == sizeof(v1CRLWithIssuer), "Wrong size %d\n", size); 4060 ok(!memcmp(buf, v1CRLWithIssuer, size), "Got unexpected value\n"); 4061 LocalFree(buf); 4062 } 4063 if (0) 4064 { 4065 /* v1 CRL with a name and a NULL entry pointer (crashes on win9x) */ 4066 info.cCRLEntry = 1; 4067 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info, 4068 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4069 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 4070 "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); 4071 } 4072 /* now set an empty entry */ 4073 info.cCRLEntry = 1; 4074 info.rgCRLEntry = &entry; 4075 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info, 4076 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4077 if (ret) 4078 { 4079 ok(size == sizeof(v1CRLWithIssuerAndEmptyEntry), 4080 "Wrong size %d\n", size); 4081 ok(!memcmp(buf, v1CRLWithIssuerAndEmptyEntry, size), 4082 "Got unexpected value\n"); 4083 LocalFree(buf); 4084 } 4085 /* an entry with a serial number */ 4086 entry.SerialNumber.cbData = sizeof(serialNum); 4087 entry.SerialNumber.pbData = (BYTE *)serialNum; 4088 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info, 4089 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4090 if (ret) 4091 { 4092 ok(size == sizeof(v1CRLWithIssuerAndEntry), 4093 "Wrong size %d\n", size); 4094 ok(!memcmp(buf, v1CRLWithIssuerAndEntry, size), 4095 "Got unexpected value\n"); 4096 LocalFree(buf); 4097 } 4098 /* an entry with an extension */ 4099 entry.cExtension = 1; 4100 entry.rgExtension = &criticalExt; 4101 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info, 4102 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4103 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4104 if (ret) 4105 { 4106 ok(size == sizeof(v1CRLWithEntryExt), "Wrong size %d\n", size); 4107 ok(!memcmp(buf, v1CRLWithEntryExt, size), "Got unexpected value\n"); 4108 LocalFree(buf); 4109 } 4110 /* a CRL with an extension */ 4111 entry.cExtension = 0; 4112 info.cExtension = 1; 4113 info.rgExtension = &criticalExt; 4114 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info, 4115 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4116 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4117 if (ret) 4118 { 4119 ok(size == sizeof(v1CRLWithExt), "Wrong size %d\n", size); 4120 ok(!memcmp(buf, v1CRLWithExt, size), "Got unexpected value\n"); 4121 LocalFree(buf); 4122 } 4123 /* a v2 CRL with an extension, this time non-critical */ 4124 info.dwVersion = CRL_V2; 4125 info.rgExtension = &nonCriticalExt; 4126 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, &info, 4127 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4128 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4129 if (ret) 4130 { 4131 ok(size == sizeof(v2CRLWithExt), "Wrong size %d\n", size); 4132 ok(!memcmp(buf, v2CRLWithExt, size), "Got unexpected value\n"); 4133 LocalFree(buf); 4134 } 4135 } 4136 4137 static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01, 4138 0x1a, 0x02, 0x01, 0x01, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 4139 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x30, 0x61, 0x31, 0x11, 0x30, 0x0f, 0x06, 4140 0x03, 0x55, 0x04, 0x07, 0x13, 0x08, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x65, 4141 0x74, 0x31, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x0a, 0x13, 0x0e, 0x56, 4142 0x65, 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x2c, 0x20, 0x49, 0x6e, 0x63, 0x2e, 4143 0x31, 0x33, 0x30, 0x31, 0x06, 0x03, 0x55, 0x04, 0x0b, 0x13, 0x2a, 0x56, 0x65, 4144 0x72, 0x69, 0x53, 0x69, 0x67, 0x6e, 0x20, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x72, 4145 0x63, 0x69, 0x61, 0x6c, 0x20, 0x53, 0x6f, 0x66, 0x74, 0x77, 0x61, 0x72, 0x65, 4146 0x20, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x65, 0x72, 0x73, 0x20, 0x43, 4147 0x41, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x33, 0x32, 0x34, 0x30, 0x30, 0x30, 0x30, 4148 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x30, 0x34, 0x30, 0x31, 0x30, 0x37, 0x32, 0x33, 4149 0x35, 0x39, 0x35, 0x39, 0x5a, 0x30, 0x69, 0x30, 0x21, 0x02, 0x10, 0x1b, 0x51, 4150 0x90, 0xf7, 0x37, 0x24, 0x39, 0x9c, 0x92, 0x54, 0xcd, 0x42, 0x46, 0x37, 0x99, 4151 0x6a, 0x17, 0x0d, 0x30, 0x31, 0x30, 0x31, 0x33, 0x30, 0x30, 0x30, 0x30, 0x31, 4152 0x32, 0x34, 0x5a, 0x30, 0x21, 0x02, 0x10, 0x75, 0x0e, 0x40, 0xff, 0x97, 0xf0, 4153 0x47, 0xed, 0xf5, 0x56, 0xc7, 0x08, 0x4e, 0xb1, 0xab, 0xfd, 0x17, 0x0d, 0x30, 4154 0x31, 0x30, 0x31, 0x33, 0x31, 0x30, 0x30, 0x30, 0x30, 0x34, 0x39, 0x5a, 0x30, 4155 0x21, 0x02, 0x10, 0x77, 0xe6, 0x5a, 0x43, 0x59, 0x93, 0x5d, 0x5f, 0x7a, 0x75, 4156 0x80, 0x1a, 0xcd, 0xad, 0xc2, 0x22, 0x17, 0x0d, 0x30, 0x30, 0x30, 0x38, 0x33, 4157 0x31, 0x30, 0x30, 0x30, 0x30, 0x35, 0x36, 0x5a, 0xa0, 0x1a, 0x30, 0x18, 0x30, 4158 0x09, 0x06, 0x03, 0x55, 0x1d, 0x13, 0x04, 0x02, 0x30, 0x00, 0x30, 0x0b, 0x06, 4159 0x03, 0x55, 0x1d, 0x0f, 0x04, 0x04, 0x03, 0x02, 0x05, 0xa0, 0x30, 0x0d, 0x06, 4160 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x02, 0x05, 0x00, 0x03, 4161 0x81, 0x81, 0x00, 0x18, 0x2c, 0xe8, 0xfc, 0x16, 0x6d, 0x91, 0x4a, 0x3d, 0x88, 4162 0x54, 0x48, 0x5d, 0xb8, 0x11, 0xbf, 0x64, 0xbb, 0xf9, 0xda, 0x59, 0x19, 0xdd, 4163 0x0e, 0x65, 0xab, 0xc0, 0x0c, 0xfa, 0x67, 0x7e, 0x21, 0x1e, 0x83, 0x0e, 0xcf, 4164 0x9b, 0x89, 0x8a, 0xcf, 0x0c, 0x4b, 0xc1, 0x39, 0x9d, 0xe7, 0x6a, 0xac, 0x46, 4165 0x74, 0x6a, 0x91, 0x62, 0x22, 0x0d, 0xc4, 0x08, 0xbd, 0xf5, 0x0a, 0x90, 0x7f, 4166 0x06, 0x21, 0x3d, 0x7e, 0xa7, 0xaa, 0x5e, 0xcd, 0x22, 0x15, 0xe6, 0x0c, 0x75, 4167 0x8e, 0x6e, 0xad, 0xf1, 0x84, 0xe4, 0x22, 0xb4, 0x30, 0x6f, 0xfb, 0x64, 0x8f, 4168 0xd7, 0x80, 0x43, 0xf5, 0x19, 0x18, 0x66, 0x1d, 0x72, 0xa3, 0xe3, 0x94, 0x82, 4169 0x28, 0x52, 0xa0, 0x06, 0x4e, 0xb1, 0xc8, 0x92, 0x0c, 0x97, 0xbe, 0x15, 0x07, 4170 0xab, 0x7a, 0xc9, 0xea, 0x08, 0x67, 0x43, 0x4d, 0x51, 0x63, 0x3b, 0x9c, 0x9c, 4171 0xcd }; 4172 static const BYTE verisignCRLWithLotsOfEntries[] = { 4173 0x30,0x82,0x1d,0xbd,0x30,0x82,0x1d,0x26,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48, 4174 0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00,0x30,0x61,0x31,0x11,0x30,0x0f,0x06, 4175 0x03,0x55,0x04,0x07,0x13,0x08,0x49,0x6e,0x74,0x65,0x72,0x6e,0x65,0x74,0x31, 4176 0x17,0x30,0x15,0x06,0x03,0x55,0x04,0x0a,0x13,0x0e,0x56,0x65,0x72,0x69,0x53, 4177 0x69,0x67,0x6e,0x2c,0x20,0x49,0x6e,0x63,0x2e,0x31,0x33,0x30,0x31,0x06,0x03, 4178 0x55,0x04,0x0b,0x13,0x2a,0x56,0x65,0x72,0x69,0x53,0x69,0x67,0x6e,0x20,0x43, 4179 0x6f,0x6d,0x6d,0x65,0x72,0x63,0x69,0x61,0x6c,0x20,0x53,0x6f,0x66,0x74,0x77, 4180 0x61,0x72,0x65,0x20,0x50,0x75,0x62,0x6c,0x69,0x73,0x68,0x65,0x72,0x73,0x20, 4181 0x43,0x41,0x17,0x0d,0x30,0x34,0x30,0x33,0x33,0x31,0x30,0x30,0x30,0x30,0x30, 4182 0x30,0x5a,0x17,0x0d,0x30,0x34,0x30,0x35,0x33,0x31,0x32,0x33,0x35,0x39,0x35, 4183 0x39,0x5a,0x30,0x82,0x1c,0x92,0x30,0x21,0x02,0x10,0x01,0x22,0xb8,0xb2,0xf3, 4184 0x76,0x42,0xcc,0x48,0x71,0xb6,0x11,0xbf,0xd1,0xcf,0xda,0x17,0x0d,0x30,0x32, 4185 0x30,0x34,0x31,0x35,0x31,0x35,0x34,0x30,0x32,0x34,0x5a,0x30,0x21,0x02,0x10, 4186 0x01,0x83,0x93,0xfb,0x96,0xde,0x1d,0x89,0x4e,0xc3,0x47,0x9c,0xe1,0x60,0x13, 4187 0x63,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x31,0x33,0x35,0x37,0x35,0x38, 4188 0x5a,0x30,0x21,0x02,0x10,0x01,0xdc,0xdb,0x63,0xd4,0xc9,0x9f,0x31,0xb8,0x16, 4189 0xf9,0x2c,0xf5,0xb1,0x08,0x8e,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31, 4190 0x37,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x02,0x1a,0xa6,0xaf,0x94, 4191 0x71,0xf0,0x07,0x6e,0xf1,0x17,0xe4,0xd4,0x17,0x82,0xdb,0x17,0x0d,0x30,0x32, 4192 0x30,0x37,0x31,0x39,0x32,0x31,0x32,0x38,0x33,0x31,0x5a,0x30,0x21,0x02,0x10, 4193 0x02,0x4c,0xe8,0x9d,0xfd,0x5f,0x77,0x4d,0x4b,0xf5,0x79,0x8b,0xb1,0x08,0x67, 4194 0xac,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x30,0x36,0x31,0x36,0x35,0x30, 4195 0x5a,0x30,0x21,0x02,0x10,0x02,0x59,0xae,0x6c,0x4c,0x21,0xf1,0x59,0x49,0x87, 4196 0xb0,0x95,0xf9,0x65,0xf3,0x20,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x39,0x30, 4197 0x38,0x30,0x34,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x03,0x3c,0x41,0x0e,0x2f, 4198 0x42,0x5c,0x32,0x2c,0xb1,0x35,0xfe,0xe7,0x61,0x97,0xa5,0x17,0x0d,0x30,0x32, 4199 0x30,0x34,0x32,0x34,0x31,0x39,0x34,0x37,0x30,0x32,0x5a,0x30,0x21,0x02,0x10, 4200 0x03,0x4e,0x68,0xfa,0x8b,0xb2,0x8e,0xb9,0x72,0xea,0x72,0xe5,0x3b,0x15,0xac, 4201 0x8b,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x35,0x31,0x35,0x31, 4202 0x5a,0x30,0x21,0x02,0x10,0x03,0xc9,0xa8,0xe3,0x48,0xb0,0x5f,0xcf,0x08,0xee, 4203 0xb9,0x93,0xf9,0xe9,0xaf,0x0c,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x38,0x31, 4204 0x33,0x34,0x39,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x04,0x9b,0x23,0x6a,0x37, 4205 0x5c,0x06,0x98,0x0a,0x31,0xc8,0x86,0xdc,0x3a,0x95,0xcc,0x17,0x0d,0x30,0x32, 4206 0x31,0x30,0x30,0x31,0x32,0x32,0x31,0x30,0x35,0x36,0x5a,0x30,0x21,0x02,0x10, 4207 0x06,0x08,0xba,0xc7,0xac,0xf8,0x5a,0x7c,0xa1,0xf4,0x25,0x85,0xbb,0x4e,0x8c, 4208 0x4f,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x33,0x30,0x37,0x35,0x37,0x31,0x34, 4209 0x5a,0x30,0x21,0x02,0x10,0x07,0x66,0x22,0x4a,0x4a,0x9d,0xff,0x6e,0xb5,0x11, 4210 0x0b,0xa9,0x94,0xfc,0x68,0x20,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30, 4211 0x31,0x34,0x30,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x07,0x8f,0xa1,0x4d,0xb5, 4212 0xfc,0x0c,0xc6,0x42,0x72,0x88,0x37,0x76,0x29,0x44,0x31,0x17,0x0d,0x30,0x32, 4213 0x30,0x33,0x31,0x35,0x32,0x30,0x31,0x39,0x34,0x39,0x5a,0x30,0x21,0x02,0x10, 4214 0x07,0xb9,0xd9,0x42,0x19,0x81,0xc4,0xfd,0x49,0x4f,0x72,0xce,0xf2,0xf8,0x6d, 4215 0x76,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x35,0x31,0x35,0x33,0x37,0x31,0x39, 4216 0x5a,0x30,0x21,0x02,0x10,0x08,0x6e,0xf9,0x6c,0x7f,0xbf,0xbc,0xc8,0x86,0x70, 4217 0x62,0x3f,0xe9,0xc4,0x2f,0x2b,0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x38,0x30, 4218 0x30,0x32,0x38,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x09,0x08,0xe4,0xaa,0xf5, 4219 0x2d,0x2b,0xc0,0x15,0x9e,0x00,0x8b,0x3f,0x97,0x93,0xf9,0x17,0x0d,0x30,0x33, 4220 0x30,0x32,0x31,0x32,0x32,0x32,0x30,0x30,0x32,0x33,0x5a,0x30,0x21,0x02,0x10, 4221 0x09,0x13,0x0a,0x4f,0x0f,0x88,0xe5,0x50,0x05,0xc3,0x5f,0xf4,0xff,0x15,0x39, 4222 0xdd,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x38,0x31,0x31,0x33,0x30, 4223 0x5a,0x30,0x21,0x02,0x10,0x09,0x8d,0xdd,0x37,0xda,0xe7,0x84,0x03,0x9d,0x98, 4224 0x96,0xf8,0x88,0x3a,0x55,0xca,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32, 4225 0x33,0x33,0x35,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x0a,0x35,0x0c,0xd7,0xf4, 4226 0x53,0xe6,0xc1,0x4e,0xf2,0x2a,0xd3,0xce,0xf8,0x7c,0xe7,0x17,0x0d,0x30,0x32, 4227 0x30,0x38,0x30,0x32,0x32,0x32,0x32,0x34,0x32,0x38,0x5a,0x30,0x21,0x02,0x10, 4228 0x0b,0x9c,0xb8,0xf8,0xfb,0x35,0x38,0xf2,0x91,0xfd,0xa1,0xe9,0x69,0x4a,0xb1, 4229 0x24,0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x38,0x30,0x31,0x30,0x32,0x32,0x32, 4230 0x5a,0x30,0x21,0x02,0x10,0x0c,0x2f,0x7f,0x32,0x15,0xe0,0x2f,0x74,0xfa,0x05, 4231 0x22,0x67,0xbc,0x8a,0x2d,0xd0,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31, 4232 0x39,0x30,0x37,0x35,0x34,0x5a,0x30,0x21,0x02,0x10,0x0c,0x32,0x5b,0x78,0x32, 4233 0xc6,0x7c,0xd8,0xdd,0x25,0x91,0x22,0x4d,0x84,0x0a,0x94,0x17,0x0d,0x30,0x32, 4234 0x30,0x33,0x31,0x38,0x31,0x32,0x33,0x39,0x30,0x33,0x5a,0x30,0x21,0x02,0x10, 4235 0x0d,0x76,0x36,0xb9,0x1c,0x72,0xb7,0x9d,0xdf,0xa5,0x35,0x82,0xc5,0xa8,0xf7, 4236 0xbb,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x32,0x31,0x34,0x32,0x31,0x31, 4237 0x5a,0x30,0x21,0x02,0x10,0x0f,0x28,0x79,0x98,0x56,0xb8,0xa5,0x5e,0xeb,0x79, 4238 0x5f,0x1b,0xed,0x0b,0x86,0x76,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x30, 4239 0x31,0x31,0x30,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x0f,0x80,0x3c,0x24,0xf4, 4240 0x62,0x27,0x24,0xbe,0x6a,0x74,0x9c,0x18,0x8e,0x4b,0x3b,0x17,0x0d,0x30,0x32, 4241 0x31,0x31,0x32,0x30,0x31,0x37,0x31,0x31,0x33,0x35,0x5a,0x30,0x21,0x02,0x10, 4242 0x0f,0xf2,0xa7,0x8c,0x80,0x9c,0xbe,0x2f,0xc8,0xa9,0xeb,0xfe,0x94,0x86,0x5a, 4243 0x5c,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x30,0x31,0x39,0x35,0x38,0x34,0x35, 4244 0x5a,0x30,0x21,0x02,0x10,0x10,0x45,0x13,0x35,0x45,0xf3,0xc6,0x02,0x8d,0x8d, 4245 0x18,0xb1,0xc4,0x0a,0x7a,0x18,0x17,0x0d,0x30,0x32,0x30,0x34,0x32,0x36,0x31, 4246 0x37,0x33,0x32,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x10,0x79,0xb1,0x71,0x1b, 4247 0x26,0x98,0x92,0x08,0x1e,0x3c,0xe4,0x8b,0x29,0x37,0xf9,0x17,0x0d,0x30,0x32, 4248 0x30,0x33,0x32,0x38,0x31,0x36,0x33,0x32,0x35,0x35,0x5a,0x30,0x21,0x02,0x10, 4249 0x11,0x38,0x80,0x77,0xcb,0x6b,0xe5,0xd6,0xa7,0xf2,0x99,0xa1,0xc8,0xe9,0x40, 4250 0x25,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x39,0x31,0x32,0x32,0x34,0x31,0x37, 4251 0x5a,0x30,0x21,0x02,0x10,0x11,0x7a,0xc3,0x82,0xfe,0x74,0x36,0x11,0x21,0xd6, 4252 0x92,0x86,0x09,0xdf,0xe6,0xf3,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x31, 4253 0x35,0x31,0x31,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x11,0xab,0x8e,0x21,0x28, 4254 0x7f,0x6d,0xf2,0xc1,0xc8,0x40,0x3e,0xa5,0xde,0x98,0xd3,0x17,0x0d,0x30,0x32, 4255 0x30,0x35,0x30,0x32,0x31,0x38,0x34,0x34,0x33,0x31,0x5a,0x30,0x21,0x02,0x10, 4256 0x12,0x3c,0x38,0xae,0x3f,0x64,0x53,0x3a,0xf7,0xbc,0x6c,0x27,0xe2,0x9c,0x65, 4257 0x75,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x32,0x33,0x30,0x38,0x35,0x39, 4258 0x5a,0x30,0x21,0x02,0x10,0x12,0x88,0xb6,0x6c,0x9b,0xcf,0xe7,0x50,0x92,0xd2, 4259 0x87,0x63,0x8f,0xb7,0xa6,0xe3,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x32, 4260 0x30,0x35,0x35,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x12,0x95,0x4e,0xb6,0x8f, 4261 0x3a,0x19,0x6a,0x16,0x73,0x4f,0x6e,0x15,0xba,0xa5,0xe7,0x17,0x0d,0x30,0x32, 4262 0x30,0x36,0x31,0x37,0x31,0x38,0x35,0x36,0x30,0x31,0x5a,0x30,0x21,0x02,0x10, 4263 0x13,0x37,0x0b,0x41,0x8c,0x31,0x43,0x1c,0x27,0xaa,0xe1,0x83,0x0f,0x99,0x21, 4264 0xcd,0x17,0x0d,0x30,0x32,0x30,0x37,0x32,0x32,0x31,0x32,0x31,0x37,0x31,0x36, 4265 0x5a,0x30,0x21,0x02,0x10,0x14,0x7a,0x29,0x0a,0x09,0x38,0xf4,0x53,0x28,0x33, 4266 0x6f,0x37,0x07,0x23,0x12,0x10,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x30, 4267 0x32,0x30,0x30,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x15,0x04,0x81,0x1e,0xe2, 4268 0x6f,0xf0,0xd8,0xdd,0x12,0x55,0x05,0x66,0x51,0x6e,0x1a,0x17,0x0d,0x30,0x32, 4269 0x30,0x33,0x31,0x33,0x31,0x30,0x35,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10, 4270 0x15,0x30,0x0d,0x8a,0xbd,0x0e,0x89,0x0e,0x66,0x4f,0x49,0x93,0xa2,0x8f,0xbc, 4271 0x2e,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x30,0x36,0x34,0x32,0x32,0x33, 4272 0x5a,0x30,0x21,0x02,0x10,0x16,0xbe,0x64,0xd6,0x4f,0x90,0xf4,0xf7,0x2b,0xc8, 4273 0xca,0x67,0x5c,0x82,0x13,0xe8,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x31, 4274 0x39,0x30,0x39,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x18,0x51,0x9c,0xe4,0x48, 4275 0x62,0x06,0xfe,0xb8,0x2d,0x93,0xb7,0xc9,0xc9,0x1b,0x4e,0x17,0x0d,0x30,0x32, 4276 0x30,0x34,0x31,0x37,0x30,0x35,0x30,0x30,0x34,0x34,0x5a,0x30,0x21,0x02,0x10, 4277 0x19,0x82,0xdb,0x39,0x74,0x00,0x38,0x36,0x59,0xf6,0xcc,0xc1,0x23,0x8d,0x40, 4278 0xe9,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30,0x37,0x35,0x34,0x35,0x34, 4279 0x5a,0x30,0x21,0x02,0x10,0x1b,0x51,0x90,0xf7,0x37,0x24,0x39,0x9c,0x92,0x54, 4280 0xcd,0x42,0x46,0x37,0x99,0x6a,0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x30,0x30, 4281 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x1b,0xe4,0xb2,0xbb,0xb6, 4282 0x74,0x5d,0x6b,0x8b,0x04,0xb6,0xa0,0x1b,0x35,0xeb,0x29,0x17,0x0d,0x30,0x32, 4283 0x30,0x39,0x32,0x35,0x32,0x30,0x31,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10, 4284 0x1c,0x1d,0xd5,0x2a,0xf6,0xaa,0xfd,0xbb,0x47,0xc2,0x73,0x36,0xcf,0x53,0xbd, 4285 0x81,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x30,0x33,0x34,0x32, 4286 0x5a,0x30,0x21,0x02,0x10,0x1c,0xb0,0x5a,0x1f,0xfd,0xa6,0x98,0xf6,0x46,0xf9, 4287 0x32,0x10,0x9e,0xef,0x52,0x8e,0x17,0x0d,0x30,0x32,0x30,0x36,0x32,0x37,0x31, 4288 0x33,0x30,0x33,0x32,0x32,0x5a,0x30,0x21,0x02,0x10,0x1d,0x01,0xfc,0xa7,0xdd, 4289 0xb4,0x0c,0x64,0xbd,0x65,0x45,0xe6,0xbf,0x1c,0x7e,0x90,0x17,0x0d,0x30,0x32, 4290 0x30,0x32,0x32,0x31,0x30,0x34,0x32,0x30,0x30,0x36,0x5a,0x30,0x21,0x02,0x10, 4291 0x1e,0x4d,0xc9,0xc6,0x6e,0x57,0xda,0x8a,0x07,0x97,0x70,0xfa,0xee,0x9c,0xc5, 4292 0x58,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x39,0x32,0x32,0x33,0x34,0x32,0x31, 4293 0x5a,0x30,0x21,0x02,0x10,0x1e,0xbb,0x9b,0x28,0x61,0x50,0x7f,0x12,0x30,0xfb, 4294 0x02,0xb5,0xe1,0xb0,0x7e,0x9d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x36,0x30, 4295 0x30,0x30,0x34,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x1f,0x5a,0x64,0xc9,0xa5, 4296 0x51,0x8c,0xe2,0x2d,0x50,0x83,0xc2,0x4c,0x7c,0xe7,0x85,0x17,0x0d,0x30,0x32, 4297 0x30,0x38,0x32,0x34,0x30,0x36,0x33,0x31,0x32,0x38,0x5a,0x30,0x21,0x02,0x10, 4298 0x1f,0xc2,0x4e,0xd0,0xac,0x52,0xd3,0x39,0x18,0x6d,0xd0,0x0f,0x23,0xd7,0x45, 4299 0x72,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x31,0x39,0x31,0x35,0x34,0x32, 4300 0x5a,0x30,0x20,0x02,0x0f,0x24,0x60,0x7a,0x8e,0x0e,0x86,0xa4,0x88,0x68,0xaf, 4301 0xd9,0x0c,0x6b,0xba,0xff,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x35, 4302 0x31,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x20,0x41,0x73,0xbb,0x72,0x88, 4303 0x6e,0x4b,0x1c,0xb6,0x70,0x02,0x67,0xaa,0x3b,0x3d,0x17,0x0d,0x30,0x32,0x30, 4304 0x39,0x30,0x33,0x31,0x37,0x30,0x36,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x20, 4305 0x6e,0x0d,0xdc,0x8c,0xa4,0xac,0xf7,0x08,0x77,0x5c,0x80,0xf9,0xa3,0x68,0x92, 4306 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x30,0x35,0x37,0x31,0x36,0x5a, 4307 0x30,0x21,0x02,0x10,0x21,0xe4,0x6b,0x98,0x47,0x91,0xe6,0x02,0xdf,0xb2,0x45, 4308 0xbc,0x31,0x37,0xa0,0x7c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x32,0x33, 4309 0x32,0x33,0x31,0x33,0x5a,0x30,0x21,0x02,0x10,0x22,0x00,0x95,0x70,0x79,0xf9, 4310 0x9c,0x34,0x91,0xbb,0x84,0xb9,0x91,0xde,0x22,0x55,0x17,0x0d,0x30,0x32,0x30, 4311 0x32,0x31,0x33,0x30,0x36,0x35,0x39,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x22, 4312 0xf9,0x67,0x4f,0xcd,0x29,0xc6,0xdc,0xc8,0x22,0x6e,0xe9,0x0a,0xa1,0x48,0x5a, 4313 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x30,0x30,0x34,0x33,0x32,0x36,0x5a, 4314 0x30,0x21,0x02,0x10,0x24,0xa3,0xa7,0xd0,0xb8,0x1d,0x1c,0xf7,0xe6,0x1f,0x6e, 4315 0xba,0xc9,0x98,0x59,0xed,0x17,0x0d,0x30,0x33,0x30,0x37,0x32,0x34,0x32,0x30, 4316 0x35,0x38,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x24,0xef,0x89,0xa1,0x30,0x4f, 4317 0x51,0x63,0xfe,0xdb,0xdb,0x64,0x6e,0x4c,0x5a,0x81,0x17,0x0d,0x30,0x32,0x30, 4318 0x37,0x30,0x33,0x30,0x39,0x32,0x31,0x31,0x37,0x5a,0x30,0x21,0x02,0x10,0x25, 4319 0x08,0xe5,0xac,0xdd,0x6f,0x74,0x44,0x51,0x1a,0xf5,0xdb,0xf8,0xba,0x25,0xe0, 4320 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x39,0x30,0x34,0x31,0x36,0x32,0x32,0x5a, 4321 0x30,0x21,0x02,0x10,0x25,0x81,0xe8,0x18,0x60,0x88,0xbc,0x1a,0xe9,0x14,0x84, 4322 0xed,0xd4,0x62,0xf5,0x47,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x33,0x30,0x31, 4323 0x35,0x37,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x26,0xe5,0x5c,0xab,0x16,0xec, 4324 0x61,0x38,0x49,0x2c,0xd2,0xb1,0x48,0x89,0xd5,0x47,0x17,0x0d,0x30,0x32,0x30, 4325 0x33,0x31,0x33,0x31,0x38,0x30,0x30,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x27, 4326 0xbe,0xda,0x7f,0x4f,0x1f,0x6c,0x76,0x09,0xc0,0x9a,0xaf,0xd4,0x68,0xe2,0x16, 4327 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x30,0x31,0x38,0x33,0x32,0x33,0x30,0x5a, 4328 0x30,0x21,0x02,0x10,0x28,0x89,0xd0,0xb3,0xb5,0xc4,0x56,0x36,0x9b,0x3e,0x81, 4329 0x1a,0x21,0x56,0xaa,0x42,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x34,0x31,0x31, 4330 0x30,0x33,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x28,0xab,0x93,0x06,0xb1,0x1e, 4331 0x05,0xe0,0xe1,0x25,0x75,0xc7,0x74,0xcb,0x55,0xa6,0x17,0x0d,0x30,0x33,0x30, 4332 0x31,0x32,0x34,0x31,0x39,0x34,0x38,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x29, 4333 0xe9,0x3b,0x44,0x8d,0xc3,0x4b,0x80,0x17,0xda,0xe4,0x1c,0x43,0x96,0x83,0x59, 4334 0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x37,0x32,0x31,0x34,0x33,0x33,0x39,0x5a, 4335 0x30,0x21,0x02,0x10,0x2a,0x08,0x64,0x2b,0x48,0xe2,0x17,0x89,0x6a,0x0c,0xf9, 4336 0x7e,0x10,0x66,0x8f,0xe7,0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x39,0x31,0x38, 4337 0x33,0x35,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x2a,0x44,0xee,0x91,0x5d,0xe3, 4338 0xa5,0x2b,0x09,0xf3,0x56,0x59,0xe0,0x8f,0x25,0x22,0x17,0x0d,0x30,0x32,0x30, 4339 0x32,0x32,0x31,0x31,0x39,0x33,0x31,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x2a, 4340 0x8b,0x4e,0xa5,0xb6,0x06,0xc8,0x48,0x3b,0x0e,0x71,0x1e,0x6b,0xf4,0x16,0xc1, 4341 0x17,0x0d,0x30,0x32,0x30,0x34,0x33,0x30,0x30,0x39,0x32,0x31,0x31,0x38,0x5a, 4342 0x30,0x21,0x02,0x10,0x2b,0x03,0xfc,0x2f,0xc2,0x8e,0x38,0x29,0x6f,0xa1,0x0f, 4343 0xe9,0x47,0x1b,0x35,0xd7,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x32,0x30, 4344 0x31,0x38,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c,0x48,0xf7,0xd6,0xd5,0x71, 4345 0xc0,0xd1,0xbd,0x6a,0x00,0x65,0x1d,0x2d,0xa9,0xdd,0x17,0x0d,0x30,0x32,0x30, 4346 0x33,0x30,0x36,0x31,0x37,0x32,0x30,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x2c, 4347 0xbf,0x84,0x1d,0xe4,0x58,0x32,0x79,0x32,0x10,0x37,0xde,0xd7,0x94,0xff,0x85, 4348 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x39,0x30,0x32,0x32,0x35,0x5a, 4349 0x30,0x21,0x02,0x10,0x2d,0x03,0x54,0x35,0x54,0x45,0x2c,0x6d,0x39,0xf0,0x1b, 4350 0x74,0x68,0xde,0xcf,0x93,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x33, 4351 0x32,0x33,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d,0x24,0x94,0x34,0x19,0x92, 4352 0xb1,0xf2,0x37,0x9d,0x6e,0xc5,0x35,0x93,0xdd,0xf0,0x17,0x0d,0x30,0x32,0x30, 4353 0x33,0x31,0x35,0x31,0x37,0x31,0x37,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2d, 4354 0x47,0x24,0x61,0x87,0x91,0xba,0x2e,0xf2,0xf7,0x92,0x21,0xf3,0x1b,0x8b,0x1e, 4355 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x32,0x33,0x30,0x38,0x32,0x32,0x5a, 4356 0x30,0x21,0x02,0x10,0x2d,0x84,0xc2,0xb1,0x01,0xa1,0x3a,0x6f,0xb0,0x30,0x13, 4357 0x76,0x5a,0x69,0xec,0x41,0x17,0x0d,0x30,0x32,0x30,0x37,0x31,0x35,0x31,0x37, 4358 0x32,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x2d,0xd5,0x26,0xc3,0xcd,0x01, 4359 0xce,0xfd,0x67,0xb8,0x08,0xac,0x5a,0x70,0xc4,0x34,0x17,0x0d,0x30,0x32,0x30, 4360 0x32,0x32,0x37,0x30,0x34,0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x2e, 4361 0x2b,0x0a,0x94,0x4d,0xf1,0xa4,0x37,0xb7,0xa3,0x9b,0x4b,0x96,0x26,0xa8,0xe3, 4362 0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x39,0x30,0x36,0x32,0x38,0x32,0x38,0x5a, 4363 0x30,0x21,0x02,0x10,0x2e,0x31,0x30,0xc1,0x2e,0x16,0x31,0xd9,0x2b,0x0a,0x70, 4364 0xca,0x3f,0x31,0x73,0x62,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x39,0x30,0x31, 4365 0x34,0x39,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x2e,0xbd,0x6d,0xdf,0xce,0x20, 4366 0x6f,0xe7,0xa8,0xf4,0xf3,0x25,0x9c,0xc3,0xc1,0x12,0x17,0x0d,0x30,0x32,0x30, 4367 0x39,0x32,0x30,0x31,0x33,0x35,0x34,0x34,0x32,0x5a,0x30,0x21,0x02,0x10,0x2f, 4368 0x56,0x16,0x22,0xba,0x87,0xd5,0xfd,0xff,0xe6,0xb0,0xdd,0x3c,0x08,0x26,0x2c, 4369 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x33,0x31,0x37,0x35,0x33,0x31,0x31,0x5a, 4370 0x30,0x21,0x02,0x10,0x30,0x3e,0x77,0x7b,0xec,0xcb,0x89,0x2c,0x15,0x55,0x7f, 4371 0x20,0xf2,0x33,0xc1,0x1e,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x32,0x33, 4372 0x35,0x30,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x30,0x59,0x6c,0xaa,0x5f,0xd3, 4373 0xac,0x50,0x86,0x2c,0xc4,0xfa,0x3c,0x48,0x50,0xd1,0x17,0x0d,0x30,0x32,0x30, 4374 0x32,0x32,0x31,0x30,0x34,0x31,0x39,0x33,0x35,0x5a,0x30,0x21,0x02,0x10,0x30, 4375 0xce,0x9a,0xf1,0xfa,0x17,0xfa,0xf5,0x4c,0xbc,0x52,0x8a,0xf4,0x26,0x2b,0x7b, 4376 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x31,0x31,0x39,0x31,0x32,0x33,0x39,0x5a, 4377 0x30,0x21,0x02,0x10,0x31,0x16,0x4a,0x6a,0x2e,0x6d,0x34,0x4d,0xd2,0x40,0xf0, 4378 0x5f,0x47,0xe6,0x5b,0x47,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x32,0x31,0x37, 4379 0x33,0x38,0x35,0x32,0x5a,0x30,0x21,0x02,0x10,0x31,0xdb,0x97,0x5b,0x06,0x63, 4380 0x0b,0xd8,0xfe,0x06,0xb3,0xf5,0xf9,0x64,0x0a,0x59,0x17,0x0d,0x30,0x32,0x30, 4381 0x32,0x31,0x32,0x31,0x35,0x35,0x39,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x32, 4382 0xbc,0xeb,0x0c,0xca,0x65,0x06,0x3f,0xa4,0xd5,0x4a,0x56,0x46,0x7c,0x22,0x09, 4383 0x17,0x0d,0x30,0x32,0x30,0x38,0x31,0x36,0x30,0x37,0x33,0x33,0x35,0x35,0x5a, 4384 0x30,0x21,0x02,0x10,0x33,0x17,0xef,0xe1,0x89,0xec,0x11,0x25,0x15,0x8f,0x3b, 4385 0x67,0x7a,0x64,0x0b,0x50,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x31,0x37, 4386 0x30,0x33,0x34,0x36,0x5a,0x30,0x21,0x02,0x10,0x34,0x24,0xa0,0xd2,0x00,0x61, 4387 0xeb,0xd3,0x9a,0xa7,0x2a,0x66,0xb4,0x82,0x23,0x77,0x17,0x0d,0x30,0x32,0x30, 4388 0x33,0x31,0x35,0x32,0x32,0x34,0x33,0x33,0x39,0x5a,0x30,0x21,0x02,0x10,0x34, 4389 0xa8,0x16,0x67,0xa5,0x1b,0xa3,0x31,0x11,0x5e,0x26,0xc8,0x3f,0x21,0x38,0xbe, 4390 0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x31,0x32,0x31,0x31,0x36,0x32,0x31,0x5a, 4391 0x30,0x21,0x02,0x10,0x36,0x3a,0xbe,0x05,0x55,0x52,0x93,0x4f,0x32,0x5f,0x30, 4392 0x63,0xc0,0xd4,0x50,0xdf,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x31, 4393 0x34,0x36,0x31,0x34,0x5a,0x30,0x21,0x02,0x10,0x37,0x19,0xcc,0xa5,0x9d,0x85, 4394 0x05,0x56,0xe1,0x63,0x42,0x4b,0x0d,0x3c,0xbf,0xd6,0x17,0x0d,0x30,0x33,0x30, 4395 0x31,0x30,0x38,0x31,0x38,0x35,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x37, 4396 0x2f,0xfd,0x2b,0xec,0x4d,0x94,0x35,0x51,0xf4,0x07,0x2a,0xf5,0x0b,0x97,0xc4, 4397 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x33,0x31,0x39,0x31,0x38,0x30,0x31,0x5a, 4398 0x30,0x21,0x02,0x10,0x37,0x83,0xf5,0x1e,0x7e,0xf4,0x5f,0xad,0x1f,0x0c,0x55, 4399 0x86,0x30,0x02,0x54,0xc1,0x17,0x0d,0x30,0x33,0x30,0x31,0x30,0x38,0x32,0x30, 4400 0x30,0x33,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x38,0x32,0x3e,0x50,0x2b,0x36, 4401 0x93,0x01,0x32,0x0a,0x59,0x8c,0xce,0xad,0xa0,0xeb,0x17,0x0d,0x30,0x32,0x30, 4402 0x34,0x33,0x30,0x32,0x31,0x32,0x34,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3a, 4403 0x62,0xd8,0x64,0xd3,0x85,0xd5,0x61,0x1d,0x9d,0x3f,0x61,0x25,0xe9,0x3a,0x1d, 4404 0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x35,0x31,0x39,0x31,0x36,0x5a, 4405 0x30,0x21,0x02,0x10,0x3a,0x97,0x36,0xb1,0x26,0x14,0x73,0x50,0xa3,0xcc,0x3f, 4406 0xd0,0x3b,0x83,0x99,0xc9,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x31,0x30,0x33, 4407 0x32,0x39,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x3b,0x87,0x3e,0x20,0xbe,0x97, 4408 0xff,0xa7,0x6b,0x2b,0x5f,0xff,0x9a,0x7f,0x4c,0x95,0x17,0x0d,0x30,0x32,0x30, 4409 0x37,0x30,0x33,0x30,0x30,0x33,0x31,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x3b, 4410 0xba,0xe5,0xf2,0x23,0x99,0xc6,0xd7,0xae,0xe2,0x98,0x0d,0xa4,0x13,0x5c,0xd4, 4411 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x34,0x31,0x39,0x32,0x38,0x34,0x35,0x5a, 4412 0x30,0x21,0x02,0x10,0x3b,0xc2,0x7c,0xf0,0xbd,0xd2,0x9a,0x6f,0x97,0xdd,0x76, 4413 0xbc,0xa9,0x6c,0x45,0x0d,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30, 4414 0x34,0x32,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x3b,0xc5,0xda,0x41,0x64,0x7a, 4415 0x37,0x8e,0x9f,0x7f,0x1f,0x9b,0x25,0x0a,0xb4,0xda,0x17,0x0d,0x30,0x32,0x30, 4416 0x33,0x30,0x36,0x31,0x33,0x32,0x34,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x3c, 4417 0x1b,0xf1,0x9a,0x48,0xb0,0xb8,0xa0,0x45,0xd5,0x8f,0x0f,0x57,0x90,0xc2,0xcd, 4418 0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x38,0x30,0x36,0x34,0x33,0x32,0x33,0x5a, 4419 0x30,0x21,0x02,0x10,0x3d,0x15,0x48,0x80,0xb4,0xfe,0x51,0x7e,0xed,0x46,0xae, 4420 0x51,0xfd,0x47,0x73,0xde,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x37,0x30,0x39, 4421 0x32,0x30,0x30,0x38,0x5a,0x30,0x21,0x02,0x10,0x3d,0x61,0x4e,0x87,0xea,0x39, 4422 0x02,0xf3,0x1e,0x3e,0x56,0x5c,0x0e,0x3b,0xa7,0xe3,0x17,0x0d,0x30,0x32,0x31, 4423 0x30,0x32,0x39,0x31,0x39,0x35,0x34,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x3d, 4424 0xdd,0x61,0x92,0x82,0x69,0x6b,0x01,0x79,0x0e,0xef,0x96,0x12,0xa3,0x76,0x80, 4425 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x31,0x32,0x32,0x32,0x34,0x31,0x36,0x5a, 4426 0x30,0x21,0x02,0x10,0x3e,0x0e,0x14,0x71,0x55,0xf3,0x48,0x09,0x1b,0x56,0x3b, 4427 0x91,0x7a,0x7d,0xec,0xc9,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x31,0x32,0x31, 4428 0x34,0x35,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x3e,0x23,0x00,0x1f,0x9b,0xbd, 4429 0xe8,0xb1,0xf0,0x06,0x67,0xa6,0x70,0x42,0x2e,0xc3,0x17,0x0d,0x30,0x32,0x30, 4430 0x38,0x30,0x38,0x31,0x32,0x32,0x31,0x33,0x32,0x5a,0x30,0x21,0x02,0x10,0x41, 4431 0x91,0x1a,0x8c,0xde,0x2d,0xb3,0xeb,0x79,0x1d,0xc7,0x99,0x99,0xbe,0x0c,0x0e, 4432 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x35,0x31,0x39,0x31,0x38,0x35,0x34,0x5a, 4433 0x30,0x21,0x02,0x10,0x41,0xa8,0xd7,0x9c,0x10,0x5e,0x5a,0xac,0x16,0x7f,0x93, 4434 0xaa,0xd1,0x83,0x34,0x55,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x31,0x32, 4435 0x35,0x33,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x42,0x88,0x96,0xb0,0x7b,0x28, 4436 0xa2,0xfa,0x2f,0x91,0x73,0x58,0xa7,0x1e,0x53,0x7c,0x17,0x0d,0x30,0x33,0x30, 4437 0x33,0x30,0x31,0x30,0x39,0x34,0x33,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x42, 4438 0x93,0x2f,0xd2,0x54,0xd3,0x94,0xd0,0x41,0x6a,0x2e,0x33,0x8b,0x81,0xb4,0x3c, 4439 0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x30,0x30,0x34,0x38,0x34,0x36,0x5a, 4440 0x30,0x21,0x02,0x10,0x44,0x24,0xdd,0xba,0x85,0xfd,0x3e,0xb2,0xb8,0x17,0x74, 4441 0xfd,0x9d,0x5c,0x0c,0xbd,0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x31,0x31,0x36, 4442 0x30,0x39,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x45,0x02,0x18,0x7d,0x39,0x9c, 4443 0xb9,0x14,0xfb,0x10,0x37,0x96,0xf4,0xc1,0xdd,0x2f,0x17,0x0d,0x30,0x32,0x30, 4444 0x32,0x31,0x31,0x31,0x31,0x31,0x31,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x45, 4445 0x16,0xbc,0x31,0x0b,0x4e,0x87,0x0a,0xcc,0xe3,0xd5,0x14,0x16,0x33,0x11,0x83, 4446 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x30,0x32,0x32,0x30,0x31,0x37,0x5a, 4447 0x30,0x21,0x02,0x10,0x46,0x16,0x36,0xde,0x3f,0xef,0x8c,0xfa,0x67,0x53,0x12, 4448 0xcc,0x76,0x63,0xd6,0xdd,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x31,0x36, 4449 0x35,0x39,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x46,0x5f,0x85,0xa3,0xa4,0x98, 4450 0x3c,0x40,0x63,0xf6,0x1c,0xf7,0xc2,0xbe,0xfd,0x0e,0x17,0x0d,0x30,0x32,0x30, 4451 0x34,0x30,0x39,0x31,0x35,0x33,0x30,0x30,0x35,0x5a,0x30,0x21,0x02,0x10,0x47, 4452 0x20,0xc2,0xd8,0x85,0x85,0x54,0x39,0xcd,0xf2,0x10,0xf0,0xa7,0x88,0x52,0x75, 4453 0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x30,0x32,0x32,0x32,0x35,0x32,0x37,0x5a, 4454 0x30,0x21,0x02,0x10,0x47,0x42,0x6e,0xa2,0xab,0xc5,0x33,0x5d,0x50,0x44,0x0b, 4455 0x88,0x97,0x84,0x59,0x4c,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x35,0x31,0x34, 4456 0x30,0x35,0x31,0x39,0x5a,0x30,0x21,0x02,0x10,0x49,0x20,0x3f,0xa8,0x6e,0x81, 4457 0xc8,0x3b,0x26,0x05,0xf4,0xa7,0x9b,0x5a,0x81,0x60,0x17,0x0d,0x30,0x32,0x30, 4458 0x37,0x31,0x31,0x31,0x37,0x35,0x30,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x49, 4459 0x8b,0x6f,0x05,0xfb,0xcb,0xf4,0x5a,0xaf,0x09,0x47,0xb1,0x04,0xc5,0xe3,0x51, 4460 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x32,0x31,0x37,0x34,0x38,0x30,0x38,0x5a, 4461 0x30,0x21,0x02,0x10,0x49,0xb2,0xc3,0x7a,0xbf,0x75,0x2a,0xb3,0x13,0xae,0x53, 4462 0xc6,0xcb,0x45,0x5a,0x3e,0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x35,0x32,0x31, 4463 0x33,0x35,0x33,0x37,0x5a,0x30,0x21,0x02,0x10,0x4b,0xca,0xc3,0xab,0x0a,0xc5, 4464 0xcd,0x90,0xa2,0xbe,0x43,0xfe,0xdd,0x06,0xe1,0x45,0x17,0x0d,0x30,0x32,0x30, 4465 0x37,0x32,0x30,0x31,0x37,0x33,0x32,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x4c, 4466 0x00,0xcc,0x73,0xd5,0x74,0x61,0x62,0x92,0x52,0xff,0xde,0x5b,0xc1,0x55,0xbd, 4467 0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x36,0x31,0x34,0x30,0x31,0x35,0x31,0x5a, 4468 0x30,0x21,0x02,0x10,0x4c,0x59,0xc1,0xc3,0x56,0x40,0x27,0xd4,0x22,0x0e,0x37, 4469 0xf6,0x5f,0x26,0x50,0xc5,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x30,0x39, 4470 0x35,0x37,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x4c,0xca,0x12,0x59,0x46,0xf9, 4471 0x2b,0xc6,0x7d,0x33,0x78,0x40,0x2c,0x3b,0x7a,0x0c,0x17,0x0d,0x30,0x32,0x30, 4472 0x35,0x33,0x30,0x32,0x30,0x32,0x34,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x4d, 4473 0x57,0x51,0x35,0x9b,0xe5,0x41,0x2c,0x69,0x66,0xc7,0x21,0xec,0xc6,0x29,0x32, 4474 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x30,0x34,0x33,0x35,0x35,0x36,0x5a, 4475 0x30,0x21,0x02,0x10,0x4e,0x85,0xab,0x9e,0x17,0x54,0xe7,0x42,0x0f,0x8c,0xa1, 4476 0x65,0x96,0x88,0x53,0x54,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x38,0x30,0x30, 4477 0x31,0x38,0x35,0x33,0x5a,0x30,0x21,0x02,0x10,0x50,0x3d,0xed,0xac,0x21,0x86, 4478 0x66,0x5d,0xa5,0x1a,0x13,0xee,0xfc,0xa7,0x0b,0xc6,0x17,0x0d,0x30,0x32,0x30, 4479 0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x34,0x39,0x5a,0x30,0x21,0x02,0x10,0x50, 4480 0xa3,0x81,0x9c,0xcb,0x22,0xe4,0x0f,0x80,0xcb,0x7a,0xec,0x35,0xf8,0x73,0x82, 4481 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x35,0x31,0x36,0x35,0x39,0x35,0x39,0x5a, 4482 0x30,0x21,0x02,0x10,0x51,0x28,0x73,0x26,0x17,0xcf,0x10,0x6e,0xeb,0x4a,0x03, 4483 0x74,0xa3,0x35,0xe5,0x60,0x17,0x0d,0x30,0x33,0x30,0x36,0x31,0x33,0x31,0x30, 4484 0x30,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x51,0x52,0xff,0xdc,0x69,0x6b, 4485 0x1f,0x1f,0xff,0x7c,0xb1,0x7f,0x03,0x90,0xa9,0x6b,0x17,0x0d,0x30,0x32,0x30, 4486 0x36,0x31,0x34,0x31,0x36,0x30,0x34,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x52, 4487 0xd9,0x53,0x69,0x9f,0xec,0xab,0xdd,0x5d,0x2a,0x2f,0xaa,0x57,0x86,0xb9,0x1f, 4488 0x17,0x0d,0x30,0x32,0x30,0x38,0x33,0x30,0x32,0x33,0x34,0x36,0x34,0x33,0x5a, 4489 0x30,0x21,0x02,0x10,0x54,0x46,0xa8,0x8f,0x69,0x2e,0x02,0xf4,0xb4,0xb2,0x69, 4490 0xda,0xbd,0x40,0x02,0xe0,0x17,0x0d,0x30,0x32,0x30,0x33,0x32,0x36,0x30,0x31, 4491 0x35,0x36,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x54,0xb5,0x81,0x73,0xb5,0x7c, 4492 0x6d,0xba,0x5c,0x99,0x0d,0xff,0x0a,0x4d,0xee,0xef,0x17,0x0d,0x30,0x32,0x30, 4493 0x37,0x32,0x34,0x31,0x36,0x33,0x39,0x35,0x31,0x5a,0x30,0x21,0x02,0x10,0x57, 4494 0x91,0x41,0x20,0x9f,0x57,0x6f,0x42,0x53,0x4e,0x19,0xcc,0xe4,0xc8,0x52,0x4a, 4495 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x38,0x32,0x33,0x32,0x34,0x30,0x30,0x5a, 4496 0x30,0x21,0x02,0x10,0x57,0xc6,0xdc,0xa0,0xed,0xbf,0x77,0xdd,0x7e,0x18,0x68, 4497 0x83,0x57,0x0c,0x2a,0x4f,0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x31,0x31,0x34, 4498 0x30,0x36,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x57,0xed,0xe2,0x5b,0xe2,0x62, 4499 0x3f,0x98,0xe1,0xf5,0x4d,0x30,0xa4,0x0e,0xdf,0xdf,0x17,0x0d,0x30,0x32,0x30, 4500 0x36,0x30,0x39,0x30,0x31,0x34,0x37,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x58, 4501 0x47,0xd9,0xbd,0x83,0x1a,0x63,0x6f,0xb7,0x63,0x7f,0x4a,0x56,0x5e,0x8e,0x4d, 4502 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x35,0x31,0x37,0x32,0x33,0x30,0x33,0x5a, 4503 0x30,0x21,0x02,0x10,0x58,0xc6,0x62,0x99,0x80,0xe6,0x0c,0x4f,0x00,0x8b,0x25, 4504 0x38,0x93,0xe6,0x18,0x10,0x17,0x0d,0x30,0x32,0x30,0x36,0x30,0x36,0x30,0x37, 4505 0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x59,0x52,0x09,0x0e,0x99,0xf3, 4506 0xa9,0xe5,0x2f,0xed,0xa9,0xb2,0xd8,0x61,0xe7,0xea,0x17,0x0d,0x30,0x32,0x30, 4507 0x36,0x32,0x36,0x31,0x34,0x31,0x38,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x59, 4508 0x5c,0xaa,0xfb,0xbe,0xfb,0x73,0xd1,0xf4,0xab,0xc8,0xe3,0x3d,0x01,0x04,0xdd, 4509 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x37,0x32,0x32,0x32,0x30,0x31,0x30,0x5a, 4510 0x30,0x21,0x02,0x10,0x59,0x97,0x59,0xa7,0x3d,0xb0,0xd9,0x7e,0xff,0x2a,0xcb, 4511 0x31,0xcc,0x66,0xf3,0x85,0x17,0x0d,0x30,0x32,0x30,0x38,0x32,0x32,0x30,0x30, 4512 0x35,0x35,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x59,0xdd,0x45,0x36,0x61,0xd9, 4513 0x3e,0xe9,0xff,0xbd,0xad,0x2e,0xbf,0x9a,0x5d,0x98,0x17,0x0d,0x30,0x32,0x30, 4514 0x37,0x30,0x32,0x32,0x30,0x34,0x30,0x30,0x33,0x5a,0x30,0x21,0x02,0x10,0x5a, 4515 0x4b,0x48,0x18,0xa9,0x2a,0x9c,0xd5,0x91,0x2f,0x4f,0xa4,0xf8,0xb3,0x1b,0x4d, 4516 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x34,0x32,0x33,0x33,0x33,0x31,0x32,0x5a, 4517 0x30,0x21,0x02,0x10,0x5a,0xdf,0x32,0x0d,0x64,0xeb,0x9b,0xd2,0x11,0xe2,0x58, 4518 0x50,0xbe,0x93,0x0c,0x65,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x35,0x31,0x37, 4519 0x30,0x37,0x32,0x31,0x5a,0x30,0x21,0x02,0x10,0x5b,0x23,0xbf,0xbb,0xc4,0xb3, 4520 0xf4,0x02,0xe9,0xcb,0x10,0x9e,0xee,0xa5,0x3f,0xcd,0x17,0x0d,0x30,0x32,0x30, 4521 0x33,0x32,0x39,0x31,0x36,0x32,0x36,0x35,0x39,0x5a,0x30,0x21,0x02,0x10,0x5b, 4522 0x51,0xbc,0x38,0xbf,0xaf,0x9f,0x27,0xa9,0xc7,0xed,0x25,0xd0,0x8d,0xec,0x2e, 4523 0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x38,0x31,0x30,0x32,0x35,0x32,0x30,0x5a, 4524 0x30,0x21,0x02,0x10,0x5c,0x29,0x7f,0x46,0x61,0xdd,0x47,0x90,0x82,0x91,0xbd, 4525 0x79,0x22,0x6a,0x98,0x38,0x17,0x0d,0x30,0x32,0x31,0x31,0x30,0x38,0x31,0x35, 4526 0x35,0x34,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x5e,0x38,0xf7,0x5b,0x00,0xf1, 4527 0xef,0x1c,0xb6,0xff,0xd5,0x5c,0x74,0xfb,0x95,0x5d,0x17,0x0d,0x30,0x32,0x31, 4528 0x31,0x32,0x33,0x30,0x31,0x34,0x39,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x5e, 4529 0x88,0xbe,0xb6,0xb4,0xb2,0xaa,0xb0,0x92,0xf3,0xf6,0xc2,0xbc,0x72,0x21,0xca, 4530 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x34,0x30,0x37,0x31,0x32,0x31,0x30,0x5a, 4531 0x30,0x21,0x02,0x10,0x5f,0x59,0xa0,0xbb,0xaf,0x26,0xc8,0xc1,0xb4,0x04,0x3a, 4532 0xbb,0xfc,0x4c,0x75,0xa5,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x36,0x31,0x35, 4533 0x35,0x31,0x32,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f,0x81,0x08,0x0f,0xa0,0xcd, 4534 0x44,0x73,0x23,0x58,0x8e,0x49,0x9f,0xb5,0x08,0x35,0x17,0x0d,0x30,0x32,0x30, 4535 0x36,0x31,0x39,0x31,0x34,0x31,0x37,0x34,0x33,0x5a,0x30,0x21,0x02,0x10,0x5f, 4536 0xba,0x1f,0x8f,0xb2,0x23,0x56,0xdd,0xbc,0xa6,0x72,0xb0,0x99,0x13,0xb5,0xb2, 4537 0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x36,0x30,0x38,0x34,0x37,0x31,0x30,0x5a, 4538 0x30,0x21,0x02,0x10,0x60,0x09,0xd5,0xb7,0x6b,0xf1,0x16,0x4a,0xfa,0xd0,0xa5, 4539 0x4c,0x8e,0xdd,0x02,0xcb,0x17,0x0d,0x30,0x32,0x30,0x36,0x31,0x37,0x31,0x36, 4540 0x31,0x32,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x60,0x1d,0x19,0xd8,0x55,0xd5, 4541 0x14,0xd5,0xff,0x03,0x0d,0xad,0x5c,0x07,0x4c,0xe7,0x17,0x0d,0x30,0x32,0x30, 4542 0x37,0x31,0x35,0x32,0x33,0x30,0x31,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x60, 4543 0x24,0x67,0xc3,0x0b,0xad,0x53,0x8f,0xce,0x89,0x05,0xb5,0x87,0xaf,0x7c,0xe4, 4544 0x17,0x0d,0x30,0x32,0x31,0x30,0x30,0x38,0x32,0x30,0x33,0x38,0x35,0x32,0x5a, 4545 0x30,0x21,0x02,0x10,0x60,0x5c,0xf3,0x3d,0x22,0x23,0x39,0x3f,0xe6,0x21,0x09, 4546 0xfd,0xdd,0x77,0xc2,0x8f,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x32,0x31,0x37, 4547 0x32,0x37,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x60,0xa2,0x5e,0xbf,0x07,0x83, 4548 0xa3,0x18,0x56,0x18,0x48,0x63,0xa7,0xfd,0xc7,0x63,0x17,0x0d,0x30,0x32,0x30, 4549 0x35,0x30,0x39,0x31,0x39,0x35,0x32,0x32,0x37,0x5a,0x30,0x21,0x02,0x10,0x60, 4550 0xc2,0xad,0xa8,0x0e,0xf9,0x9a,0x66,0x5d,0xa2,0x75,0x04,0x5e,0x5c,0x71,0xc2, 4551 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x32,0x31,0x33,0x33,0x36,0x31,0x37,0x5a, 4552 0x30,0x21,0x02,0x10,0x60,0xdb,0x1d,0x37,0x34,0xf6,0x02,0x9d,0x68,0x1b,0x70, 4553 0xf1,0x13,0x00,0x2f,0x80,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x38,0x30,0x39, 4554 0x35,0x35,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x61,0xf0,0x38,0xea,0xbc,0x17, 4555 0x0d,0x11,0xd2,0x89,0xee,0x87,0x50,0x57,0xa0,0xed,0x17,0x0d,0x30,0x33,0x30, 4556 0x31,0x32,0x39,0x31,0x37,0x34,0x31,0x34,0x34,0x5a,0x30,0x21,0x02,0x10,0x61, 4557 0xfa,0x9b,0xeb,0x58,0xf9,0xe5,0xa5,0x9e,0x79,0xa8,0x3d,0x79,0xac,0x35,0x97, 4558 0x17,0x0d,0x30,0x32,0x31,0x30,0x31,0x30,0x32,0x30,0x31,0x36,0x33,0x37,0x5a, 4559 0x30,0x21,0x02,0x10,0x62,0x44,0x57,0x24,0x41,0xc0,0x89,0x3f,0x5b,0xd2,0xbd, 4560 0xe7,0x2f,0x75,0x41,0xfa,0x17,0x0d,0x30,0x32,0x30,0x38,0x30,0x38,0x31,0x38, 4561 0x33,0x30,0x31,0x35,0x5a,0x30,0x21,0x02,0x10,0x62,0x51,0x3a,0x2d,0x8d,0x82, 4562 0x39,0x65,0xfe,0xf6,0x8a,0xc8,0x4e,0x29,0x91,0xfd,0x17,0x0d,0x30,0x32,0x30, 4563 0x39,0x32,0x36,0x30,0x30,0x35,0x34,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x62, 4564 0x52,0x49,0x49,0xf2,0x51,0x67,0x7a,0xe2,0xee,0xc9,0x0c,0x23,0x11,0x3d,0xb2, 4565 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x38,0x30,0x36,0x35,0x35,0x5a, 4566 0x30,0x21,0x02,0x10,0x63,0x52,0xbd,0xdc,0xb7,0xbf,0xbb,0x90,0x6c,0x82,0xee, 4567 0xb5,0xa3,0x9f,0xd8,0xc9,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x31,0x31,0x36, 4568 0x33,0x30,0x35,0x38,0x5a,0x30,0x21,0x02,0x10,0x63,0x5e,0x6b,0xe9,0xea,0x3d, 4569 0xd6,0x3b,0xc3,0x4d,0x09,0xc3,0x13,0xdb,0xdd,0xbc,0x17,0x0d,0x30,0x33,0x30, 4570 0x36,0x30,0x32,0x31,0x34,0x34,0x37,0x33,0x36,0x5a,0x30,0x21,0x02,0x10,0x63, 4571 0xda,0x0b,0xd5,0x13,0x1e,0x98,0x83,0x32,0xa2,0x3a,0x4b,0xdf,0x8c,0x89,0x86, 4572 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x35,0x30,0x38,0x30,0x38,0x31,0x33,0x5a, 4573 0x30,0x21,0x02,0x10,0x64,0xfe,0xf0,0x1a,0x3a,0xed,0x89,0xf8,0xb5,0x34,0xd3, 4574 0x1e,0x0f,0xce,0x0d,0xce,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x38,0x32,0x31, 4575 0x30,0x36,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x65,0xa7,0x49,0xd8,0x37,0x22, 4576 0x4b,0x4a,0xe5,0xcf,0xa3,0xfe,0xd6,0x3b,0xc0,0x67,0x17,0x0d,0x30,0x32,0x31, 4577 0x32,0x30,0x34,0x31,0x37,0x31,0x34,0x31,0x36,0x5a,0x30,0x21,0x02,0x10,0x65, 4578 0xc9,0x9e,0x47,0x76,0x98,0x0d,0x9e,0x57,0xe4,0xae,0xc5,0x1c,0x3e,0xf2,0xe7, 4579 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x33,0x31,0x34,0x30,0x38,0x31,0x38,0x5a, 4580 0x30,0x21,0x02,0x10,0x65,0xe0,0x7b,0xc5,0x74,0xe4,0xab,0x01,0x4f,0xa3,0x5e, 4581 0xd6,0xeb,0xcd,0xd5,0x69,0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x33,0x31,0x37, 4582 0x32,0x34,0x30,0x36,0x5a,0x30,0x21,0x02,0x10,0x66,0x51,0xb7,0xe5,0x62,0xb7, 4583 0xe3,0x31,0xc0,0xee,0xf2,0xe8,0xfe,0x84,0x6a,0x4e,0x17,0x0d,0x30,0x32,0x30, 4584 0x39,0x30,0x36,0x31,0x33,0x32,0x33,0x33,0x33,0x5a,0x30,0x21,0x02,0x10,0x67, 4585 0x7c,0x76,0xac,0x66,0x5a,0x6b,0x41,0x5c,0x07,0x83,0x02,0xd6,0xd9,0x63,0xc0, 4586 0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x38,0x31,0x33,0x35,0x35,0x31,0x30,0x5a, 4587 0x30,0x21,0x02,0x10,0x68,0x67,0xde,0xb3,0xaa,0x20,0xcf,0x4b,0x34,0xa5,0xe0, 4588 0xc8,0xc0,0xc5,0xc9,0xa4,0x17,0x0d,0x30,0x32,0x30,0x33,0x31,0x32,0x30,0x31, 4589 0x30,0x39,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x69,0x23,0x34,0x5d,0x75,0x04, 4590 0xdc,0x99,0xbd,0xce,0x8d,0x21,0xb4,0x6b,0x10,0xfc,0x17,0x0d,0x30,0x32,0x30, 4591 0x39,0x30,0x33,0x31,0x33,0x31,0x39,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x69, 4592 0x9f,0x20,0x31,0xd1,0x3f,0xfa,0x1e,0x70,0x2e,0x37,0xd5,0x9a,0x8c,0x0a,0x16, 4593 0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x30,0x30,0x39,0x30,0x31,0x33,0x35,0x5a, 4594 0x30,0x21,0x02,0x10,0x6a,0x94,0xd6,0x25,0xd0,0x67,0xe4,0x4d,0x79,0x2b,0xc6, 4595 0xd5,0xc9,0x4a,0x7f,0xc6,0x17,0x0d,0x30,0x32,0x30,0x32,0x31,0x31,0x31,0x39, 4596 0x31,0x35,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x6b,0x5c,0xa4,0x45,0x5b,0xe9, 4597 0xcf,0xe7,0x3b,0x29,0xb1,0x32,0xd7,0xa1,0x04,0x3d,0x17,0x0d,0x30,0x32,0x31, 4598 0x30,0x31,0x38,0x31,0x35,0x34,0x33,0x34,0x38,0x5a,0x30,0x21,0x02,0x10,0x6b, 4599 0xc0,0x7d,0x4f,0x18,0xfe,0xb7,0x07,0xe8,0x56,0x9a,0x6c,0x40,0x0f,0x36,0x53, 4600 0x17,0x0d,0x30,0x32,0x30,0x39,0x32,0x36,0x32,0x31,0x30,0x31,0x32,0x36,0x5a, 4601 0x30,0x21,0x02,0x10,0x6b,0xe1,0xdd,0x36,0x3b,0xec,0xe0,0xa9,0xf5,0x92,0x7e, 4602 0x33,0xbf,0xed,0x48,0x46,0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x37,0x31,0x34, 4603 0x34,0x32,0x33,0x31,0x5a,0x30,0x21,0x02,0x10,0x6c,0xac,0xeb,0x37,0x2b,0x6a, 4604 0x42,0xe2,0xca,0xc8,0xd2,0xda,0xb8,0xb9,0x82,0x6a,0x17,0x0d,0x30,0x32,0x30, 4605 0x33,0x30,0x31,0x31,0x34,0x32,0x38,0x33,0x34,0x5a,0x30,0x21,0x02,0x10,0x6d, 4606 0x98,0x1b,0xb4,0x76,0xd1,0x62,0x59,0xa1,0x3c,0xee,0xd2,0x21,0xd8,0xdf,0x4c, 4607 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x34,0x31,0x37,0x35,0x36,0x31,0x32,0x5a, 4608 0x30,0x21,0x02,0x10,0x6d,0xdd,0x0b,0x5a,0x3c,0x9c,0xab,0xd3,0x3b,0xd9,0x16, 4609 0xec,0x69,0x74,0xfb,0x9a,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x32,0x31,0x32, 4610 0x32,0x36,0x33,0x38,0x5a,0x30,0x21,0x02,0x10,0x6e,0xde,0xfd,0x89,0x36,0xae, 4611 0xa0,0x41,0x8d,0x5c,0xec,0x2e,0x90,0x31,0xf8,0x9a,0x17,0x0d,0x30,0x32,0x30, 4612 0x34,0x30,0x38,0x32,0x32,0x33,0x36,0x31,0x32,0x5a,0x30,0x21,0x02,0x10,0x6f, 4613 0xb2,0x6b,0x4c,0x48,0xca,0xfe,0xe6,0x69,0x9a,0x06,0x63,0xc4,0x32,0x96,0xc1, 4614 0x17,0x0d,0x30,0x33,0x30,0x31,0x31,0x37,0x31,0x37,0x32,0x37,0x32,0x35,0x5a, 4615 0x30,0x21,0x02,0x10,0x70,0x0b,0xe1,0xee,0x44,0x89,0x51,0x52,0x65,0x27,0x2c, 4616 0x2d,0x34,0x7c,0xe0,0x8d,0x17,0x0d,0x30,0x32,0x30,0x39,0x31,0x38,0x30,0x30, 4617 0x33,0x36,0x30,0x30,0x5a,0x30,0x21,0x02,0x10,0x70,0x2d,0xc0,0xa6,0xb8,0xa5, 4618 0xa0,0xda,0x48,0x59,0xb3,0x96,0x34,0x80,0xc8,0x25,0x17,0x0d,0x30,0x32,0x30, 4619 0x38,0x33,0x30,0x31,0x34,0x30,0x31,0x30,0x31,0x5a,0x30,0x21,0x02,0x10,0x70, 4620 0xe1,0xd9,0x92,0xcd,0x76,0x42,0x63,0x51,0x6e,0xcd,0x8c,0x09,0x29,0x17,0x48, 4621 0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x37,0x31,0x31,0x31,0x30,0x34,0x31,0x5a, 4622 0x30,0x21,0x02,0x10,0x72,0x38,0xe4,0x91,0x6a,0x7a,0x8a,0xf3,0xbf,0xf0,0xd8, 4623 0xe0,0xa4,0x70,0x8d,0xa8,0x17,0x0d,0x30,0x32,0x30,0x33,0x30,0x34,0x31,0x39, 4624 0x30,0x36,0x34,0x30,0x5a,0x30,0x21,0x02,0x10,0x72,0x97,0xa1,0xd8,0x9c,0x3b, 4625 0x00,0xc2,0xc4,0x26,0x2d,0x06,0x2b,0x29,0x76,0x4e,0x17,0x0d,0x30,0x32,0x30, 4626 0x36,0x31,0x38,0x31,0x35,0x30,0x39,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x72, 4627 0xd2,0x23,0x9b,0xf2,0x33,0xe9,0x7c,0xcf,0xb6,0xa9,0x41,0xd5,0x0e,0x5c,0x39, 4628 0x17,0x0d,0x30,0x33,0x30,0x34,0x30,0x39,0x31,0x37,0x30,0x32,0x32,0x39,0x5a, 4629 0x30,0x21,0x02,0x10,0x74,0x5c,0x9c,0xf9,0xaa,0xc3,0xfa,0x94,0x3c,0x25,0x39, 4630 0x65,0x44,0x95,0x13,0xf1,0x17,0x0d,0x30,0x32,0x30,0x37,0x30,0x39,0x32,0x33, 4631 0x35,0x33,0x32,0x30,0x5a,0x30,0x21,0x02,0x10,0x74,0x98,0x7f,0x68,0xad,0x17, 4632 0x92,0x93,0xf2,0x65,0x94,0x0c,0x33,0xe6,0xbd,0x49,0x17,0x0d,0x30,0x32,0x30, 4633 0x34,0x32,0x33,0x30,0x37,0x34,0x34,0x31,0x38,0x5a,0x30,0x21,0x02,0x10,0x75, 4634 0x0e,0x40,0xff,0x97,0xf0,0x47,0xed,0xf5,0x56,0xc7,0x08,0x4e,0xb1,0xab,0xfd, 4635 0x17,0x0d,0x30,0x31,0x30,0x31,0x33,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a, 4636 0x30,0x21,0x02,0x10,0x75,0x26,0x51,0x59,0x65,0xb7,0x33,0x32,0x5f,0xe6,0xcd, 4637 0xaa,0x30,0x65,0x78,0xe0,0x17,0x0d,0x30,0x32,0x30,0x35,0x31,0x36,0x31,0x38, 4638 0x32,0x34,0x35,0x36,0x5a,0x30,0x21,0x02,0x10,0x76,0x13,0x6f,0xbf,0xc8,0xde, 4639 0xd9,0x36,0x30,0x39,0xcc,0x85,0x8f,0x00,0x2f,0x19,0x17,0x0d,0x30,0x32,0x30, 4640 0x33,0x31,0x34,0x30,0x39,0x34,0x38,0x32,0x34,0x5a,0x30,0x21,0x02,0x10,0x76, 4641 0x52,0x78,0x89,0x44,0xfa,0xc1,0xb3,0xd7,0xc9,0x4c,0xb3,0x32,0x95,0xaf,0x03, 4642 0x17,0x0d,0x30,0x32,0x31,0x31,0x31,0x34,0x31,0x39,0x31,0x35,0x34,0x33,0x5a, 4643 0x30,0x21,0x02,0x10,0x77,0x5d,0x4c,0x40,0xd9,0x8d,0xfa,0xc8,0x9a,0x24,0x8d, 4644 0x47,0x10,0x90,0x4a,0x0a,0x17,0x0d,0x30,0x32,0x30,0x35,0x30,0x39,0x30,0x31, 4645 0x31,0x33,0x30,0x32,0x5a,0x30,0x21,0x02,0x10,0x77,0xe6,0x5a,0x43,0x59,0x93, 4646 0x5d,0x5f,0x7a,0x75,0x80,0x1a,0xcd,0xad,0xc2,0x22,0x17,0x0d,0x30,0x30,0x30, 4647 0x38,0x33,0x31,0x31,0x38,0x32,0x32,0x35,0x30,0x5a,0x30,0x21,0x02,0x10,0x78, 4648 0x19,0xf1,0xb6,0x87,0x83,0xaf,0xdf,0x60,0x8d,0x9a,0x64,0x0d,0xec,0xe0,0x51, 4649 0x17,0x0d,0x30,0x32,0x30,0x35,0x32,0x30,0x31,0x37,0x32,0x38,0x31,0x36,0x5a, 4650 0x30,0x21,0x02,0x10,0x78,0x64,0x65,0x8f,0x82,0x79,0xdb,0xa5,0x1c,0x47,0x10, 4651 0x1d,0x72,0x23,0x66,0x52,0x17,0x0d,0x30,0x33,0x30,0x31,0x32,0x34,0x31,0x38, 4652 0x34,0x35,0x34,0x37,0x5a,0x30,0x21,0x02,0x10,0x78,0x64,0xe1,0xc0,0x69,0x8f, 4653 0x3a,0xc7,0x8b,0x23,0xe3,0x29,0xb1,0xee,0xa9,0x41,0x17,0x0d,0x30,0x32,0x30, 4654 0x35,0x30,0x38,0x31,0x37,0x34,0x36,0x32,0x36,0x5a,0x30,0x21,0x02,0x10,0x78, 4655 0x79,0x89,0x61,0x12,0x67,0x64,0x14,0xfd,0x08,0xcc,0xb3,0x05,0x55,0xc0,0x67, 4656 0x17,0x0d,0x30,0x32,0x30,0x34,0x30,0x32,0x31,0x33,0x31,0x38,0x35,0x33,0x5a, 4657 0x30,0x21,0x02,0x10,0x78,0x8a,0x56,0x22,0x08,0xce,0x42,0xee,0xd1,0xa3,0x79, 4658 0x10,0x14,0xfd,0x3a,0x36,0x17,0x0d,0x30,0x33,0x30,0x32,0x30,0x35,0x31,0x36, 4659 0x35,0x33,0x32,0x39,0x5a,0x30,0x21,0x02,0x10,0x7a,0xa0,0x6c,0xba,0x33,0x02, 4660 0xac,0x5f,0xf5,0x0b,0xb6,0x77,0x61,0xef,0x77,0x09,0x17,0x0d,0x30,0x32,0x30, 4661 0x32,0x32,0x38,0x31,0x37,0x35,0x35,0x31,0x31,0x5a,0x30,0x21,0x02,0x10,0x7b, 4662 0x91,0x33,0x66,0x6c,0xf0,0xd4,0xe3,0x9d,0xf6,0x88,0x29,0x9b,0xf7,0xd0,0xea, 4663 0x17,0x0d,0x30,0x32,0x31,0x31,0x32,0x30,0x32,0x32,0x31,0x36,0x34,0x39,0x5a, 4664 0x30,0x21,0x02,0x10,0x7c,0xef,0xf2,0x0a,0x08,0xae,0x10,0x57,0x1e,0xde,0xdc, 4665 0xd6,0x63,0x76,0xb0,0x5d,0x17,0x0d,0x30,0x32,0x30,0x32,0x32,0x36,0x31,0x30, 4666 0x32,0x32,0x33,0x30,0x5a,0x30,0x21,0x02,0x10,0x7f,0x76,0xef,0x69,0xeb,0xf5, 4667 0x3f,0x53,0x2e,0xaa,0xa5,0xed,0xde,0xc0,0xb4,0x06,0x17,0x0d,0x30,0x32,0x30, 4668 0x35,0x30,0x31,0x30,0x33,0x33,0x33,0x30,0x37,0x5a,0x30,0x21,0x02,0x10,0x7f, 4669 0xcb,0x6b,0x99,0x91,0xd0,0x76,0xe1,0x3c,0x0e,0x67,0x15,0xc4,0xd4,0x4d,0x7b, 4670 0x17,0x0d,0x30,0x32,0x30,0x34,0x31,0x30,0x32,0x31,0x31,0x38,0x34,0x30,0x5a, 4671 0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01,0x04,0x05,0x00, 4672 0x03,0x81,0x81,0x00,0x5c,0xb9,0xb3,0xbe,0xd3,0xd6,0x73,0xa3,0xfe,0x4a,0xb2, 4673 0x21,0x80,0xea,0xaa,0x05,0x61,0x14,0x1d,0x67,0xb1,0xdf,0xa6,0xf9,0x42,0x08, 4674 0x0d,0x59,0x62,0x9c,0x11,0x5f,0x0e,0x92,0xc5,0xc6,0xae,0x74,0x64,0xc7,0x84, 4675 0x3e,0x64,0x43,0xd2,0xec,0xbb,0xe1,0x9b,0x52,0x74,0x57,0xcf,0x96,0xef,0x68, 4676 0x02,0x7a,0x7b,0x36,0xb7,0xc6,0x9a,0x5f,0xca,0x9c,0x37,0x47,0xc8,0x3a,0x5c, 4677 0x34,0x35,0x3b,0x4b,0xca,0x20,0x77,0x44,0x68,0x07,0x02,0x34,0x46,0xaa,0x0f, 4678 0xd0,0x4d,0xd9,0x47,0xf4,0xb3,0x2d,0xb1,0x44,0xa5,0x69,0xa9,0x85,0x13,0x43, 4679 0xcd,0xcc,0x1d,0x9a,0xe6,0x2d,0xfd,0x9f,0xdc,0x2f,0x83,0xbb,0x8c,0xe2,0x8c, 4680 0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 }; 4681 4682 static void test_decodeCRLToBeSigned(DWORD dwEncoding) 4683 { 4684 static const BYTE *corruptCRLs[] = { v1CRL, v2CRL }; 4685 BOOL ret; 4686 BYTE *buf = NULL; 4687 DWORD size = 0, i; 4688 4689 for (i = 0; i < ARRAY_SIZE(corruptCRLs); i++) 4690 { 4691 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, 4692 corruptCRLs[i], corruptCRLs[i][1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, 4693 &buf, &size); 4694 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT || 4695 GetLastError() == OSS_DATA_ERROR /* Win9x */), 4696 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n", 4697 GetLastError()); 4698 } 4699 /* at a minimum, a CRL must contain an issuer: */ 4700 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, 4701 v1CRLWithIssuer, v1CRLWithIssuer[1] + 2, CRYPT_DECODE_ALLOC_FLAG, NULL, 4702 &buf, &size); 4703 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 4704 if (ret) 4705 { 4706 CRL_INFO *info = (CRL_INFO *)buf; 4707 4708 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size); 4709 ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n", 4710 info->cCRLEntry); 4711 ok(info->Issuer.cbData == sizeof(encodedCommonName), 4712 "Wrong issuer size %d\n", info->Issuer.cbData); 4713 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData), 4714 "Unexpected issuer\n"); 4715 LocalFree(buf); 4716 } 4717 /* check decoding with an empty CRL entry */ 4718 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, 4719 v1CRLWithIssuerAndEmptyEntry, v1CRLWithIssuerAndEmptyEntry[1] + 2, 4720 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 4721 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT || 4722 GetLastError() == OSS_DATA_ERROR /* Win9x */ || 4723 GetLastError() == CRYPT_E_BAD_ENCODE /* Win8 */), 4724 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %08x\n", 4725 GetLastError()); 4726 /* with a real CRL entry */ 4727 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, 4728 v1CRLWithIssuerAndEntry, v1CRLWithIssuerAndEntry[1] + 2, 4729 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 4730 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 4731 if (ret) 4732 { 4733 CRL_INFO *info = (CRL_INFO *)buf; 4734 CRL_ENTRY *entry; 4735 4736 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size); 4737 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n", 4738 info->cCRLEntry); 4739 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n"); 4740 entry = info->rgCRLEntry; 4741 ok(entry->SerialNumber.cbData == 1, 4742 "Expected serial number size 1, got %d\n", 4743 entry->SerialNumber.cbData); 4744 ok(*entry->SerialNumber.pbData == *serialNum, 4745 "Expected serial number %d, got %d\n", *serialNum, 4746 *entry->SerialNumber.pbData); 4747 ok(info->Issuer.cbData == sizeof(encodedCommonName), 4748 "Wrong issuer size %d\n", info->Issuer.cbData); 4749 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData), 4750 "Unexpected issuer\n"); 4751 LocalFree(buf); 4752 } 4753 /* a real CRL from verisign that has extensions */ 4754 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, 4755 verisignCRL, sizeof(verisignCRL), CRYPT_DECODE_ALLOC_FLAG, 4756 NULL, &buf, &size); 4757 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 4758 if (ret) 4759 { 4760 CRL_INFO *info = (CRL_INFO *)buf; 4761 4762 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size); 4763 ok(info->cCRLEntry == 3, "Expected 3 CRL entries, got %d\n", 4764 info->cCRLEntry); 4765 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n"); 4766 ok(info->cExtension == 2, "Expected 2 extensions, got %d\n", 4767 info->cExtension); 4768 LocalFree(buf); 4769 } 4770 /* another real CRL from verisign that has lots of entries */ 4771 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, 4772 verisignCRLWithLotsOfEntries, sizeof(verisignCRLWithLotsOfEntries), 4773 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 4774 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 4775 if (ret) 4776 { 4777 CRL_INFO *info = (CRL_INFO *)buf; 4778 4779 ok(size >= sizeof(CRL_INFO), "Got size %d\n", size); 4780 ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n", 4781 info->cCRLEntry); 4782 ok(info->cExtension == 0, "Expected 0 extensions, got %d\n", 4783 info->cExtension); 4784 LocalFree(buf); 4785 } 4786 /* and finally, with an extension */ 4787 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, 4788 v1CRLWithExt, sizeof(v1CRLWithExt), CRYPT_DECODE_ALLOC_FLAG, 4789 NULL, &buf, &size); 4790 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 4791 if (ret) 4792 { 4793 CRL_INFO *info = (CRL_INFO *)buf; 4794 CRL_ENTRY *entry; 4795 4796 ok(size >= sizeof(CRL_INFO), "Wrong size %d\n", size); 4797 ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n", 4798 info->cCRLEntry); 4799 ok(info->rgCRLEntry != NULL, "Expected a valid CRL entry array\n"); 4800 entry = info->rgCRLEntry; 4801 ok(entry->SerialNumber.cbData == 1, 4802 "Expected serial number size 1, got %d\n", 4803 entry->SerialNumber.cbData); 4804 ok(*entry->SerialNumber.pbData == *serialNum, 4805 "Expected serial number %d, got %d\n", *serialNum, 4806 *entry->SerialNumber.pbData); 4807 ok(info->Issuer.cbData == sizeof(encodedCommonName), 4808 "Wrong issuer size %d\n", info->Issuer.cbData); 4809 ok(!memcmp(info->Issuer.pbData, encodedCommonName, info->Issuer.cbData), 4810 "Unexpected issuer\n"); 4811 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n", 4812 info->cExtension); 4813 LocalFree(buf); 4814 } 4815 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_CRL_TO_BE_SIGNED, 4816 v2CRLWithExt, sizeof(v2CRLWithExt), CRYPT_DECODE_ALLOC_FLAG, 4817 NULL, &buf, &size); 4818 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 4819 if (ret) 4820 { 4821 CRL_INFO *info = (CRL_INFO *)buf; 4822 4823 ok(info->cExtension == 1, "Expected 1 extensions, got %d\n", 4824 info->cExtension); 4825 LocalFree(buf); 4826 } 4827 } 4828 4829 static const LPCSTR keyUsages[] = { szOID_PKIX_KP_CODE_SIGNING, 4830 szOID_PKIX_KP_CLIENT_AUTH, szOID_RSA_RSA }; 4831 static const BYTE encodedUsage[] = { 4832 0x30, 0x1f, 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x03, 4833 0x06, 0x08, 0x2b, 0x06, 0x01, 0x05, 0x05, 0x07, 0x03, 0x02, 0x06, 0x09, 4834 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01, 0x01 }; 4835 4836 static void test_encodeEnhancedKeyUsage(DWORD dwEncoding) 4837 { 4838 BOOL ret; 4839 BYTE *buf = NULL; 4840 DWORD size = 0; 4841 CERT_ENHKEY_USAGE usage; 4842 4843 /* Test with empty usage */ 4844 usage.cUsageIdentifier = 0; 4845 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage, 4846 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4847 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4848 if (ret) 4849 { 4850 ok(size == sizeof(emptySequence), "Wrong size %d\n", size); 4851 ok(!memcmp(buf, emptySequence, size), "Got unexpected value\n"); 4852 LocalFree(buf); 4853 } 4854 /* Test with a few usages */ 4855 usage.cUsageIdentifier = ARRAY_SIZE(keyUsages); 4856 usage.rgpszUsageIdentifier = (LPSTR *)keyUsages; 4857 ret = pCryptEncodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, &usage, 4858 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4859 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4860 if (ret) 4861 { 4862 ok(size == sizeof(encodedUsage), "Wrong size %d\n", size); 4863 ok(!memcmp(buf, encodedUsage, size), "Got unexpected value\n"); 4864 LocalFree(buf); 4865 } 4866 } 4867 4868 static void test_decodeEnhancedKeyUsage(DWORD dwEncoding) 4869 { 4870 BOOL ret; 4871 LPBYTE buf = NULL; 4872 DWORD size = 0; 4873 4874 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, 4875 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL, 4876 &buf, &size); 4877 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 4878 if (ret) 4879 { 4880 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf; 4881 4882 ok(size >= sizeof(CERT_ENHKEY_USAGE), 4883 "Wrong size %d\n", size); 4884 ok(usage->cUsageIdentifier == 0, "Expected 0 CRL entries, got %d\n", 4885 usage->cUsageIdentifier); 4886 LocalFree(buf); 4887 } 4888 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, 4889 encodedUsage, sizeof(encodedUsage), CRYPT_DECODE_ALLOC_FLAG, NULL, 4890 &buf, &size); 4891 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 4892 if (ret) 4893 { 4894 CERT_ENHKEY_USAGE *usage = (CERT_ENHKEY_USAGE *)buf; 4895 DWORD i; 4896 4897 ok(size >= sizeof(CERT_ENHKEY_USAGE), 4898 "Wrong size %d\n", size); 4899 ok(usage->cUsageIdentifier == ARRAY_SIZE(keyUsages), 4900 "Wrong CRL entries count %d\n", usage->cUsageIdentifier); 4901 for (i = 0; i < usage->cUsageIdentifier; i++) 4902 ok(!strcmp(usage->rgpszUsageIdentifier[i], keyUsages[i]), 4903 "Expected OID %s, got %s\n", keyUsages[i], 4904 usage->rgpszUsageIdentifier[i]); 4905 LocalFree(buf); 4906 } 4907 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, 4908 encodedUsage, sizeof(encodedUsage), 0, NULL, NULL, &size); 4909 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 4910 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 4911 if (buf) 4912 { 4913 ret = pCryptDecodeObjectEx(dwEncoding, X509_ENHANCED_KEY_USAGE, 4914 encodedUsage, sizeof(encodedUsage), 0, NULL, buf, &size); 4915 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 4916 HeapFree(GetProcessHeap(), 0, buf); 4917 } 4918 } 4919 4920 static BYTE keyId[] = { 1,2,3,4 }; 4921 static const BYTE authorityKeyIdWithId[] = { 4922 0x30,0x06,0x80,0x04,0x01,0x02,0x03,0x04 }; 4923 static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15, 4924 0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e, 4925 0x20,0x4c,0x61,0x6e,0x67,0x00 }; 4926 static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 }; 4927 4928 static void test_encodeAuthorityKeyId(DWORD dwEncoding) 4929 { 4930 CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } }; 4931 BOOL ret; 4932 BYTE *buf = NULL; 4933 DWORD size = 0; 4934 4935 /* Test with empty id */ 4936 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info, 4937 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4938 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4939 if (ret) 4940 { 4941 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size); 4942 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n"); 4943 LocalFree(buf); 4944 } 4945 /* With just a key id */ 4946 info.KeyId.cbData = sizeof(keyId); 4947 info.KeyId.pbData = keyId; 4948 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info, 4949 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4950 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4951 if (ret) 4952 { 4953 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", size); 4954 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n"); 4955 LocalFree(buf); 4956 } 4957 /* With just an issuer */ 4958 info.KeyId.cbData = 0; 4959 info.CertIssuer.cbData = sizeof(encodedCommonName); 4960 info.CertIssuer.pbData = (BYTE *)encodedCommonName; 4961 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info, 4962 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4963 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4964 if (ret) 4965 { 4966 ok(size == sizeof(authorityKeyIdWithIssuer), "Unexpected size %d\n", 4967 size); 4968 ok(!memcmp(buf, authorityKeyIdWithIssuer, size), "Unexpected value\n"); 4969 LocalFree(buf); 4970 } 4971 /* With just a serial number */ 4972 info.CertIssuer.cbData = 0; 4973 info.CertSerialNumber.cbData = sizeof(serialNum); 4974 info.CertSerialNumber.pbData = (BYTE *)serialNum; 4975 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, &info, 4976 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 4977 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 4978 if (ret) 4979 { 4980 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n", 4981 size); 4982 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n"); 4983 LocalFree(buf); 4984 } 4985 } 4986 4987 static void test_decodeAuthorityKeyId(DWORD dwEncoding) 4988 { 4989 BOOL ret; 4990 LPBYTE buf = NULL; 4991 DWORD size = 0; 4992 4993 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, 4994 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL, 4995 &buf, &size); 4996 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 4997 if (ret) 4998 { 4999 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf; 5000 5001 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n", 5002 size); 5003 ok(info->KeyId.cbData == 0, "Expected no key id\n"); 5004 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n"); 5005 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n"); 5006 LocalFree(buf); 5007 } 5008 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, 5009 authorityKeyIdWithId, sizeof(authorityKeyIdWithId), 5010 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5011 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5012 if (ret) 5013 { 5014 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf; 5015 5016 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n", 5017 size); 5018 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n"); 5019 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)), 5020 "Unexpected key id\n"); 5021 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n"); 5022 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n"); 5023 LocalFree(buf); 5024 } 5025 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, 5026 authorityKeyIdWithIssuer, sizeof(authorityKeyIdWithIssuer), 5027 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5028 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5029 if (ret) 5030 { 5031 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf; 5032 5033 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n", 5034 size); 5035 ok(info->KeyId.cbData == 0, "Expected no key id\n"); 5036 ok(info->CertIssuer.cbData == sizeof(encodedCommonName), 5037 "Unexpected issuer len\n"); 5038 ok(!memcmp(info->CertIssuer.pbData, encodedCommonName, 5039 sizeof(encodedCommonName)), "Unexpected issuer\n"); 5040 ok(info->CertSerialNumber.cbData == 0, "Expected no serial number\n"); 5041 LocalFree(buf); 5042 } 5043 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID, 5044 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial), 5045 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5046 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5047 if (ret) 5048 { 5049 CERT_AUTHORITY_KEY_ID_INFO *info = (CERT_AUTHORITY_KEY_ID_INFO *)buf; 5050 5051 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n", 5052 size); 5053 ok(info->KeyId.cbData == 0, "Expected no key id\n"); 5054 ok(info->CertIssuer.cbData == 0, "Expected no issuer name\n"); 5055 ok(info->CertSerialNumber.cbData == sizeof(serialNum), 5056 "Unexpected serial number len\n"); 5057 ok(!memcmp(info->CertSerialNumber.pbData, serialNum, sizeof(serialNum)), 5058 "Unexpected serial number\n"); 5059 LocalFree(buf); 5060 } 5061 } 5062 5063 static const BYTE authorityKeyIdWithIssuerUrl[] = { 0x30,0x15,0xa1,0x13,0x86, 5064 0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e, 5065 0x6f,0x72,0x67 }; 5066 5067 static void test_encodeAuthorityKeyId2(DWORD dwEncoding) 5068 { 5069 CERT_AUTHORITY_KEY_ID2_INFO info = { { 0 } }; 5070 CERT_ALT_NAME_ENTRY entry = { 0 }; 5071 BOOL ret; 5072 BYTE *buf = NULL; 5073 DWORD size = 0; 5074 5075 /* Test with empty id */ 5076 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info, 5077 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5078 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5079 if (ret) 5080 { 5081 ok(size == sizeof(emptySequence), "Unexpected size %d\n", size); 5082 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n"); 5083 LocalFree(buf); 5084 } 5085 /* With just a key id */ 5086 info.KeyId.cbData = sizeof(keyId); 5087 info.KeyId.pbData = keyId; 5088 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info, 5089 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5090 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5091 if (ret) 5092 { 5093 ok(size == sizeof(authorityKeyIdWithId), "Unexpected size %d\n", 5094 size); 5095 ok(!memcmp(buf, authorityKeyIdWithId, size), "Unexpected value\n"); 5096 LocalFree(buf); 5097 } 5098 /* With a bogus issuer name */ 5099 info.KeyId.cbData = 0; 5100 info.AuthorityCertIssuer.cAltEntry = 1; 5101 info.AuthorityCertIssuer.rgAltEntry = &entry; 5102 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info, 5103 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5104 ok(!ret && GetLastError() == E_INVALIDARG, 5105 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 5106 /* With an issuer name */ 5107 entry.dwAltNameChoice = CERT_ALT_NAME_URL; 5108 U(entry).pwszURL = (LPWSTR)url; 5109 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info, 5110 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5111 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5112 if (ret) 5113 { 5114 ok(size == sizeof(authorityKeyIdWithIssuerUrl), "Unexpected size %d\n", 5115 size); 5116 ok(!memcmp(buf, authorityKeyIdWithIssuerUrl, size), 5117 "Unexpected value\n"); 5118 LocalFree(buf); 5119 } 5120 /* With just a serial number */ 5121 info.AuthorityCertIssuer.cAltEntry = 0; 5122 info.AuthorityCertSerialNumber.cbData = sizeof(serialNum); 5123 info.AuthorityCertSerialNumber.pbData = (BYTE *)serialNum; 5124 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, &info, 5125 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5126 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5127 if (ret) 5128 { 5129 ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n", 5130 size); 5131 ok(!memcmp(buf, authorityKeyIdWithSerial, size), "Unexpected value\n"); 5132 LocalFree(buf); 5133 } 5134 } 5135 5136 static void test_decodeAuthorityKeyId2(DWORD dwEncoding) 5137 { 5138 BOOL ret; 5139 LPBYTE buf = NULL; 5140 DWORD size = 0; 5141 5142 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, 5143 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL, 5144 &buf, &size); 5145 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5146 if (ret) 5147 { 5148 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf; 5149 5150 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n", 5151 size); 5152 ok(info->KeyId.cbData == 0, "Expected no key id\n"); 5153 ok(info->AuthorityCertIssuer.cAltEntry == 0, 5154 "Expected no issuer name entries\n"); 5155 ok(info->AuthorityCertSerialNumber.cbData == 0, 5156 "Expected no serial number\n"); 5157 LocalFree(buf); 5158 } 5159 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, 5160 authorityKeyIdWithId, sizeof(authorityKeyIdWithId), 5161 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5162 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5163 if (ret) 5164 { 5165 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf; 5166 5167 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n", 5168 size); 5169 ok(info->KeyId.cbData == sizeof(keyId), "Unexpected key id len\n"); 5170 ok(!memcmp(info->KeyId.pbData, keyId, sizeof(keyId)), 5171 "Unexpected key id\n"); 5172 ok(info->AuthorityCertIssuer.cAltEntry == 0, 5173 "Expected no issuer name entries\n"); 5174 ok(info->AuthorityCertSerialNumber.cbData == 0, 5175 "Expected no serial number\n"); 5176 LocalFree(buf); 5177 } 5178 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, 5179 authorityKeyIdWithIssuerUrl, sizeof(authorityKeyIdWithIssuerUrl), 5180 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5181 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5182 if (ret) 5183 { 5184 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf; 5185 5186 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n", 5187 size); 5188 ok(info->KeyId.cbData == 0, "Expected no key id\n"); 5189 ok(info->AuthorityCertIssuer.cAltEntry == 1, 5190 "Expected 1 issuer entry, got %d\n", 5191 info->AuthorityCertIssuer.cAltEntry); 5192 ok(info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice == 5193 CERT_ALT_NAME_URL, "Expected CERT_ALT_NAME_URL, got %d\n", 5194 info->AuthorityCertIssuer.rgAltEntry[0].dwAltNameChoice); 5195 ok(!lstrcmpW(U(info->AuthorityCertIssuer.rgAltEntry[0]).pwszURL, 5196 url), "Unexpected URL\n"); 5197 ok(info->AuthorityCertSerialNumber.cbData == 0, 5198 "Expected no serial number\n"); 5199 LocalFree(buf); 5200 } 5201 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_KEY_ID2, 5202 authorityKeyIdWithSerial, sizeof(authorityKeyIdWithSerial), 5203 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5204 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5205 if (ret) 5206 { 5207 CERT_AUTHORITY_KEY_ID2_INFO *info = (CERT_AUTHORITY_KEY_ID2_INFO *)buf; 5208 5209 ok(size >= sizeof(CERT_AUTHORITY_KEY_ID2_INFO), "Unexpected size %d\n", 5210 size); 5211 ok(info->KeyId.cbData == 0, "Expected no key id\n"); 5212 ok(info->AuthorityCertIssuer.cAltEntry == 0, 5213 "Expected no issuer name entries\n"); 5214 ok(info->AuthorityCertSerialNumber.cbData == sizeof(serialNum), 5215 "Unexpected serial number len\n"); 5216 ok(!memcmp(info->AuthorityCertSerialNumber.pbData, serialNum, 5217 sizeof(serialNum)), "Unexpected serial number\n"); 5218 LocalFree(buf); 5219 } 5220 } 5221 5222 static const BYTE authorityInfoAccessWithUrl[] = { 5223 0x30,0x19,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a, 5224 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 }; 5225 static const BYTE authorityInfoAccessWithUrlAndIPAddr[] = { 5226 0x30,0x29,0x30,0x17,0x06,0x02,0x2a,0x03,0x86,0x11,0x68,0x74,0x74,0x70,0x3a, 5227 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67,0x30,0x0e,0x06, 5228 0x02,0x2d,0x06,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00,0x01 }; 5229 5230 static void test_encodeAuthorityInfoAccess(DWORD dwEncoding) 5231 { 5232 static char oid1[] = "1.2.3"; 5233 static char oid2[] = "1.5.6"; 5234 BOOL ret; 5235 BYTE *buf = NULL; 5236 DWORD size = 0; 5237 CERT_ACCESS_DESCRIPTION accessDescription[2]; 5238 CERT_AUTHORITY_INFO_ACCESS aia; 5239 5240 memset(accessDescription, 0, sizeof(accessDescription)); 5241 aia.cAccDescr = 0; 5242 aia.rgAccDescr = NULL; 5243 /* Having no access descriptions is allowed */ 5244 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia, 5245 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5246 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5247 if (ret) 5248 { 5249 ok(size == sizeof(emptySequence), "unexpected size %d\n", size); 5250 ok(!memcmp(buf, emptySequence, size), "unexpected value\n"); 5251 LocalFree(buf); 5252 buf = NULL; 5253 } 5254 /* It can't have an empty access method */ 5255 aia.cAccDescr = 1; 5256 aia.rgAccDescr = accessDescription; 5257 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia, 5258 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5259 ok(!ret && (GetLastError() == E_INVALIDARG || 5260 GetLastError() == OSS_LIMITED /* Win9x */), 5261 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError()); 5262 /* It can't have an empty location */ 5263 accessDescription[0].pszAccessMethod = oid1; 5264 SetLastError(0xdeadbeef); 5265 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia, 5266 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5267 ok(!ret && GetLastError() == E_INVALIDARG, 5268 "expected E_INVALIDARG, got %08x\n", GetLastError()); 5269 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL; 5270 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url; 5271 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia, 5272 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5273 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5274 if (ret) 5275 { 5276 ok(size == sizeof(authorityInfoAccessWithUrl), "unexpected size %d\n", 5277 size); 5278 ok(!memcmp(buf, authorityInfoAccessWithUrl, size), 5279 "unexpected value\n"); 5280 LocalFree(buf); 5281 buf = NULL; 5282 } 5283 accessDescription[1].pszAccessMethod = oid2; 5284 accessDescription[1].AccessLocation.dwAltNameChoice = 5285 CERT_ALT_NAME_IP_ADDRESS; 5286 U(accessDescription[1].AccessLocation).IPAddress.cbData = 5287 sizeof(encodedIPAddr); 5288 U(accessDescription[1].AccessLocation).IPAddress.pbData = 5289 (LPBYTE)encodedIPAddr; 5290 aia.cAccDescr = 2; 5291 ret = pCryptEncodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, &aia, 5292 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5293 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5294 if (ret) 5295 { 5296 ok(size == sizeof(authorityInfoAccessWithUrlAndIPAddr), 5297 "unexpected size %d\n", size); 5298 ok(!memcmp(buf, authorityInfoAccessWithUrlAndIPAddr, size), 5299 "unexpected value\n"); 5300 LocalFree(buf); 5301 buf = NULL; 5302 } 5303 } 5304 5305 static void compareAuthorityInfoAccess(LPCSTR header, 5306 const CERT_AUTHORITY_INFO_ACCESS *expected, 5307 const CERT_AUTHORITY_INFO_ACCESS *got) 5308 { 5309 DWORD i; 5310 5311 ok(expected->cAccDescr == got->cAccDescr, 5312 "%s: expected %d access descriptions, got %d\n", header, 5313 expected->cAccDescr, got->cAccDescr); 5314 for (i = 0; i < expected->cAccDescr; i++) 5315 { 5316 ok(!strcmp(expected->rgAccDescr[i].pszAccessMethod, 5317 got->rgAccDescr[i].pszAccessMethod), "%s[%d]: expected %s, got %s\n", 5318 header, i, expected->rgAccDescr[i].pszAccessMethod, 5319 got->rgAccDescr[i].pszAccessMethod); 5320 compareAltNameEntry(&expected->rgAccDescr[i].AccessLocation, 5321 &got->rgAccDescr[i].AccessLocation); 5322 } 5323 } 5324 5325 static void test_decodeAuthorityInfoAccess(DWORD dwEncoding) 5326 { 5327 static char oid1[] = "1.2.3"; 5328 static char oid2[] = "1.5.6"; 5329 BOOL ret; 5330 LPBYTE buf = NULL; 5331 DWORD size = 0; 5332 5333 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, 5334 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL, 5335 &buf, &size); 5336 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 5337 if (ret) 5338 { 5339 CERT_AUTHORITY_INFO_ACCESS aia = { 0, NULL }; 5340 5341 compareAuthorityInfoAccess("empty AIA", &aia, 5342 (CERT_AUTHORITY_INFO_ACCESS *)buf); 5343 LocalFree(buf); 5344 buf = NULL; 5345 } 5346 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, 5347 authorityInfoAccessWithUrl, sizeof(authorityInfoAccessWithUrl), 5348 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5349 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 5350 if (ret) 5351 { 5352 CERT_ACCESS_DESCRIPTION accessDescription; 5353 CERT_AUTHORITY_INFO_ACCESS aia; 5354 5355 accessDescription.pszAccessMethod = oid1; 5356 accessDescription.AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL; 5357 U(accessDescription.AccessLocation).pwszURL = (LPWSTR)url; 5358 aia.cAccDescr = 1; 5359 aia.rgAccDescr = &accessDescription; 5360 compareAuthorityInfoAccess("AIA with URL", &aia, 5361 (CERT_AUTHORITY_INFO_ACCESS *)buf); 5362 LocalFree(buf); 5363 buf = NULL; 5364 } 5365 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, 5366 authorityInfoAccessWithUrlAndIPAddr, 5367 sizeof(authorityInfoAccessWithUrlAndIPAddr), CRYPT_DECODE_ALLOC_FLAG, 5368 NULL, &buf, &size); 5369 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 5370 if (ret) 5371 { 5372 CERT_ACCESS_DESCRIPTION accessDescription[2]; 5373 CERT_AUTHORITY_INFO_ACCESS aia; 5374 5375 accessDescription[0].pszAccessMethod = oid1; 5376 accessDescription[0].AccessLocation.dwAltNameChoice = CERT_ALT_NAME_URL; 5377 U(accessDescription[0].AccessLocation).pwszURL = (LPWSTR)url; 5378 accessDescription[1].pszAccessMethod = oid2; 5379 accessDescription[1].AccessLocation.dwAltNameChoice = 5380 CERT_ALT_NAME_IP_ADDRESS; 5381 U(accessDescription[1].AccessLocation).IPAddress.cbData = 5382 sizeof(encodedIPAddr); 5383 U(accessDescription[1].AccessLocation).IPAddress.pbData = 5384 (LPBYTE)encodedIPAddr; 5385 aia.cAccDescr = 2; 5386 aia.rgAccDescr = accessDescription; 5387 compareAuthorityInfoAccess("AIA with URL and IP addr", &aia, 5388 (CERT_AUTHORITY_INFO_ACCESS *)buf); 5389 LocalFree(buf); 5390 buf = NULL; 5391 } 5392 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, 5393 authorityInfoAccessWithUrlAndIPAddr, 5394 sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, NULL, &size); 5395 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 5396 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 5397 if (buf) 5398 { 5399 ret = pCryptDecodeObjectEx(dwEncoding, X509_AUTHORITY_INFO_ACCESS, 5400 authorityInfoAccessWithUrlAndIPAddr, 5401 sizeof(authorityInfoAccessWithUrlAndIPAddr), 0, NULL, buf, &size); 5402 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 5403 HeapFree(GetProcessHeap(), 0, buf); 5404 } 5405 } 5406 5407 static const BYTE emptyCTL[] = { 5408 0x30,0x17,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30, 5409 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 }; 5410 static const BYTE emptyCTLWithVersion1[] = { 5411 0x30,0x1a,0x02,0x01,0x01,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31, 5412 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 }; 5413 static const BYTE ctlWithUsageIdentifier[] = { 5414 0x30,0x1b,0x30,0x04,0x06,0x02,0x2a,0x03,0x18,0x0f,0x31,0x36,0x30,0x31,0x30, 5415 0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 }; 5416 static const BYTE ctlWithListIdentifier[] = { 5417 0x30,0x1a,0x30,0x00,0x04,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31, 5418 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 }; 5419 static const BYTE ctlWithSequenceNumber[] = { 5420 0x30,0x1a,0x30,0x00,0x02,0x01,0x01,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31, 5421 0x30,0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 }; 5422 static const BYTE ctlWithThisUpdate[] = { 5423 0x30,0x15,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31, 5424 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 }; 5425 static const BYTE ctlWithThisAndNextUpdate[] = { 5426 0x30,0x24,0x30,0x00,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31, 5427 0x30,0x30,0x30,0x5a,0x17,0x0d,0x30,0x35,0x30,0x36,0x30,0x36,0x31,0x36,0x31, 5428 0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00 }; 5429 static const BYTE ctlWithAlgId[] = { 5430 0x30,0x1b,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30, 5431 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 }; 5432 static const BYTE ctlWithBogusEntry[] = { 5433 0x30,0x29,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30, 5434 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x10,0x30,0x0e,0x04, 5435 0x01,0x01,0x31,0x09,0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01,0x01 }; 5436 static const BYTE ctlWithOneEntry[] = { 5437 0x30,0x2a,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30, 5438 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x11,0x30,0x0f,0x04, 5439 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00 }; 5440 static const BYTE ctlWithTwoEntries[] = { 5441 0x30,0x41,0x30,0x00,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30, 5442 0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x02,0x06,0x00,0x30,0x28,0x30,0x0f,0x04, 5443 0x01,0x01,0x31,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x31,0x02,0x30,0x00,0x30, 5444 0x15,0x04,0x01,0x01,0x31,0x10,0x30,0x0e,0x06,0x02,0x2d,0x06,0x31,0x08,0x30, 5445 0x06,0x87,0x04,0x7f,0x00,0x00,0x01 }; 5446 5447 static void test_encodeCTL(DWORD dwEncoding) 5448 { 5449 static char oid1[] = "1.2.3"; 5450 static char oid2[] = "1.5.6"; 5451 char *pOid1 = oid1; 5452 BOOL ret; 5453 BYTE *buf = NULL; 5454 DWORD size = 0; 5455 CTL_INFO info; 5456 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 }; 5457 CTL_ENTRY ctlEntry[2]; 5458 CRYPT_ATTRIBUTE attr1, attr2; 5459 CRYPT_ATTR_BLOB value1, value2; 5460 5461 memset(&info, 0, sizeof(info)); 5462 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info, 5463 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5464 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5465 if (ret) 5466 { 5467 ok(size == sizeof(emptyCTL), "unexpected size %d\n", size); 5468 ok(!memcmp(buf, emptyCTL, size), "unexpected value\n"); 5469 LocalFree(buf); 5470 buf = NULL; 5471 } 5472 info.dwVersion = 1; 5473 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info, 5474 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5475 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5476 if (ret) 5477 { 5478 ok(size == sizeof(emptyCTLWithVersion1), "unexpected size %d\n", size); 5479 ok(!memcmp(buf, emptyCTLWithVersion1, size), "unexpected value\n"); 5480 LocalFree(buf); 5481 buf = NULL; 5482 } 5483 info.dwVersion = 0; 5484 info.SubjectUsage.cUsageIdentifier = 1; 5485 info.SubjectUsage.rgpszUsageIdentifier = &pOid1; 5486 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info, 5487 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5488 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5489 if (ret) 5490 { 5491 ok(size == sizeof(ctlWithUsageIdentifier), "unexpected size %d\n", 5492 size); 5493 ok(!memcmp(buf, ctlWithUsageIdentifier, size), "unexpected value\n"); 5494 LocalFree(buf); 5495 buf = NULL; 5496 } 5497 info.SubjectUsage.cUsageIdentifier = 0; 5498 info.ListIdentifier.cbData = sizeof(serialNum); 5499 info.ListIdentifier.pbData = (LPBYTE)serialNum; 5500 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info, 5501 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5502 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5503 if (ret) 5504 { 5505 ok(size == sizeof(ctlWithListIdentifier), "unexpected size %d\n", size); 5506 ok(!memcmp(buf, ctlWithListIdentifier, size), "unexpected value\n"); 5507 LocalFree(buf); 5508 buf = NULL; 5509 } 5510 info.ListIdentifier.cbData = 0; 5511 info.SequenceNumber.cbData = sizeof(serialNum); 5512 info.SequenceNumber.pbData = (LPBYTE)serialNum; 5513 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info, 5514 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5515 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5516 if (ret) 5517 { 5518 ok(size == sizeof(ctlWithSequenceNumber), "unexpected size %d\n", 5519 size); 5520 ok(!memcmp(buf, ctlWithSequenceNumber, size), "unexpected value\n"); 5521 LocalFree(buf); 5522 buf = NULL; 5523 } 5524 info.SequenceNumber.cbData = 0; 5525 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate); 5526 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info, 5527 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5528 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5529 if (ret) 5530 { 5531 ok(size == sizeof(ctlWithThisUpdate), "unexpected size %d\n", size); 5532 ok(!memcmp(buf, ctlWithThisUpdate, size), "unexpected value\n"); 5533 LocalFree(buf); 5534 buf = NULL; 5535 } 5536 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate); 5537 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info, 5538 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5539 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5540 if (ret) 5541 { 5542 ok(size == sizeof(ctlWithThisAndNextUpdate), "unexpected size %d\n", 5543 size); 5544 ok(!memcmp(buf, ctlWithThisAndNextUpdate, size), "unexpected value\n"); 5545 LocalFree(buf); 5546 buf = NULL; 5547 } 5548 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0; 5549 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0; 5550 info.SubjectAlgorithm.pszObjId = oid2; 5551 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info, 5552 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5553 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5554 if (ret) 5555 { 5556 ok(size == sizeof(ctlWithAlgId), "unexpected size %d\n", size); 5557 ok(!memcmp(buf, ctlWithAlgId, size), "unexpected value\n"); 5558 LocalFree(buf); 5559 buf = NULL; 5560 } 5561 /* The value is supposed to be asn.1 encoded, so this'll fail to decode 5562 * (see tests below) but it'll encode fine. 5563 */ 5564 info.SubjectAlgorithm.pszObjId = NULL; 5565 value1.cbData = sizeof(serialNum); 5566 value1.pbData = (LPBYTE)serialNum; 5567 attr1.pszObjId = oid1; 5568 attr1.cValue = 1; 5569 attr1.rgValue = &value1; 5570 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum); 5571 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum; 5572 ctlEntry[0].cAttribute = 1; 5573 ctlEntry[0].rgAttribute = &attr1; 5574 info.cCTLEntry = 1; 5575 info.rgCTLEntry = ctlEntry; 5576 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info, 5577 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5578 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5579 if (ret) 5580 { 5581 ok(size == sizeof(ctlWithBogusEntry), "unexpected size %d\n", size); 5582 ok(!memcmp(buf, ctlWithBogusEntry, size), "unexpected value\n"); 5583 LocalFree(buf); 5584 buf = NULL; 5585 } 5586 value1.cbData = sizeof(emptySequence); 5587 value1.pbData = (LPBYTE)emptySequence; 5588 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info, 5589 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5590 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5591 if (ret) 5592 { 5593 ok(size == sizeof(ctlWithOneEntry), "unexpected size %d\n", size); 5594 ok(!memcmp(buf, ctlWithOneEntry, size), "unexpected value\n"); 5595 LocalFree(buf); 5596 buf = NULL; 5597 } 5598 value2.cbData = sizeof(encodedIPAddr); 5599 value2.pbData = (LPBYTE)encodedIPAddr; 5600 attr2.pszObjId = oid2; 5601 attr2.cValue = 1; 5602 attr2.rgValue = &value2; 5603 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum); 5604 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum; 5605 ctlEntry[1].cAttribute = 1; 5606 ctlEntry[1].rgAttribute = &attr2; 5607 info.cCTLEntry = 2; 5608 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CTL, &info, 5609 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5610 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 5611 if (ret) 5612 { 5613 ok(size == sizeof(ctlWithTwoEntries), "unexpected size %d\n", size); 5614 ok(!memcmp(buf, ctlWithTwoEntries, size), "unexpected value\n"); 5615 LocalFree(buf); 5616 buf = NULL; 5617 } 5618 } 5619 5620 static void compareCTLInfo(LPCSTR header, const CTL_INFO *expected, 5621 const CTL_INFO *got) 5622 { 5623 DWORD i, j, k; 5624 5625 ok(expected->dwVersion == got->dwVersion, 5626 "%s: expected version %d, got %d\n", header, expected->dwVersion, 5627 got->dwVersion); 5628 ok(expected->SubjectUsage.cUsageIdentifier == 5629 got->SubjectUsage.cUsageIdentifier, 5630 "%s: expected %d usage identifiers, got %d\n", header, 5631 expected->SubjectUsage.cUsageIdentifier, 5632 got->SubjectUsage.cUsageIdentifier); 5633 for (i = 0; i < expected->SubjectUsage.cUsageIdentifier; i++) 5634 ok(!strcmp(expected->SubjectUsage.rgpszUsageIdentifier[i], 5635 got->SubjectUsage.rgpszUsageIdentifier[i]), 5636 "%s[%d]: expected %s, got %s\n", header, i, 5637 expected->SubjectUsage.rgpszUsageIdentifier[i], 5638 got->SubjectUsage.rgpszUsageIdentifier[i]); 5639 ok(expected->ListIdentifier.cbData == got->ListIdentifier.cbData, 5640 "%s: expected list identifier of %d bytes, got %d\n", header, 5641 expected->ListIdentifier.cbData, got->ListIdentifier.cbData); 5642 if (expected->ListIdentifier.cbData) 5643 ok(!memcmp(expected->ListIdentifier.pbData, got->ListIdentifier.pbData, 5644 expected->ListIdentifier.cbData), 5645 "%s: unexpected list identifier value\n", header); 5646 ok(expected->SequenceNumber.cbData == got->SequenceNumber.cbData, 5647 "%s: expected sequence number of %d bytes, got %d\n", header, 5648 expected->SequenceNumber.cbData, got->SequenceNumber.cbData); 5649 if (expected->SequenceNumber.cbData) 5650 ok(!memcmp(expected->SequenceNumber.pbData, got->SequenceNumber.pbData, 5651 expected->SequenceNumber.cbData), 5652 "%s: unexpected sequence number value\n", header); 5653 ok(!memcmp(&expected->ThisUpdate, &got->ThisUpdate, sizeof(FILETIME)), 5654 "%s: expected this update = (%d, %d), got (%d, %d)\n", header, 5655 expected->ThisUpdate.dwLowDateTime, expected->ThisUpdate.dwHighDateTime, 5656 got->ThisUpdate.dwLowDateTime, got->ThisUpdate.dwHighDateTime); 5657 ok(!memcmp(&expected->NextUpdate, &got->NextUpdate, sizeof(FILETIME)), 5658 "%s: expected next update = (%d, %d), got (%d, %d)\n", header, 5659 expected->NextUpdate.dwLowDateTime, expected->NextUpdate.dwHighDateTime, 5660 got->NextUpdate.dwLowDateTime, got->NextUpdate.dwHighDateTime); 5661 if (expected->SubjectAlgorithm.pszObjId && 5662 *expected->SubjectAlgorithm.pszObjId && !got->SubjectAlgorithm.pszObjId) 5663 ok(0, "%s: expected subject algorithm %s, got NULL\n", header, 5664 expected->SubjectAlgorithm.pszObjId); 5665 if (expected->SubjectAlgorithm.pszObjId && got->SubjectAlgorithm.pszObjId) 5666 ok(!strcmp(expected->SubjectAlgorithm.pszObjId, 5667 got->SubjectAlgorithm.pszObjId), 5668 "%s: expected subject algorithm %s, got %s\n", header, 5669 expected->SubjectAlgorithm.pszObjId, got->SubjectAlgorithm.pszObjId); 5670 ok(expected->SubjectAlgorithm.Parameters.cbData == 5671 got->SubjectAlgorithm.Parameters.cbData, 5672 "%s: expected subject algorithm parameters of %d bytes, got %d\n", header, 5673 expected->SubjectAlgorithm.Parameters.cbData, 5674 got->SubjectAlgorithm.Parameters.cbData); 5675 if (expected->SubjectAlgorithm.Parameters.cbData) 5676 ok(!memcmp(expected->SubjectAlgorithm.Parameters.pbData, 5677 got->SubjectAlgorithm.Parameters.pbData, 5678 expected->SubjectAlgorithm.Parameters.cbData), 5679 "%s: unexpected subject algorithm parameter value\n", header); 5680 ok(expected->cCTLEntry == got->cCTLEntry, 5681 "%s: expected %d CTL entries, got %d\n", header, expected->cCTLEntry, 5682 got->cCTLEntry); 5683 for (i = 0; i < expected->cCTLEntry; i++) 5684 { 5685 ok(expected->rgCTLEntry[i].SubjectIdentifier.cbData == 5686 got->rgCTLEntry[i].SubjectIdentifier.cbData, 5687 "%s[%d]: expected subject identifier of %d bytes, got %d\n", 5688 header, i, expected->rgCTLEntry[i].SubjectIdentifier.cbData, 5689 got->rgCTLEntry[i].SubjectIdentifier.cbData); 5690 if (expected->rgCTLEntry[i].SubjectIdentifier.cbData) 5691 ok(!memcmp(expected->rgCTLEntry[i].SubjectIdentifier.pbData, 5692 got->rgCTLEntry[i].SubjectIdentifier.pbData, 5693 expected->rgCTLEntry[i].SubjectIdentifier.cbData), 5694 "%s[%d]: unexpected subject identifier value\n", 5695 header, i); 5696 for (j = 0; j < expected->rgCTLEntry[i].cAttribute; j++) 5697 { 5698 ok(!strcmp(expected->rgCTLEntry[i].rgAttribute[j].pszObjId, 5699 got->rgCTLEntry[i].rgAttribute[j].pszObjId), 5700 "%s[%d][%d]: expected attribute OID %s, got %s\n", header, i, j, 5701 expected->rgCTLEntry[i].rgAttribute[j].pszObjId, 5702 got->rgCTLEntry[i].rgAttribute[j].pszObjId); 5703 for (k = 0; k < expected->rgCTLEntry[i].rgAttribute[j].cValue; k++) 5704 { 5705 ok(expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData == 5706 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData, 5707 "%s[%d][%d][%d]: expected value of %d bytes, got %d\n", 5708 header, i, j, k, 5709 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData, 5710 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData); 5711 if (expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData) 5712 ok(!memcmp( 5713 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData, 5714 got->rgCTLEntry[i].rgAttribute[j].rgValue[k].pbData, 5715 expected->rgCTLEntry[i].rgAttribute[j].rgValue[k].cbData), 5716 "%s[%d][%d][%d]: unexpected value\n", 5717 header, i, j, k); 5718 } 5719 } 5720 } 5721 ok(expected->cExtension == got->cExtension, 5722 "%s: expected %d extensions, got %d\n", header, expected->cExtension, 5723 got->cExtension); 5724 for (i = 0; i < expected->cExtension; i++) 5725 { 5726 ok(!strcmp(expected->rgExtension[i].pszObjId, 5727 got->rgExtension[i].pszObjId), "%s[%d]: expected %s, got %s\n", 5728 header, i, expected->rgExtension[i].pszObjId, 5729 got->rgExtension[i].pszObjId); 5730 ok(expected->rgExtension[i].fCritical == got->rgExtension[i].fCritical, 5731 "%s[%d]: expected fCritical = %d, got %d\n", header, i, 5732 expected->rgExtension[i].fCritical, got->rgExtension[i].fCritical); 5733 ok(expected->rgExtension[i].Value.cbData == 5734 got->rgExtension[i].Value.cbData, 5735 "%s[%d]: expected extension value to have %d bytes, got %d\n", 5736 header, i, expected->rgExtension[i].Value.cbData, 5737 got->rgExtension[i].Value.cbData); 5738 if (expected->rgExtension[i].Value.cbData) 5739 ok(!memcmp(expected->rgExtension[i].Value.pbData, 5740 got->rgExtension[i].Value.pbData, 5741 expected->rgExtension[i].Value.cbData), 5742 "%s[%d]: unexpected extension value\n", header, i); 5743 } 5744 } 5745 5746 static const BYTE signedCTL[] = { 5747 0x30,0x81,0xc7,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0, 5748 0x81,0xb9,0x30,0x81,0xb6,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a, 5749 0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x28,0x06,0x09,0x2a,0x86, 5750 0x48,0x86,0xf7,0x0d,0x01,0x07,0x01,0xa0,0x1b,0x04,0x19,0x30,0x17,0x30,0x00, 5751 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30, 5752 0x30,0x5a,0x30,0x02,0x06,0x00,0x31,0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a, 5753 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75, 5754 0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08, 5755 0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05, 5756 0x00,0x04,0x40,0xca,0xd8,0x32,0xd1,0xbd,0x97,0x61,0x54,0xd6,0x80,0xcf,0x0d, 5757 0xbd,0xa2,0x42,0xc7,0xca,0x37,0x91,0x7d,0x9d,0xac,0x8c,0xdf,0x05,0x8a,0x39, 5758 0xc6,0x07,0xc1,0x37,0xe6,0xb9,0xd1,0x0d,0x26,0xec,0xa5,0xb0,0x8a,0x51,0x26, 5759 0x2b,0x4f,0x73,0x44,0x86,0x83,0x5e,0x2b,0x6e,0xcc,0xf8,0x1b,0x85,0x53,0xe9, 5760 0x7a,0x80,0x8f,0x6b,0x42,0x19,0x93 }; 5761 static const BYTE signedCTLWithCTLInnerContent[] = { 5762 0x30,0x82,0x01,0x0f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02, 5763 0xa0,0x82,0x01,0x00,0x30,0x81,0xfd,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06, 5764 0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x30,0x06,0x09, 5765 0x2b,0x06,0x01,0x04,0x01,0x82,0x37,0x0a,0x01,0xa0,0x23,0x30,0x21,0x30,0x00, 5766 0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30,0x30,0x30,0x30,0x30, 5767 0x30,0x5a,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02,0x05,0x05, 5768 0x00,0x31,0x81,0xb5,0x30,0x81,0xb2,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31, 5769 0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20, 5770 0x4c,0x61,0x6e,0x67,0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48, 5771 0x86,0xf7,0x0d,0x02,0x05,0x05,0x00,0xa0,0x3b,0x30,0x18,0x06,0x09,0x2a,0x86, 5772 0x48,0x86,0xf7,0x0d,0x01,0x09,0x03,0x31,0x0b,0x06,0x09,0x2b,0x06,0x01,0x04, 5773 0x01,0x82,0x37,0x0a,0x01,0x30,0x1f,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d, 5774 0x01,0x09,0x04,0x31,0x12,0x04,0x10,0x54,0x71,0xbc,0xe1,0x56,0x31,0xa2,0xf9, 5775 0x65,0x70,0x34,0xf8,0xe2,0xe9,0xb4,0xf4,0x30,0x04,0x06,0x00,0x05,0x00,0x04, 5776 0x40,0x2f,0x1b,0x9f,0x5a,0x4a,0x15,0x73,0xfa,0xb1,0x93,0x3d,0x09,0x52,0xdf, 5777 0x6b,0x98,0x4b,0x13,0x5e,0xe7,0xbf,0x65,0xf4,0x9c,0xc2,0xb1,0x77,0x09,0xb1, 5778 0x66,0x4d,0x72,0x0d,0xb1,0x1a,0x50,0x20,0xe0,0x57,0xa2,0x39,0xc7,0xcd,0x7f, 5779 0x8e,0xe7,0x5f,0x76,0x2b,0xd1,0x6a,0x82,0xb3,0x30,0x25,0x61,0xf6,0x25,0x23, 5780 0x57,0x6c,0x0b,0x47,0xb8 }; 5781 5782 static void test_decodeCTL(DWORD dwEncoding) 5783 { 5784 static char oid1[] = "1.2.3"; 5785 static char oid2[] = "1.5.6"; 5786 static BYTE nullData[] = { 5,0 }; 5787 char *pOid1 = oid1; 5788 BOOL ret; 5789 BYTE *buf = NULL; 5790 DWORD size = 0; 5791 CTL_INFO info; 5792 SYSTEMTIME thisUpdate = { 2005, 6, 1, 6, 16, 10, 0, 0 }; 5793 CTL_ENTRY ctlEntry[2]; 5794 CRYPT_ATTRIBUTE attr1, attr2; 5795 CRYPT_ATTR_BLOB value1, value2; 5796 5797 memset(&info, 0, sizeof(info)); 5798 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTL, sizeof(emptyCTL), 5799 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5800 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5801 if (ret) 5802 { 5803 compareCTLInfo("empty CTL", &info, (CTL_INFO *)buf); 5804 LocalFree(buf); 5805 buf = NULL; 5806 } 5807 info.dwVersion = 1; 5808 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, emptyCTLWithVersion1, 5809 sizeof(emptyCTLWithVersion1), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, 5810 &size); 5811 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5812 if (ret) 5813 { 5814 compareCTLInfo("v1 CTL", &info, (CTL_INFO *)buf); 5815 LocalFree(buf); 5816 buf = NULL; 5817 } 5818 info.dwVersion = 0; 5819 info.SubjectUsage.cUsageIdentifier = 1; 5820 info.SubjectUsage.rgpszUsageIdentifier = &pOid1; 5821 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithUsageIdentifier, 5822 sizeof(ctlWithUsageIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, 5823 &buf, &size); 5824 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5825 if (ret) 5826 { 5827 compareCTLInfo("CTL with usage identifier", &info, (CTL_INFO *)buf); 5828 LocalFree(buf); 5829 buf = NULL; 5830 } 5831 info.SubjectUsage.cUsageIdentifier = 0; 5832 info.ListIdentifier.cbData = sizeof(serialNum); 5833 info.ListIdentifier.pbData = (LPBYTE)serialNum; 5834 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithListIdentifier, 5835 sizeof(ctlWithListIdentifier), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5836 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5837 if (ret) 5838 { 5839 compareCTLInfo("CTL with list identifier", &info, (CTL_INFO *)buf); 5840 LocalFree(buf); 5841 buf = NULL; 5842 } 5843 info.ListIdentifier.cbData = 0; 5844 info.SequenceNumber.cbData = sizeof(serialNum); 5845 info.SequenceNumber.pbData = (LPBYTE)serialNum; 5846 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithSequenceNumber, 5847 sizeof(ctlWithSequenceNumber), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5848 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5849 if (ret) 5850 { 5851 compareCTLInfo("CTL with sequence number", &info, (CTL_INFO *)buf); 5852 LocalFree(buf); 5853 buf = NULL; 5854 } 5855 info.SequenceNumber.cbData = 0; 5856 SystemTimeToFileTime(&thisUpdate, &info.ThisUpdate); 5857 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisUpdate, 5858 sizeof(ctlWithThisUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5859 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5860 if (ret) 5861 { 5862 compareCTLInfo("CTL with this update", &info, (CTL_INFO *)buf); 5863 LocalFree(buf); 5864 buf = NULL; 5865 } 5866 SystemTimeToFileTime(&thisUpdate, &info.NextUpdate); 5867 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithThisAndNextUpdate, 5868 sizeof(ctlWithThisAndNextUpdate), CRYPT_DECODE_ALLOC_FLAG, NULL, 5869 &buf, &size); 5870 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5871 if (ret) 5872 { 5873 compareCTLInfo("CTL with this and next update", &info, (CTL_INFO *)buf); 5874 LocalFree(buf); 5875 buf = NULL; 5876 } 5877 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0; 5878 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0; 5879 info.SubjectAlgorithm.pszObjId = oid2; 5880 info.SubjectAlgorithm.Parameters.cbData = sizeof(nullData); 5881 info.SubjectAlgorithm.Parameters.pbData = nullData; 5882 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithAlgId, 5883 sizeof(ctlWithAlgId), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5884 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5885 if (ret) 5886 { 5887 compareCTLInfo("CTL with algorithm identifier", &info, (CTL_INFO *)buf); 5888 LocalFree(buf); 5889 buf = NULL; 5890 } 5891 SetLastError(0xdeadbeef); 5892 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithBogusEntry, 5893 sizeof(ctlWithBogusEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5894 ok(!ret && 5895 (GetLastError() == CRYPT_E_ASN1_EOD || 5896 GetLastError() == CRYPT_E_ASN1_CORRUPT || 5897 GetLastError() == OSS_MORE_INPUT), /* Win9x */ 5898 "expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %08x\n", 5899 GetLastError()); 5900 info.SubjectAlgorithm.Parameters.cbData = 0; 5901 info.ThisUpdate.dwLowDateTime = info.ThisUpdate.dwHighDateTime = 0; 5902 info.NextUpdate.dwLowDateTime = info.NextUpdate.dwHighDateTime = 0; 5903 info.SubjectAlgorithm.pszObjId = NULL; 5904 value1.cbData = sizeof(emptySequence); 5905 value1.pbData = (LPBYTE)emptySequence; 5906 attr1.pszObjId = oid1; 5907 attr1.cValue = 1; 5908 attr1.rgValue = &value1; 5909 ctlEntry[0].SubjectIdentifier.cbData = sizeof(serialNum); 5910 ctlEntry[0].SubjectIdentifier.pbData = (LPBYTE)serialNum; 5911 ctlEntry[0].cAttribute = 1; 5912 ctlEntry[0].rgAttribute = &attr1; 5913 info.cCTLEntry = 1; 5914 info.rgCTLEntry = ctlEntry; 5915 SetLastError(0xdeadbeef); 5916 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithOneEntry, 5917 sizeof(ctlWithOneEntry), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5918 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5919 if (ret) 5920 { 5921 compareCTLInfo("CTL with one entry", &info, (CTL_INFO *)buf); 5922 LocalFree(buf); 5923 buf = NULL; 5924 } 5925 value2.cbData = sizeof(encodedIPAddr); 5926 value2.pbData = (LPBYTE)encodedIPAddr; 5927 attr2.pszObjId = oid2; 5928 attr2.cValue = 1; 5929 attr2.rgValue = &value2; 5930 ctlEntry[1].SubjectIdentifier.cbData = sizeof(serialNum); 5931 ctlEntry[1].SubjectIdentifier.pbData = (LPBYTE)serialNum; 5932 ctlEntry[1].cAttribute = 1; 5933 ctlEntry[1].rgAttribute = &attr2; 5934 info.cCTLEntry = 2; 5935 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, ctlWithTwoEntries, 5936 sizeof(ctlWithTwoEntries), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5937 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 5938 if (ret) 5939 { 5940 compareCTLInfo("CTL with two entries", &info, (CTL_INFO *)buf); 5941 LocalFree(buf); 5942 buf = NULL; 5943 } 5944 /* A signed CTL isn't decodable, even if the inner content is a CTL */ 5945 SetLastError(0xdeadbeef); 5946 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, signedCTL, 5947 sizeof(signedCTL), CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5948 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || 5949 GetLastError() == OSS_DATA_ERROR /* Win9x */), 5950 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n", 5951 GetLastError()); 5952 SetLastError(0xdeadbeef); 5953 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CTL, 5954 signedCTLWithCTLInnerContent, sizeof(signedCTLWithCTLInnerContent), 5955 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 5956 ok(!ret && (GetLastError() == CRYPT_E_ASN1_BADTAG || 5957 GetLastError() == OSS_DATA_ERROR /* Win9x */), 5958 "expected CRYPT_E_ASN1_BADTAG or OSS_DATA_ERROR, got %08x\n", 5959 GetLastError()); 5960 } 5961 5962 static const BYTE emptyPKCSContentInfo[] = { 0x30,0x04,0x06,0x02,0x2a,0x03 }; 5963 static const BYTE emptyPKCSContentInfoExtraBytes[] = { 0x30,0x04,0x06,0x02,0x2a, 5964 0x03,0,0,0,0,0,0 }; 5965 static const BYTE bogusPKCSContentInfo[] = { 0x30,0x07,0x06,0x02,0x2a,0x03, 5966 0xa0,0x01,0x01 }; 5967 static const BYTE intPKCSContentInfo[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0xa0, 5968 0x03,0x02,0x01,0x01 }; 5969 static BYTE bogusDER[] = { 1 }; 5970 5971 static void test_encodePKCSContentInfo(DWORD dwEncoding) 5972 { 5973 BOOL ret; 5974 BYTE *buf = NULL; 5975 DWORD size = 0; 5976 CRYPT_CONTENT_INFO info = { 0 }; 5977 char oid1[] = "1.2.3"; 5978 5979 if (0) 5980 { 5981 /* Crashes on win9x */ 5982 SetLastError(0xdeadbeef); 5983 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, NULL, 5984 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5985 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 5986 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError()); 5987 } 5988 SetLastError(0xdeadbeef); 5989 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info, 5990 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5991 ok(!ret && (GetLastError() == E_INVALIDARG || 5992 GetLastError() == OSS_LIMITED /* Win9x */), 5993 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError()); 5994 info.pszObjId = oid1; 5995 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info, 5996 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 5997 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 5998 if (ret) 5999 { 6000 ok(size == sizeof(emptyPKCSContentInfo), "Unexpected size %d\n", size); 6001 ok(!memcmp(buf, emptyPKCSContentInfo, size), "Unexpected value\n"); 6002 LocalFree(buf); 6003 } 6004 info.Content.pbData = bogusDER; 6005 info.Content.cbData = sizeof(bogusDER); 6006 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info, 6007 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6008 ok(ret, "CryptEncodeObjectEx failed; %x\n", GetLastError()); 6009 if (ret) 6010 { 6011 ok(size == sizeof(bogusPKCSContentInfo), "Unexpected size %d\n", size); 6012 ok(!memcmp(buf, bogusPKCSContentInfo, size), "Unexpected value\n"); 6013 LocalFree(buf); 6014 } 6015 info.Content.pbData = (BYTE *)ints[0].encoded; 6016 info.Content.cbData = ints[0].encoded[1] + 2; 6017 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, &info, 6018 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6019 if (ret) 6020 { 6021 ok(size == sizeof(intPKCSContentInfo), "Unexpected size %d\n", size); 6022 ok(!memcmp(buf, intPKCSContentInfo, size), "Unexpected value\n"); 6023 LocalFree(buf); 6024 } 6025 } 6026 6027 static const BYTE indefiniteSignedPKCSContent[] = { 6028 0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x07,0x02,0xa0,0x80, 6029 0x30,0x80,0x02,0x01,0x01,0x31,0x0e,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86, 6030 0xf7,0x0d,0x02,0x05,0x05,0x00,0x30,0x80,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7, 6031 0x0d,0x01,0x07,0x01,0xa0,0x80,0x24,0x80,0x04,0x04,0x01,0x02,0x03,0x04,0x04, 6032 0x04,0x01,0x02,0x03,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0xa0,0x81,0xd2,0x30, 6033 0x81,0xcf,0x02,0x01,0x01,0x30,0x02,0x06,0x00,0x30,0x15,0x31,0x13,0x30,0x11, 6034 0x06,0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, 6035 0x67,0x00,0x30,0x22,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30,0x31,0x30, 6036 0x30,0x30,0x30,0x30,0x30,0x5a,0x18,0x0f,0x31,0x36,0x30,0x31,0x30,0x31,0x30, 6037 0x31,0x30,0x30,0x30,0x30,0x30,0x30,0x5a,0x30,0x15,0x31,0x13,0x30,0x11,0x06, 6038 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67, 6039 0x00,0x30,0x5c,0x30,0x0d,0x06,0x09,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x01,0x01, 6040 0x01,0x05,0x00,0x03,0x4b,0x00,0x30,0x48,0x02,0x41,0x00,0xe2,0x54,0x3a,0xa7, 6041 0x83,0xb1,0x27,0x14,0x3e,0x59,0xbb,0xb4,0x53,0xe6,0x1f,0xe7,0x5d,0xf1,0x21, 6042 0x68,0xad,0x85,0x53,0xdb,0x6b,0x1e,0xeb,0x65,0x97,0x03,0x86,0x60,0xde,0xf3, 6043 0x6c,0x38,0x75,0xe0,0x4c,0x61,0xbb,0xbc,0x62,0x17,0xa9,0xcd,0x79,0x3f,0x21, 6044 0x4e,0x96,0xcb,0x0e,0xdc,0x61,0x94,0x30,0x18,0x10,0x6b,0xd0,0x1c,0x10,0x79, 6045 0x02,0x03,0x01,0x00,0x01,0xa3,0x16,0x30,0x14,0x30,0x12,0x06,0x03,0x55,0x1d, 6046 0x13,0x01,0x01,0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01,0x31, 6047 0x77,0x30,0x75,0x02,0x01,0x01,0x30,0x1a,0x30,0x15,0x31,0x13,0x30,0x11,0x06, 6048 0x03,0x55,0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67, 6049 0x00,0x02,0x01,0x01,0x30,0x0c,0x06,0x08,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x02, 6050 0x05,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x40,0x57,0xba,0xe0,0xad, 6051 0xfe,0x36,0x8d,0xb3,0x88,0xa2,0x8d,0x84,0x82,0x52,0x09,0x09,0xd9,0xf0,0xb8, 6052 0x04,0xfa,0xb5,0x51,0x0b,0x2b,0x2e,0xd5,0x72,0x3e,0x3d,0x13,0x8a,0x51,0xc3, 6053 0x71,0x65,0x9a,0x52,0xf2,0x8f,0xb2,0x5b,0x39,0x28,0xb3,0x29,0x36,0xa5,0x8d, 6054 0xe3,0x55,0x71,0x91,0xf9,0x2a,0xd1,0xb8,0xaa,0x52,0xb8,0x22,0x3a,0xeb,0x61, 6055 0x00,0x00,0x00,0x00,0x00,0x00 }; 6056 6057 static const BYTE content_abcd[] = { 6058 ASN_SEQUENCE, 0x80, 6059 ASN_OBJECTIDENTIFIER, 2, 42,3, 6060 ASN_CONTEXT|ASN_CONSTRUCTOR, 0x80, 6061 ASN_OCTETSTRING, 4, 'a','b','c','d', 6062 0,0, 6063 0,0, 6064 }; 6065 6066 static const BYTE encoded_abcd[] = { 6067 ASN_OCTETSTRING, 4, 'a','b','c','d', 6068 }; 6069 6070 static const BYTE content_constructed_abcd[] = { 6071 ASN_SEQUENCE, 0x80, 6072 ASN_OBJECTIDENTIFIER, 2, 42,3, 6073 ASN_CONTEXT|ASN_CONSTRUCTOR, 0x80, 6074 ASN_CONSTRUCTOR|ASN_OCTETSTRING,0x80, 6075 ASN_OCTETSTRING, 4, 'a','b','0','0', 6076 0,0, 6077 0,0, 6078 0,0, 6079 1,2,3,4,5,6,7 /* extra garbage */ 6080 }; 6081 6082 static void test_decodePKCSContentInfo(DWORD dwEncoding) 6083 { 6084 BOOL ret; 6085 LPBYTE buf = NULL; 6086 DWORD size = 0, i; 6087 CRYPT_CONTENT_INFO *info; 6088 6089 const struct { 6090 const BYTE *encoded; 6091 UINT encoded_size; 6092 const char *obj_id; 6093 const BYTE *content; 6094 UINT content_size; 6095 } tests[] = { 6096 { emptyPKCSContentInfo, sizeof(emptyPKCSContentInfo), 6097 "1.2.3", NULL, 0 }, 6098 { emptyPKCSContentInfoExtraBytes, sizeof(emptyPKCSContentInfoExtraBytes), 6099 "1.2.3", NULL, 0 }, 6100 { intPKCSContentInfo, sizeof(intPKCSContentInfo), 6101 "1.2.3", ints[0].encoded, ints[0].encoded[1] + 2 }, 6102 { indefiniteSignedPKCSContent, sizeof(indefiniteSignedPKCSContent), 6103 "1.2.840.113549.1.7.2", NULL, 392 }, 6104 { content_abcd, sizeof(content_abcd), 6105 "1.2.3", encoded_abcd, 6 }, 6106 { content_constructed_abcd, sizeof(content_constructed_abcd), 6107 "1.2.3", content_constructed_abcd + 8, 10 } 6108 }; 6109 6110 for (i = 0; i < ARRAY_SIZE(tests); i++) 6111 { 6112 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, tests[i].encoded, 6113 tests[i].encoded_size, CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6114 ok(ret, "[%u] CryptDecodeObjectEx failed: %x\n", i, GetLastError()); 6115 if (!ret) continue; 6116 6117 info = (CRYPT_CONTENT_INFO *)buf; 6118 6119 ok(!strcmp(info->pszObjId, tests[i].obj_id), "[%u] Expected %s, got %s\n", 6120 i, tests[i].obj_id, info->pszObjId); 6121 ok(info->Content.cbData == tests[i].content_size, 6122 "[%u] Unexpected size %d expected %d\n", i, info->Content.cbData, 6123 tests[i].content_size); 6124 if (tests[i].content) 6125 ok(!memcmp(info->Content.pbData, tests[i].content, tests[i].content_size), 6126 "[%u] Unexpected value\n", i); 6127 LocalFree(buf); 6128 } 6129 6130 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_CONTENT_INFO, 6131 bogusPKCSContentInfo, sizeof(bogusPKCSContentInfo), 6132 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6133 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as 6134 * I doubt an app depends on that. 6135 */ 6136 ok((!ret && (GetLastError() == CRYPT_E_ASN1_EOD || 6137 GetLastError() == CRYPT_E_ASN1_CORRUPT)) || broken(ret), 6138 "Expected CRYPT_E_ASN1_EOD or CRYPT_E_ASN1_CORRUPT, got %x\n", 6139 GetLastError()); 6140 } 6141 6142 static const BYTE emptyPKCSAttr[] = { 0x30,0x06,0x06,0x02,0x2a,0x03,0x31, 6143 0x00 }; 6144 static const BYTE bogusPKCSAttr[] = { 0x30,0x07,0x06,0x02,0x2a,0x03,0x31,0x01, 6145 0x01 }; 6146 static const BYTE intPKCSAttr[] = { 0x30,0x09,0x06,0x02,0x2a,0x03,0x31,0x03, 6147 0x02,0x01,0x01 }; 6148 6149 static void test_encodePKCSAttribute(DWORD dwEncoding) 6150 { 6151 CRYPT_ATTRIBUTE attr = { 0 }; 6152 BOOL ret; 6153 LPBYTE buf = NULL; 6154 DWORD size = 0; 6155 CRYPT_ATTR_BLOB blob; 6156 char oid[] = "1.2.3"; 6157 6158 if (0) 6159 { 6160 /* Crashes on win9x */ 6161 SetLastError(0xdeadbeef); 6162 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, NULL, 6163 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6164 ok(!ret && GetLastError() == STATUS_ACCESS_VIOLATION, 6165 "Expected STATUS_ACCESS_VIOLATION, got %x\n", GetLastError()); 6166 } 6167 SetLastError(0xdeadbeef); 6168 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr, 6169 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6170 ok(!ret && (GetLastError() == E_INVALIDARG || 6171 GetLastError() == OSS_LIMITED /* Win9x */), 6172 "Expected E_INVALIDARG or OSS_LIMITED, got %x\n", GetLastError()); 6173 attr.pszObjId = oid; 6174 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr, 6175 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6176 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6177 if (ret) 6178 { 6179 ok(size == sizeof(emptyPKCSAttr), "Unexpected size %d\n", size); 6180 ok(!memcmp(buf, emptyPKCSAttr, size), "Unexpected value\n"); 6181 LocalFree(buf); 6182 } 6183 blob.cbData = sizeof(bogusDER); 6184 blob.pbData = bogusDER; 6185 attr.cValue = 1; 6186 attr.rgValue = &blob; 6187 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr, 6188 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6189 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6190 if (ret) 6191 { 6192 ok(size == sizeof(bogusPKCSAttr), "Unexpected size %d\n", size); 6193 ok(!memcmp(buf, bogusPKCSAttr, size), "Unexpected value\n"); 6194 LocalFree(buf); 6195 } 6196 blob.pbData = (BYTE *)ints[0].encoded; 6197 blob.cbData = ints[0].encoded[1] + 2; 6198 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, &attr, 6199 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6200 if (ret) 6201 { 6202 ok(size == sizeof(intPKCSAttr), "Unexpected size %d\n", size); 6203 ok(!memcmp(buf, intPKCSAttr, size), "Unexpected value\n"); 6204 LocalFree(buf); 6205 } 6206 } 6207 6208 static void test_decodePKCSAttribute(DWORD dwEncoding) 6209 { 6210 BOOL ret; 6211 LPBYTE buf = NULL; 6212 DWORD size = 0; 6213 CRYPT_ATTRIBUTE *attr; 6214 6215 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, 6216 emptyPKCSAttr, sizeof(emptyPKCSAttr), 6217 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6218 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 6219 if (ret) 6220 { 6221 attr = (CRYPT_ATTRIBUTE *)buf; 6222 6223 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n", 6224 attr->pszObjId); 6225 ok(attr->cValue == 0, "Expected no value, got %d\n", attr->cValue); 6226 LocalFree(buf); 6227 } 6228 SetLastError(0xdeadbeef); 6229 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, 6230 bogusPKCSAttr, sizeof(bogusPKCSAttr), 6231 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6232 /* Native fails with CRYPT_E_ASN1_EOD, accept also CRYPT_E_ASN1_CORRUPT as 6233 * I doubt an app depends on that. 6234 */ 6235 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD || 6236 GetLastError() == CRYPT_E_ASN1_CORRUPT || 6237 GetLastError() == OSS_MORE_INPUT /* Win9x */), 6238 "Expected CRYPT_E_ASN1_EOD, CRYPT_E_ASN1_CORRUPT, or OSS_MORE_INPUT, got %x\n", 6239 GetLastError()); 6240 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTE, 6241 intPKCSAttr, sizeof(intPKCSAttr), 6242 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6243 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 6244 if (ret) 6245 { 6246 attr = (CRYPT_ATTRIBUTE *)buf; 6247 6248 ok(!strcmp(attr->pszObjId, "1.2.3"), "Expected 1.2.3, got %s\n", 6249 attr->pszObjId); 6250 ok(attr->cValue == 1, "Expected 1 value, got %d\n", attr->cValue); 6251 ok(attr->rgValue[0].cbData == ints[0].encoded[1] + 2, 6252 "Unexpected size %d\n", attr->rgValue[0].cbData); 6253 ok(!memcmp(attr->rgValue[0].pbData, ints[0].encoded, 6254 attr->rgValue[0].cbData), "Unexpected value\n"); 6255 LocalFree(buf); 6256 } 6257 } 6258 6259 static const BYTE emptyPKCSAttributes[] = { 0x31,0x00 }; 6260 static const BYTE singlePKCSAttributes[] = { 0x31,0x08,0x30,0x06,0x06,0x02, 6261 0x2a,0x03,0x31,0x00 }; 6262 static const BYTE doublePKCSAttributes[] = { 0x31,0x13,0x30,0x06,0x06,0x02, 6263 0x2a,0x03,0x31,0x00,0x30,0x09,0x06,0x02,0x2d,0x06,0x31,0x03,0x02,0x01,0x01 }; 6264 6265 static void test_encodePKCSAttributes(DWORD dwEncoding) 6266 { 6267 CRYPT_ATTRIBUTES attributes = { 0 }; 6268 CRYPT_ATTRIBUTE attr[2] = { { 0 } }; 6269 CRYPT_ATTR_BLOB blob; 6270 BOOL ret; 6271 LPBYTE buf = NULL; 6272 DWORD size = 0; 6273 char oid1[] = "1.2.3", oid2[] = "1.5.6"; 6274 6275 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes, 6276 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6277 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6278 if (ret) 6279 { 6280 ok(size == sizeof(emptyPKCSAttributes), "Unexpected size %d\n", size); 6281 ok(!memcmp(buf, emptyPKCSAttributes, size), "Unexpected value\n"); 6282 LocalFree(buf); 6283 } 6284 attributes.cAttr = 1; 6285 attributes.rgAttr = attr; 6286 SetLastError(0xdeadbeef); 6287 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes, 6288 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6289 ok(!ret && (GetLastError() == E_INVALIDARG || 6290 GetLastError() == OSS_LIMITED /* Win9x */), 6291 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError()); 6292 attr[0].pszObjId = oid1; 6293 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes, 6294 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6295 if (ret) 6296 { 6297 ok(size == sizeof(singlePKCSAttributes), "Unexpected size %d\n", size); 6298 ok(!memcmp(buf, singlePKCSAttributes, size), "Unexpected value\n"); 6299 LocalFree(buf); 6300 } 6301 attr[1].pszObjId = oid2; 6302 attr[1].cValue = 1; 6303 attr[1].rgValue = &blob; 6304 blob.pbData = (BYTE *)ints[0].encoded; 6305 blob.cbData = ints[0].encoded[1] + 2; 6306 attributes.cAttr = 2; 6307 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, &attributes, 6308 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6309 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6310 if (ret) 6311 { 6312 ok(size == sizeof(doublePKCSAttributes), "Unexpected size %d\n", size); 6313 ok(!memcmp(buf, doublePKCSAttributes, size), "Unexpected value\n"); 6314 LocalFree(buf); 6315 } 6316 } 6317 6318 static void test_decodePKCSAttributes(DWORD dwEncoding) 6319 { 6320 BOOL ret; 6321 LPBYTE buf = NULL; 6322 DWORD size = 0; 6323 CRYPT_ATTRIBUTES *attributes; 6324 6325 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, 6326 emptyPKCSAttributes, sizeof(emptyPKCSAttributes), 6327 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6328 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 6329 if (ret) 6330 { 6331 attributes = (CRYPT_ATTRIBUTES *)buf; 6332 ok(attributes->cAttr == 0, "Expected no attributes, got %d\n", 6333 attributes->cAttr); 6334 LocalFree(buf); 6335 } 6336 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, 6337 singlePKCSAttributes, sizeof(singlePKCSAttributes), 6338 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6339 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 6340 if (ret) 6341 { 6342 attributes = (CRYPT_ATTRIBUTES *)buf; 6343 ok(attributes->cAttr == 1, "Expected 1 attribute, got %d\n", 6344 attributes->cAttr); 6345 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"), 6346 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId); 6347 ok(attributes->rgAttr[0].cValue == 0, 6348 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue); 6349 LocalFree(buf); 6350 } 6351 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, 6352 doublePKCSAttributes, sizeof(doublePKCSAttributes), 6353 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6354 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 6355 if (ret) 6356 { 6357 attributes = (CRYPT_ATTRIBUTES *)buf; 6358 ok(attributes->cAttr == 2, "Expected 2 attributes, got %d\n", 6359 attributes->cAttr); 6360 ok(!strcmp(attributes->rgAttr[0].pszObjId, "1.2.3"), 6361 "Expected 1.2.3, got %s\n", attributes->rgAttr[0].pszObjId); 6362 ok(attributes->rgAttr[0].cValue == 0, 6363 "Expected no attributes, got %d\n", attributes->rgAttr[0].cValue); 6364 ok(!strcmp(attributes->rgAttr[1].pszObjId, "1.5.6"), 6365 "Expected 1.5.6, got %s\n", attributes->rgAttr[1].pszObjId); 6366 ok(attributes->rgAttr[1].cValue == 1, 6367 "Expected 1 attribute, got %d\n", attributes->rgAttr[1].cValue); 6368 ok(attributes->rgAttr[1].rgValue[0].cbData == ints[0].encoded[1] + 2, 6369 "Unexpected size %d\n", attributes->rgAttr[1].rgValue[0].cbData); 6370 ok(!memcmp(attributes->rgAttr[1].rgValue[0].pbData, ints[0].encoded, 6371 attributes->rgAttr[1].rgValue[0].cbData), "Unexpected value\n"); 6372 LocalFree(buf); 6373 } 6374 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, 6375 doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, NULL, &size); 6376 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 6377 buf = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 6378 if (buf) 6379 { 6380 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_ATTRIBUTES, 6381 doublePKCSAttributes, sizeof(doublePKCSAttributes), 0, NULL, buf, &size); 6382 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 6383 HeapFree(GetProcessHeap(), 0, buf); 6384 } 6385 } 6386 6387 static const BYTE singleCapability[] = { 6388 0x30,0x06,0x30,0x04,0x06,0x02,0x2d,0x06 }; 6389 static const BYTE twoCapabilities[] = { 6390 0x30,0x0c,0x30,0x04,0x06,0x02,0x2d,0x06,0x30,0x04,0x06,0x02,0x2a,0x03 }; 6391 static const BYTE singleCapabilitywithNULL[] = { 6392 0x30,0x08,0x30,0x06,0x06,0x02,0x2d,0x06,0x05,0x00 }; 6393 6394 static void test_encodePKCSSMimeCapabilities(DWORD dwEncoding) 6395 { 6396 static char oid1[] = "1.5.6", oid2[] = "1.2.3"; 6397 BOOL ret; 6398 LPBYTE buf = NULL; 6399 DWORD size = 0; 6400 CRYPT_SMIME_CAPABILITY capability[2]; 6401 CRYPT_SMIME_CAPABILITIES capabilities; 6402 6403 /* An empty capabilities is allowed */ 6404 capabilities.cCapability = 0; 6405 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES, 6406 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6407 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 6408 if (ret) 6409 { 6410 ok(size == sizeof(emptySequence), "unexpected size %d\n", size); 6411 ok(!memcmp(buf, emptySequence, size), "unexpected value\n"); 6412 LocalFree(buf); 6413 } 6414 /* A non-empty capabilities with an empty capability (lacking an OID) is 6415 * not allowed 6416 */ 6417 capability[0].pszObjId = NULL; 6418 capability[0].Parameters.cbData = 0; 6419 capabilities.cCapability = 1; 6420 capabilities.rgCapability = capability; 6421 SetLastError(0xdeadbeef); 6422 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES, 6423 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6424 ok(!ret && (GetLastError() == E_INVALIDARG || 6425 GetLastError() == OSS_LIMITED /* Win9x */), 6426 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError()); 6427 capability[0].pszObjId = oid1; 6428 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES, 6429 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6430 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 6431 if (ret) 6432 { 6433 ok(size == sizeof(singleCapability), "unexpected size %d\n", size); 6434 ok(!memcmp(buf, singleCapability, size), "unexpected value\n"); 6435 LocalFree(buf); 6436 } 6437 capability[1].pszObjId = oid2; 6438 capability[1].Parameters.cbData = 0; 6439 capabilities.cCapability = 2; 6440 ret = pCryptEncodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES, 6441 &capabilities, CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6442 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 6443 if (ret) 6444 { 6445 ok(size == sizeof(twoCapabilities), "unexpected size %d\n", size); 6446 ok(!memcmp(buf, twoCapabilities, size), "unexpected value\n"); 6447 LocalFree(buf); 6448 } 6449 } 6450 6451 static void compareSMimeCapabilities(LPCSTR header, 6452 const CRYPT_SMIME_CAPABILITIES *expected, const CRYPT_SMIME_CAPABILITIES *got) 6453 { 6454 DWORD i; 6455 6456 ok(got->cCapability == expected->cCapability, 6457 "%s: expected %d capabilities, got %d\n", header, expected->cCapability, 6458 got->cCapability); 6459 for (i = 0; i < expected->cCapability; i++) 6460 { 6461 ok(!strcmp(expected->rgCapability[i].pszObjId, 6462 got->rgCapability[i].pszObjId), "%s[%d]: expected %s, got %s\n", 6463 header, i, expected->rgCapability[i].pszObjId, 6464 got->rgCapability[i].pszObjId); 6465 ok(expected->rgCapability[i].Parameters.cbData == 6466 got->rgCapability[i].Parameters.cbData, 6467 "%s[%d]: expected %d bytes, got %d\n", header, i, 6468 expected->rgCapability[i].Parameters.cbData, 6469 got->rgCapability[i].Parameters.cbData); 6470 if (expected->rgCapability[i].Parameters.cbData) 6471 ok(!memcmp(expected->rgCapability[i].Parameters.pbData, 6472 got->rgCapability[i].Parameters.pbData, 6473 expected->rgCapability[i].Parameters.cbData), 6474 "%s[%d]: unexpected value\n", header, i); 6475 } 6476 } 6477 6478 static void test_decodePKCSSMimeCapabilities(DWORD dwEncoding) 6479 { 6480 static char oid1[] = "1.5.6", oid2[] = "1.2.3"; 6481 BOOL ret; 6482 DWORD size = 0; 6483 CRYPT_SMIME_CAPABILITY capability[2]; 6484 CRYPT_SMIME_CAPABILITIES capabilities, *ptr; 6485 6486 SetLastError(0xdeadbeef); 6487 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES, 6488 emptySequence, sizeof(emptySequence), 6489 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size); 6490 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 6491 if (ret) 6492 { 6493 capabilities.cCapability = 0; 6494 compareSMimeCapabilities("empty capabilities", &capabilities, ptr); 6495 LocalFree(ptr); 6496 } 6497 SetLastError(0xdeadbeef); 6498 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES, 6499 singleCapability, sizeof(singleCapability), CRYPT_DECODE_ALLOC_FLAG, NULL, 6500 &ptr, &size); 6501 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 6502 if (ret) 6503 { 6504 capability[0].pszObjId = oid1; 6505 capability[0].Parameters.cbData = 0; 6506 capabilities.cCapability = 1; 6507 capabilities.rgCapability = capability; 6508 compareSMimeCapabilities("single capability", &capabilities, ptr); 6509 LocalFree(ptr); 6510 } 6511 SetLastError(0xdeadbeef); 6512 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES, 6513 singleCapabilitywithNULL, sizeof(singleCapabilitywithNULL), 6514 CRYPT_DECODE_ALLOC_FLAG, NULL, &ptr, &size); 6515 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 6516 if (ret) 6517 { 6518 BYTE NULLparam[] = {0x05, 0x00}; 6519 capability[0].pszObjId = oid1; 6520 capability[0].Parameters.cbData = 2; 6521 capability[0].Parameters.pbData = NULLparam; 6522 capabilities.cCapability = 1; 6523 capabilities.rgCapability = capability; 6524 compareSMimeCapabilities("single capability with NULL", &capabilities, 6525 ptr); 6526 LocalFree(ptr); 6527 } 6528 SetLastError(0xdeadbeef); 6529 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES, 6530 twoCapabilities, sizeof(twoCapabilities), CRYPT_DECODE_ALLOC_FLAG, NULL, 6531 &ptr, &size); 6532 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 6533 if (ret) 6534 { 6535 capability[0].Parameters.cbData = 0; 6536 capability[1].pszObjId = oid2; 6537 capability[1].Parameters.cbData = 0; 6538 capabilities.cCapability = 2; 6539 compareSMimeCapabilities("two capabilities", &capabilities, ptr); 6540 LocalFree(ptr); 6541 } 6542 SetLastError(0xdeadbeef); 6543 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES, 6544 twoCapabilities, sizeof(twoCapabilities), 0, NULL, NULL, &size); 6545 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 6546 ptr = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 6547 if (ptr) 6548 { 6549 SetLastError(0xdeadbeef); 6550 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_SMIME_CAPABILITIES, 6551 twoCapabilities, sizeof(twoCapabilities), 0, NULL, ptr, &size); 6552 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 6553 HeapFree(GetProcessHeap(), 0, ptr); 6554 } 6555 } 6556 6557 static BYTE encodedCommonNameNoNull[] = { 0x30,0x14,0x31,0x12,0x30,0x10, 6558 0x06,0x03,0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e, 6559 0x67 }; 6560 static const BYTE minimalPKCSSigner[] = { 6561 0x30,0x2b,0x02,0x01,0x00,0x30,0x18,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03, 6562 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02, 6563 0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04,0x00 }; 6564 static const BYTE PKCSSignerWithSerial[] = { 6565 0x30,0x2c,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03, 6566 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02, 6567 0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30,0x04,0x06,0x00,0x05,0x00,0x04, 6568 0x00 }; 6569 static const BYTE PKCSSignerWithHashAlgo[] = { 6570 0x30,0x2e,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03, 6571 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02, 6572 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x04,0x06,0x00,0x05, 6573 0x00,0x04,0x00 }; 6574 static const BYTE PKCSSignerWithHashAndEncryptionAlgo[] = { 6575 0x30,0x30,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03, 6576 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02, 6577 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d, 6578 0x06,0x05,0x00,0x04,0x00 }; 6579 static const BYTE PKCSSignerWithHash[] = { 6580 0x30,0x40,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03, 6581 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02, 6582 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0x30,0x06,0x06,0x02,0x2d, 6583 0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09, 6584 0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; 6585 static const BYTE PKCSSignerWithAuthAttr[] = { 6586 0x30,0x62,0x02,0x01,0x00,0x30,0x19,0x30,0x14,0x31,0x12,0x30,0x10,0x06,0x03, 6587 0x55,0x04,0x03,0x13,0x09,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x02, 6588 0x01,0x01,0x30,0x06,0x06,0x02,0x2a,0x03,0x05,0x00,0xa0,0x20,0x30,0x1e,0x06, 6589 0x03,0x55,0x04,0x03,0x31,0x17,0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55, 6590 0x04,0x03,0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00,0x30, 6591 0x06,0x06,0x02,0x2d,0x06,0x05,0x00,0x04,0x10,0x00,0x01,0x02,0x03,0x04,0x05, 6592 0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x0f }; 6593 6594 static void test_encodePKCSSignerInfo(DWORD dwEncoding) 6595 { 6596 static char oid1[] = "1.2.3", oid2[] = "1.5.6"; 6597 BOOL ret; 6598 LPBYTE buf = NULL; 6599 DWORD size = 0; 6600 CMSG_SIGNER_INFO info = { 0 }; 6601 char oid_common_name[] = szOID_COMMON_NAME; 6602 CRYPT_ATTR_BLOB commonName = { sizeof(encodedCommonName), 6603 (LPBYTE)encodedCommonName }; 6604 CRYPT_ATTRIBUTE attr = { oid_common_name, 1, &commonName }; 6605 6606 SetLastError(0xdeadbeef); 6607 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, 6608 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6609 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 6610 { 6611 skip("no PKCS7_SIGNER_INFO encode support\n"); 6612 return; 6613 } 6614 ok(!ret && (GetLastError() == E_INVALIDARG || 6615 GetLastError() == OSS_LIMITED /* Win9x */), 6616 "Expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError()); 6617 /* To be encoded, a signer must have an issuer at least, and the encoding 6618 * must include PKCS_7_ASN_ENCODING. (That isn't enough to be decoded, 6619 * see decoding tests.) 6620 */ 6621 info.Issuer.cbData = sizeof(encodedCommonNameNoNull); 6622 info.Issuer.pbData = encodedCommonNameNoNull; 6623 SetLastError(0xdeadbeef); 6624 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, 6625 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6626 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 6627 ok(!ret && GetLastError() == E_INVALIDARG, 6628 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6629 else 6630 { 6631 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */), 6632 "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6633 if (ret) 6634 { 6635 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size); 6636 if (size == sizeof(minimalPKCSSigner)) 6637 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n"); 6638 else 6639 ok(0, "Unexpected value\n"); 6640 LocalFree(buf); 6641 } 6642 } 6643 info.SerialNumber.cbData = sizeof(serialNum); 6644 info.SerialNumber.pbData = (BYTE *)serialNum; 6645 SetLastError(0xdeadbeef); 6646 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, 6647 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6648 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 6649 ok(!ret && GetLastError() == E_INVALIDARG, 6650 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6651 else 6652 { 6653 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */), 6654 "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6655 if (ret) 6656 { 6657 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n", 6658 size); 6659 if (size == sizeof(PKCSSignerWithSerial)) 6660 ok(!memcmp(buf, PKCSSignerWithSerial, size), 6661 "Unexpected value\n"); 6662 else 6663 ok(0, "Unexpected value\n"); 6664 LocalFree(buf); 6665 } 6666 } 6667 info.HashAlgorithm.pszObjId = oid1; 6668 SetLastError(0xdeadbeef); 6669 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, 6670 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6671 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 6672 ok(!ret && GetLastError() == E_INVALIDARG, 6673 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6674 else 6675 { 6676 ok(ret || broken(GetLastError() == OSS_LIMITED /* Win9x */), 6677 "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6678 if (ret) 6679 { 6680 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n", 6681 size); 6682 if (size == sizeof(PKCSSignerWithHashAlgo)) 6683 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size), 6684 "Unexpected value\n"); 6685 else 6686 ok(0, "Unexpected value\n"); 6687 LocalFree(buf); 6688 } 6689 } 6690 info.HashEncryptionAlgorithm.pszObjId = oid2; 6691 SetLastError(0xdeadbeef); 6692 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, 6693 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6694 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 6695 ok(!ret && GetLastError() == E_INVALIDARG, 6696 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6697 else 6698 { 6699 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6700 if (ret) 6701 { 6702 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo), 6703 "Unexpected size %d\n", size); 6704 if (size == sizeof(PKCSSignerWithHashAndEncryptionAlgo)) 6705 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size), 6706 "Unexpected value\n"); 6707 else 6708 ok(0, "Unexpected value\n"); 6709 LocalFree(buf); 6710 } 6711 } 6712 info.EncryptedHash.cbData = sizeof(hash); 6713 info.EncryptedHash.pbData = (BYTE *)hash; 6714 SetLastError(0xdeadbeef); 6715 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, 6716 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6717 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 6718 ok(!ret && GetLastError() == E_INVALIDARG, 6719 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6720 else 6721 { 6722 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6723 if (ret) 6724 { 6725 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n", 6726 size); 6727 if (size == sizeof(PKCSSignerWithHash)) 6728 ok(!memcmp(buf, PKCSSignerWithHash, size), 6729 "Unexpected value\n"); 6730 else 6731 ok(0, "Unexpected value\n"); 6732 LocalFree(buf); 6733 } 6734 } 6735 info.AuthAttrs.cAttr = 1; 6736 info.AuthAttrs.rgAttr = &attr; 6737 SetLastError(0xdeadbeef); 6738 ret = pCryptEncodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, &info, 6739 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6740 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 6741 ok(!ret && GetLastError() == E_INVALIDARG, 6742 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6743 else 6744 { 6745 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6746 if (ret) 6747 { 6748 ok(size == sizeof(PKCSSignerWithAuthAttr), "Unexpected size %d\n", 6749 size); 6750 if (size == sizeof(PKCSSignerWithAuthAttr)) 6751 ok(!memcmp(buf, PKCSSignerWithAuthAttr, size), 6752 "Unexpected value\n"); 6753 else 6754 ok(0, "Unexpected value\n"); 6755 LocalFree(buf); 6756 } 6757 } 6758 } 6759 6760 static void test_decodePKCSSignerInfo(DWORD dwEncoding) 6761 { 6762 BOOL ret; 6763 LPBYTE buf = NULL; 6764 DWORD size = 0; 6765 CMSG_SIGNER_INFO *info; 6766 6767 /* A PKCS signer can't be decoded without a serial number. */ 6768 SetLastError(0xdeadbeef); 6769 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, 6770 minimalPKCSSigner, sizeof(minimalPKCSSigner), 6771 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6772 ok(!ret && (GetLastError() == CRYPT_E_ASN1_CORRUPT || 6773 GetLastError() == OSS_DATA_ERROR /* Win9x */), 6774 "Expected CRYPT_E_ASN1_CORRUPT or OSS_DATA_ERROR, got %x\n", 6775 GetLastError()); 6776 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, 6777 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial), 6778 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6779 ok(ret || broken(GetLastError() == OSS_DATA_ERROR), 6780 "CryptDecodeObjectEx failed: %x\n", GetLastError()); 6781 if (ret) 6782 { 6783 info = (CMSG_SIGNER_INFO *)buf; 6784 ok(info->dwVersion == 0, "Expected version 0, got %d\n", 6785 info->dwVersion); 6786 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull), 6787 "Unexpected size %d\n", info->Issuer.cbData); 6788 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull, 6789 info->Issuer.cbData), "Unexpected value\n"); 6790 ok(info->SerialNumber.cbData == sizeof(serialNum), 6791 "Unexpected size %d\n", info->SerialNumber.cbData); 6792 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)), 6793 "Unexpected value\n"); 6794 LocalFree(buf); 6795 } 6796 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, 6797 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo), 6798 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6799 if (ret) 6800 { 6801 info = (CMSG_SIGNER_INFO *)buf; 6802 ok(info->dwVersion == 0, "Expected version 0, got %d\n", 6803 info->dwVersion); 6804 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull), 6805 "Unexpected size %d\n", info->Issuer.cbData); 6806 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull, 6807 info->Issuer.cbData), "Unexpected value\n"); 6808 ok(info->SerialNumber.cbData == sizeof(serialNum), 6809 "Unexpected size %d\n", info->SerialNumber.cbData); 6810 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)), 6811 "Unexpected value\n"); 6812 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"), 6813 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId); 6814 LocalFree(buf); 6815 } 6816 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, 6817 PKCSSignerWithHashAndEncryptionAlgo, 6818 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG, 6819 NULL, &buf, &size); 6820 if (ret) 6821 { 6822 info = (CMSG_SIGNER_INFO *)buf; 6823 ok(info->dwVersion == 0, "Expected version 0, got %d\n", 6824 info->dwVersion); 6825 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull), 6826 "Unexpected size %d\n", info->Issuer.cbData); 6827 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull, 6828 info->Issuer.cbData), "Unexpected value\n"); 6829 ok(info->SerialNumber.cbData == sizeof(serialNum), 6830 "Unexpected size %d\n", info->SerialNumber.cbData); 6831 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)), 6832 "Unexpected value\n"); 6833 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"), 6834 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId); 6835 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"), 6836 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId); 6837 LocalFree(buf); 6838 } 6839 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, 6840 PKCSSignerWithHash, sizeof(PKCSSignerWithHash), 6841 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6842 if (ret) 6843 { 6844 info = (CMSG_SIGNER_INFO *)buf; 6845 ok(info->dwVersion == 0, "Expected version 0, got %d\n", 6846 info->dwVersion); 6847 ok(info->Issuer.cbData == sizeof(encodedCommonNameNoNull), 6848 "Unexpected size %d\n", info->Issuer.cbData); 6849 ok(!memcmp(info->Issuer.pbData, encodedCommonNameNoNull, 6850 info->Issuer.cbData), "Unexpected value\n"); 6851 ok(info->SerialNumber.cbData == sizeof(serialNum), 6852 "Unexpected size %d\n", info->SerialNumber.cbData); 6853 ok(!memcmp(info->SerialNumber.pbData, serialNum, sizeof(serialNum)), 6854 "Unexpected value\n"); 6855 ok(!strcmp(info->HashAlgorithm.pszObjId, "1.2.3"), 6856 "Expected 1.2.3, got %s\n", info->HashAlgorithm.pszObjId); 6857 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, "1.5.6"), 6858 "Expected 1.5.6, got %s\n", info->HashEncryptionAlgorithm.pszObjId); 6859 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n", 6860 info->EncryptedHash.cbData); 6861 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)), 6862 "Unexpected value\n"); 6863 LocalFree(buf); 6864 } 6865 ret = pCryptDecodeObjectEx(dwEncoding, PKCS7_SIGNER_INFO, 6866 PKCSSignerWithAuthAttr, sizeof(PKCSSignerWithAuthAttr), 6867 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 6868 if (ret) 6869 { 6870 info = (CMSG_SIGNER_INFO *)buf; 6871 ok(info->AuthAttrs.cAttr == 1, "Expected 1 attribute, got %d\n", 6872 info->AuthAttrs.cAttr); 6873 ok(!strcmp(info->AuthAttrs.rgAttr[0].pszObjId, szOID_COMMON_NAME), 6874 "Expected %s, got %s\n", szOID_COMMON_NAME, 6875 info->AuthAttrs.rgAttr[0].pszObjId); 6876 ok(info->AuthAttrs.rgAttr[0].cValue == 1, "Expected 1 value, got %d\n", 6877 info->AuthAttrs.rgAttr[0].cValue); 6878 ok(info->AuthAttrs.rgAttr[0].rgValue[0].cbData == 6879 sizeof(encodedCommonName), "Unexpected size %d\n", 6880 info->AuthAttrs.rgAttr[0].rgValue[0].cbData); 6881 ok(!memcmp(info->AuthAttrs.rgAttr[0].rgValue[0].pbData, 6882 encodedCommonName, sizeof(encodedCommonName)), "Unexpected value\n"); 6883 LocalFree(buf); 6884 } 6885 } 6886 6887 static const BYTE CMSSignerWithKeyId[] = { 6888 0x30,0x14,0x02,0x01,0x00,0x80,0x01,0x01,0x30,0x04,0x06,0x00,0x05,0x00,0x30, 6889 0x04,0x06,0x00,0x05,0x00,0x04,0x00 }; 6890 6891 static void test_encodeCMSSignerInfo(DWORD dwEncoding) 6892 { 6893 BOOL ret; 6894 LPBYTE buf = NULL; 6895 DWORD size = 0; 6896 CMSG_CMS_SIGNER_INFO info = { 0 }; 6897 static char oid1[] = "1.2.3", oid2[] = "1.5.6"; 6898 6899 SetLastError(0xdeadbeef); 6900 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info, 6901 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6902 ok(!ret, "Expected failure, got %d\n", ret); 6903 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 6904 { 6905 skip("no CMS_SIGNER_INFO encode support\n"); 6906 return; 6907 } 6908 ok(GetLastError() == E_INVALIDARG, 6909 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6910 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 6911 SetLastError(0xdeadbeef); 6912 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info, 6913 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6914 ok(!ret, "Expected failure, got %d\n", ret); 6915 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 6916 { 6917 skip("no CMS_SIGNER_INFO encode support\n"); 6918 return; 6919 } 6920 ok(GetLastError() == E_INVALIDARG, 6921 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6922 /* To be encoded, a signer must have a valid cert ID, where a valid ID may 6923 * be a key id or an issuer serial number with at least the issuer set, and 6924 * the encoding must include PKCS_7_ASN_ENCODING. 6925 * (That isn't enough to be decoded, see decoding tests.) 6926 */ 6927 U(info.SignerId).IssuerSerialNumber.Issuer.cbData = 6928 sizeof(encodedCommonNameNoNull); 6929 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull; 6930 SetLastError(0xdeadbeef); 6931 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info, 6932 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6933 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 6934 ok(!ret && GetLastError() == E_INVALIDARG, 6935 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6936 else 6937 { 6938 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6939 if (ret) 6940 { 6941 ok(size == sizeof(minimalPKCSSigner), "Unexpected size %d\n", size); 6942 ok(!memcmp(buf, minimalPKCSSigner, size), "Unexpected value\n"); 6943 LocalFree(buf); 6944 } 6945 } 6946 U(info.SignerId).IssuerSerialNumber.SerialNumber.cbData = sizeof(serialNum); 6947 U(info.SignerId).IssuerSerialNumber.SerialNumber.pbData = (BYTE *)serialNum; 6948 SetLastError(0xdeadbeef); 6949 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info, 6950 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6951 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 6952 ok(!ret && GetLastError() == E_INVALIDARG, 6953 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6954 else 6955 { 6956 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6957 if (ret) 6958 { 6959 ok(size == sizeof(PKCSSignerWithSerial), "Unexpected size %d\n", 6960 size); 6961 ok(!memcmp(buf, PKCSSignerWithSerial, size), "Unexpected value\n"); 6962 LocalFree(buf); 6963 } 6964 } 6965 info.SignerId.dwIdChoice = CERT_ID_KEY_IDENTIFIER; 6966 U(info.SignerId).KeyId.cbData = sizeof(serialNum); 6967 U(info.SignerId).KeyId.pbData = (BYTE *)serialNum; 6968 SetLastError(0xdeadbeef); 6969 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info, 6970 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6971 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 6972 ok(!ret && GetLastError() == E_INVALIDARG, 6973 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6974 else 6975 { 6976 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 6977 if (ret) 6978 { 6979 ok(size == sizeof(CMSSignerWithKeyId), "Unexpected size %d\n", 6980 size); 6981 ok(!memcmp(buf, CMSSignerWithKeyId, size), "Unexpected value\n"); 6982 LocalFree(buf); 6983 } 6984 } 6985 /* While a CERT_ID can have a hash type, that's not allowed in CMS, where 6986 * only the IssuerAndSerialNumber and SubjectKeyIdentifier types are allowed 6987 * (see RFC 3852, section 5.3.) 6988 */ 6989 info.SignerId.dwIdChoice = CERT_ID_SHA1_HASH; 6990 U(info.SignerId).HashId.cbData = sizeof(hash); 6991 U(info.SignerId).HashId.pbData = (BYTE *)hash; 6992 SetLastError(0xdeadbeef); 6993 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info, 6994 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 6995 ok(!ret && GetLastError() == E_INVALIDARG, 6996 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 6997 /* Now with a hash algo */ 6998 info.SignerId.dwIdChoice = CERT_ID_ISSUER_SERIAL_NUMBER; 6999 U(info.SignerId).IssuerSerialNumber.Issuer.cbData = 7000 sizeof(encodedCommonNameNoNull); 7001 U(info.SignerId).IssuerSerialNumber.Issuer.pbData = encodedCommonNameNoNull; 7002 info.HashAlgorithm.pszObjId = oid1; 7003 SetLastError(0xdeadbeef); 7004 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info, 7005 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7006 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 7007 ok(!ret && GetLastError() == E_INVALIDARG, 7008 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 7009 else 7010 { 7011 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 7012 if (ret) 7013 { 7014 ok(size == sizeof(PKCSSignerWithHashAlgo), "Unexpected size %d\n", 7015 size); 7016 ok(!memcmp(buf, PKCSSignerWithHashAlgo, size), 7017 "Unexpected value\n"); 7018 LocalFree(buf); 7019 } 7020 } 7021 info.HashEncryptionAlgorithm.pszObjId = oid2; 7022 SetLastError(0xdeadbeef); 7023 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info, 7024 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7025 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 7026 ok(!ret && GetLastError() == E_INVALIDARG, 7027 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 7028 else 7029 { 7030 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 7031 if (ret) 7032 { 7033 ok(size == sizeof(PKCSSignerWithHashAndEncryptionAlgo), 7034 "Unexpected size %d\n", size); 7035 ok(!memcmp(buf, PKCSSignerWithHashAndEncryptionAlgo, size), 7036 "Unexpected value\n"); 7037 LocalFree(buf); 7038 } 7039 } 7040 info.EncryptedHash.cbData = sizeof(hash); 7041 info.EncryptedHash.pbData = (BYTE *)hash; 7042 SetLastError(0xdeadbeef); 7043 ret = pCryptEncodeObjectEx(dwEncoding, CMS_SIGNER_INFO, &info, 7044 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7045 if (!(dwEncoding & PKCS_7_ASN_ENCODING)) 7046 ok(!ret && GetLastError() == E_INVALIDARG, 7047 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 7048 else 7049 { 7050 ok(ret, "CryptEncodeObjectEx failed: %x\n", GetLastError()); 7051 if (ret) 7052 { 7053 ok(size == sizeof(PKCSSignerWithHash), "Unexpected size %d\n", 7054 size); 7055 ok(!memcmp(buf, PKCSSignerWithHash, size), "Unexpected value\n"); 7056 LocalFree(buf); 7057 } 7058 } 7059 } 7060 7061 static void test_decodeCMSSignerInfo(DWORD dwEncoding) 7062 { 7063 BOOL ret; 7064 LPBYTE buf = NULL; 7065 DWORD size = 0; 7066 CMSG_CMS_SIGNER_INFO *info; 7067 static const char oid1[] = "1.2.3", oid2[] = "1.5.6"; 7068 7069 /* A CMS signer can't be decoded without a serial number. */ 7070 SetLastError(0xdeadbeef); 7071 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO, 7072 minimalPKCSSigner, sizeof(minimalPKCSSigner), 7073 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 7074 ok(!ret, "expected failure\n"); 7075 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 7076 { 7077 skip("no CMS_SIGNER_INFO decode support\n"); 7078 return; 7079 } 7080 ok(GetLastError() == CRYPT_E_ASN1_CORRUPT, 7081 "Expected CRYPT_E_ASN1_CORRUPT, got %x\n", GetLastError()); 7082 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO, 7083 PKCSSignerWithSerial, sizeof(PKCSSignerWithSerial), 7084 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 7085 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 7086 if (ret) 7087 { 7088 info = (CMSG_CMS_SIGNER_INFO *)buf; 7089 ok(info->dwVersion == 0, "Expected version 0, got %d\n", 7090 info->dwVersion); 7091 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER, 7092 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n", 7093 info->SignerId.dwIdChoice); 7094 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData == 7095 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n", 7096 U(info->SignerId).IssuerSerialNumber.Issuer.cbData); 7097 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData, 7098 encodedCommonNameNoNull, 7099 U(info->SignerId).IssuerSerialNumber.Issuer.cbData), 7100 "Unexpected value\n"); 7101 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData == 7102 sizeof(serialNum), "Unexpected size %d\n", 7103 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData); 7104 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData, 7105 serialNum, sizeof(serialNum)), "Unexpected value\n"); 7106 LocalFree(buf); 7107 } 7108 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO, 7109 PKCSSignerWithHashAlgo, sizeof(PKCSSignerWithHashAlgo), 7110 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 7111 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 7112 if (ret) 7113 { 7114 info = (CMSG_CMS_SIGNER_INFO *)buf; 7115 ok(info->dwVersion == 0, "Expected version 0, got %d\n", 7116 info->dwVersion); 7117 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER, 7118 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n", 7119 info->SignerId.dwIdChoice); 7120 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData == 7121 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n", 7122 U(info->SignerId).IssuerSerialNumber.Issuer.cbData); 7123 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData, 7124 encodedCommonNameNoNull, 7125 U(info->SignerId).IssuerSerialNumber.Issuer.cbData), 7126 "Unexpected value\n"); 7127 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData == 7128 sizeof(serialNum), "Unexpected size %d\n", 7129 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData); 7130 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData, 7131 serialNum, sizeof(serialNum)), "Unexpected value\n"); 7132 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1), 7133 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId); 7134 LocalFree(buf); 7135 } 7136 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO, 7137 PKCSSignerWithHashAndEncryptionAlgo, 7138 sizeof(PKCSSignerWithHashAndEncryptionAlgo), CRYPT_DECODE_ALLOC_FLAG, 7139 NULL, &buf, &size); 7140 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 7141 if (ret) 7142 { 7143 info = (CMSG_CMS_SIGNER_INFO *)buf; 7144 ok(info->dwVersion == 0, "Expected version 0, got %d\n", 7145 info->dwVersion); 7146 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER, 7147 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n", 7148 info->SignerId.dwIdChoice); 7149 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData == 7150 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n", 7151 U(info->SignerId).IssuerSerialNumber.Issuer.cbData); 7152 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData, 7153 encodedCommonNameNoNull, 7154 U(info->SignerId).IssuerSerialNumber.Issuer.cbData), 7155 "Unexpected value\n"); 7156 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData == 7157 sizeof(serialNum), "Unexpected size %d\n", 7158 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData); 7159 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData, 7160 serialNum, sizeof(serialNum)), "Unexpected value\n"); 7161 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1), 7162 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId); 7163 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2), 7164 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId); 7165 LocalFree(buf); 7166 } 7167 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO, 7168 PKCSSignerWithHash, sizeof(PKCSSignerWithHash), 7169 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 7170 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 7171 if (ret) 7172 { 7173 info = (CMSG_CMS_SIGNER_INFO *)buf; 7174 ok(info->dwVersion == 0, "Expected version 0, got %d\n", 7175 info->dwVersion); 7176 ok(info->SignerId.dwIdChoice == CERT_ID_ISSUER_SERIAL_NUMBER, 7177 "Expected CERT_ID_ISSUER_SERIAL_NUMBER, got %d\n", 7178 info->SignerId.dwIdChoice); 7179 ok(U(info->SignerId).IssuerSerialNumber.Issuer.cbData == 7180 sizeof(encodedCommonNameNoNull), "Unexpected size %d\n", 7181 U(info->SignerId).IssuerSerialNumber.Issuer.cbData); 7182 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.Issuer.pbData, 7183 encodedCommonNameNoNull, 7184 U(info->SignerId).IssuerSerialNumber.Issuer.cbData), 7185 "Unexpected value\n"); 7186 ok(U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData == 7187 sizeof(serialNum), "Unexpected size %d\n", 7188 U(info->SignerId).IssuerSerialNumber.SerialNumber.cbData); 7189 ok(!memcmp(U(info->SignerId).IssuerSerialNumber.SerialNumber.pbData, 7190 serialNum, sizeof(serialNum)), "Unexpected value\n"); 7191 ok(!strcmp(info->HashAlgorithm.pszObjId, oid1), 7192 "Expected %s, got %s\n", oid1, info->HashAlgorithm.pszObjId); 7193 ok(!strcmp(info->HashEncryptionAlgorithm.pszObjId, oid2), 7194 "Expected %s, got %s\n", oid2, info->HashEncryptionAlgorithm.pszObjId); 7195 ok(info->EncryptedHash.cbData == sizeof(hash), "Unexpected size %d\n", 7196 info->EncryptedHash.cbData); 7197 ok(!memcmp(info->EncryptedHash.pbData, hash, sizeof(hash)), 7198 "Unexpected value\n"); 7199 LocalFree(buf); 7200 } 7201 ret = pCryptDecodeObjectEx(dwEncoding, CMS_SIGNER_INFO, 7202 CMSSignerWithKeyId, sizeof(CMSSignerWithKeyId), 7203 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &size); 7204 ok(ret, "CryptDecodeObjectEx failed: %x\n", GetLastError()); 7205 if (ret) 7206 { 7207 info = (CMSG_CMS_SIGNER_INFO *)buf; 7208 ok(info->dwVersion == 0, "Expected version 0, got %d\n", 7209 info->dwVersion); 7210 ok(info->SignerId.dwIdChoice == CERT_ID_KEY_IDENTIFIER, 7211 "Expected CERT_ID_KEY_IDENTIFIER, got %d\n", 7212 info->SignerId.dwIdChoice); 7213 ok(U(info->SignerId).KeyId.cbData == sizeof(serialNum), 7214 "Unexpected size %d\n", U(info->SignerId).KeyId.cbData); 7215 ok(!memcmp(U(info->SignerId).KeyId.pbData, serialNum, sizeof(serialNum)), 7216 "Unexpected value\n"); 7217 LocalFree(buf); 7218 } 7219 } 7220 7221 static BYTE emptyDNSPermittedConstraints[] = { 7222 0x30,0x06,0xa0,0x04,0x30,0x02,0x82,0x00 }; 7223 static BYTE emptyDNSExcludedConstraints[] = { 7224 0x30,0x06,0xa1,0x04,0x30,0x02,0x82,0x00 }; 7225 static BYTE DNSExcludedConstraints[] = { 7226 0x30,0x17,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f, 7227 0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 }; 7228 static BYTE permittedAndExcludedConstraints[] = { 7229 0x30,0x25,0xa0,0x0c,0x30,0x0a,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00, 7230 0x01,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a,0x2f,0x2f,0x77, 7231 0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 }; 7232 static BYTE permittedAndExcludedWithMinConstraints[] = { 7233 0x30,0x28,0xa0,0x0f,0x30,0x0d,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00, 7234 0x01,0x80,0x01,0x05,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74,0x74,0x70,0x3a, 7235 0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 }; 7236 static BYTE permittedAndExcludedWithMinMaxConstraints[] = { 7237 0x30,0x2b,0xa0,0x12,0x30,0x10,0x87,0x08,0x30,0x06,0x87,0x04,0x7f,0x00,0x00, 7238 0x01,0x80,0x01,0x05,0x81,0x01,0x03,0xa1,0x15,0x30,0x13,0x82,0x11,0x68,0x74, 7239 0x74,0x70,0x3a,0x2f,0x2f,0x77,0x69,0x6e,0x65,0x68,0x71,0x2e,0x6f,0x72,0x67 }; 7240 7241 static void test_encodeNameConstraints(DWORD dwEncoding) 7242 { 7243 BOOL ret; 7244 CERT_NAME_CONSTRAINTS_INFO constraints = { 0 }; 7245 CERT_GENERAL_SUBTREE permitted = { { 0 } }; 7246 CERT_GENERAL_SUBTREE excluded = { { 0 } }; 7247 LPBYTE buf; 7248 DWORD size; 7249 7250 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, 7251 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7252 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 7253 { 7254 skip("no X509_NAME_CONSTRAINTS encode support\n"); 7255 return; 7256 } 7257 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7258 if (ret) 7259 { 7260 ok(size == sizeof(emptySequence), "Unexpected size\n"); 7261 ok(!memcmp(buf, emptySequence, size), "Unexpected value\n"); 7262 LocalFree(buf); 7263 } 7264 constraints.cPermittedSubtree = 1; 7265 constraints.rgPermittedSubtree = &permitted; 7266 SetLastError(0xdeadbeef); 7267 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, 7268 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7269 ok(!ret && GetLastError() == E_INVALIDARG, 7270 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 7271 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME; 7272 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, 7273 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7274 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7275 if (ret) 7276 { 7277 ok(size == sizeof(emptyDNSPermittedConstraints), "Unexpected size\n"); 7278 ok(!memcmp(buf, emptyDNSPermittedConstraints, size), 7279 "Unexpected value\n"); 7280 LocalFree(buf); 7281 } 7282 constraints.cPermittedSubtree = 0; 7283 constraints.cExcludedSubtree = 1; 7284 constraints.rgExcludedSubtree = &excluded; 7285 excluded.Base.dwAltNameChoice = CERT_ALT_NAME_DNS_NAME; 7286 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, 7287 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7288 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7289 if (ret) 7290 { 7291 ok(size == sizeof(emptyDNSExcludedConstraints), "Unexpected size\n"); 7292 ok(!memcmp(buf, emptyDNSExcludedConstraints, size), 7293 "Unexpected value\n"); 7294 LocalFree(buf); 7295 } 7296 U(excluded.Base).pwszURL = (LPWSTR)url; 7297 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, 7298 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7299 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7300 if (ret) 7301 { 7302 ok(size == sizeof(DNSExcludedConstraints), "Unexpected size\n"); 7303 ok(!memcmp(buf, DNSExcludedConstraints, size), 7304 "Unexpected value\n"); 7305 LocalFree(buf); 7306 } 7307 permitted.Base.dwAltNameChoice = CERT_ALT_NAME_IP_ADDRESS; 7308 U(permitted.Base).IPAddress.cbData = sizeof(encodedIPAddr); 7309 U(permitted.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr; 7310 constraints.cPermittedSubtree = 1; 7311 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, 7312 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7313 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7314 if (ret) 7315 { 7316 ok(size == sizeof(permittedAndExcludedConstraints), 7317 "Unexpected size\n"); 7318 ok(!memcmp(buf, permittedAndExcludedConstraints, size), 7319 "Unexpected value\n"); 7320 LocalFree(buf); 7321 } 7322 permitted.dwMinimum = 5; 7323 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, 7324 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7325 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7326 if (ret) 7327 { 7328 ok(size == sizeof(permittedAndExcludedWithMinConstraints), 7329 "Unexpected size\n"); 7330 ok(!memcmp(buf, permittedAndExcludedWithMinConstraints, size), 7331 "Unexpected value\n"); 7332 LocalFree(buf); 7333 } 7334 permitted.fMaximum = TRUE; 7335 permitted.dwMaximum = 3; 7336 SetLastError(0xdeadbeef); 7337 ret = pCryptEncodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, &constraints, 7338 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7339 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7340 if (ret) 7341 { 7342 ok(size == sizeof(permittedAndExcludedWithMinMaxConstraints), 7343 "Unexpected size\n"); 7344 ok(!memcmp(buf, permittedAndExcludedWithMinMaxConstraints, size), 7345 "Unexpected value\n"); 7346 LocalFree(buf); 7347 } 7348 } 7349 7350 struct EncodedNameConstraints 7351 { 7352 CRYPT_DATA_BLOB encoded; 7353 CERT_NAME_CONSTRAINTS_INFO constraints; 7354 }; 7355 7356 static CERT_GENERAL_SUBTREE emptyDNSSubtree = { 7357 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 }; 7358 static CERT_GENERAL_SUBTREE DNSSubtree = { 7359 { CERT_ALT_NAME_DNS_NAME, { 0 } }, 0 }; 7360 static CERT_GENERAL_SUBTREE IPAddressSubtree = { 7361 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 0 }; 7362 static CERT_GENERAL_SUBTREE IPAddressWithMinSubtree = { 7363 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, 0 }; 7364 static CERT_GENERAL_SUBTREE IPAddressWithMinMaxSubtree = { 7365 { CERT_ALT_NAME_IP_ADDRESS, { 0 } }, 5, TRUE, 3 }; 7366 7367 static const struct EncodedNameConstraints encodedNameConstraints[] = { 7368 { { sizeof(emptySequence), (LPBYTE)emptySequence }, { 0 } }, 7369 { { sizeof(emptyDNSPermittedConstraints), emptyDNSPermittedConstraints }, 7370 { 1, &emptyDNSSubtree, 0, NULL } }, 7371 { { sizeof(emptyDNSExcludedConstraints), emptyDNSExcludedConstraints }, 7372 { 0, NULL, 1, &emptyDNSSubtree } }, 7373 { { sizeof(DNSExcludedConstraints), DNSExcludedConstraints }, 7374 { 0, NULL, 1, &DNSSubtree } }, 7375 { { sizeof(permittedAndExcludedConstraints), permittedAndExcludedConstraints }, 7376 { 1, &IPAddressSubtree, 1, &DNSSubtree } }, 7377 { { sizeof(permittedAndExcludedWithMinConstraints), 7378 permittedAndExcludedWithMinConstraints }, 7379 { 1, &IPAddressWithMinSubtree, 1, &DNSSubtree } }, 7380 { { sizeof(permittedAndExcludedWithMinMaxConstraints), 7381 permittedAndExcludedWithMinMaxConstraints }, 7382 { 1, &IPAddressWithMinMaxSubtree, 1, &DNSSubtree } }, 7383 }; 7384 7385 static void test_decodeNameConstraints(DWORD dwEncoding) 7386 { 7387 BOOL ret; 7388 DWORD i; 7389 CERT_NAME_CONSTRAINTS_INFO *constraints; 7390 7391 U(DNSSubtree.Base).pwszURL = (LPWSTR)url; 7392 U(IPAddressSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr); 7393 U(IPAddressSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr; 7394 U(IPAddressWithMinSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr); 7395 U(IPAddressWithMinSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr; 7396 U(IPAddressWithMinMaxSubtree.Base).IPAddress.cbData = sizeof(encodedIPAddr); 7397 U(IPAddressWithMinMaxSubtree.Base).IPAddress.pbData = (LPBYTE)encodedIPAddr; 7398 for (i = 0; i < ARRAY_SIZE(encodedNameConstraints); i++) 7399 { 7400 DWORD size; 7401 7402 ret = pCryptDecodeObjectEx(dwEncoding, X509_NAME_CONSTRAINTS, 7403 encodedNameConstraints[i].encoded.pbData, 7404 encodedNameConstraints[i].encoded.cbData, 7405 CRYPT_DECODE_ALLOC_FLAG, NULL, &constraints, &size); 7406 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 7407 { 7408 skip("no X509_NAME_CONSTRAINTS decode support\n"); 7409 return; 7410 } 7411 ok(ret, "%d: CryptDecodeObjectEx failed: %08x\n", i, GetLastError()); 7412 if (ret) 7413 { 7414 DWORD j; 7415 7416 if (constraints->cPermittedSubtree != 7417 encodedNameConstraints[i].constraints.cPermittedSubtree) 7418 fprintf(stderr, "%d: expected %u permitted, got %u\n", i, 7419 encodedNameConstraints[i].constraints.cPermittedSubtree, 7420 constraints->cPermittedSubtree); 7421 if (constraints->cPermittedSubtree == 7422 encodedNameConstraints[i].constraints.cPermittedSubtree) 7423 { 7424 for (j = 0; j < constraints->cPermittedSubtree; j++) 7425 { 7426 compareAltNameEntry(&constraints->rgPermittedSubtree[j].Base, 7427 &encodedNameConstraints[i].constraints.rgPermittedSubtree[j].Base); 7428 } 7429 } 7430 if (constraints->cExcludedSubtree != 7431 encodedNameConstraints[i].constraints.cExcludedSubtree) 7432 fprintf(stderr, "%d: expected %u excluded, got %u\n", i, 7433 encodedNameConstraints[i].constraints.cExcludedSubtree, 7434 constraints->cExcludedSubtree); 7435 if (constraints->cExcludedSubtree == 7436 encodedNameConstraints[i].constraints.cExcludedSubtree) 7437 { 7438 for (j = 0; j < constraints->cExcludedSubtree; j++) 7439 { 7440 compareAltNameEntry(&constraints->rgExcludedSubtree[j].Base, 7441 &encodedNameConstraints[i].constraints.rgExcludedSubtree[j].Base); 7442 } 7443 } 7444 LocalFree(constraints); 7445 } 7446 } 7447 } 7448 7449 static WCHAR noticeText[] = { 'T','h','i','s',' ','i','s',' ','a',' ', 7450 'n','o','t','i','c','e',0 }; 7451 static const BYTE noticeWithDisplayText[] = { 7452 0x30,0x22,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20,0x00, 7453 0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00,0x74, 7454 0x00,0x69,0x00,0x63,0x00,0x65 7455 }; 7456 static char org[] = "Wine"; 7457 static int noticeNumbers[] = { 2,3 }; 7458 static BYTE noticeWithReference[] = { 7459 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02, 7460 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20, 7461 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00, 7462 0x74,0x00,0x69,0x00,0x63,0x00,0x65 7463 }; 7464 7465 static void test_encodePolicyQualifierUserNotice(DWORD dwEncoding) 7466 { 7467 BOOL ret; 7468 LPBYTE buf; 7469 DWORD size; 7470 CERT_POLICY_QUALIFIER_USER_NOTICE notice; 7471 CERT_POLICY_QUALIFIER_NOTICE_REFERENCE reference; 7472 7473 memset(¬ice, 0, sizeof(notice)); 7474 ret = pCryptEncodeObjectEx(dwEncoding, 7475 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, ¬ice, CRYPT_ENCODE_ALLOC_FLAG, 7476 NULL, &buf, &size); 7477 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 7478 { 7479 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE encode support\n"); 7480 return; 7481 } 7482 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7483 if (ret) 7484 { 7485 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size); 7486 ok(!memcmp(buf, emptySequence, size), "unexpected value\n"); 7487 LocalFree(buf); 7488 } 7489 notice.pszDisplayText = noticeText; 7490 ret = pCryptEncodeObjectEx(dwEncoding, 7491 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, ¬ice, CRYPT_ENCODE_ALLOC_FLAG, 7492 NULL, &buf, &size); 7493 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7494 if (ret) 7495 { 7496 ok(sizeof(noticeWithDisplayText) == size, "unexpected size %d\n", size); 7497 ok(!memcmp(buf, noticeWithDisplayText, size), "unexpected value\n"); 7498 LocalFree(buf); 7499 } 7500 reference.pszOrganization = org; 7501 reference.cNoticeNumbers = 2; 7502 reference.rgNoticeNumbers = noticeNumbers; 7503 notice.pNoticeReference = &reference; 7504 ret = pCryptEncodeObjectEx(dwEncoding, 7505 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, ¬ice, CRYPT_ENCODE_ALLOC_FLAG, 7506 NULL, &buf, &size); 7507 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7508 if (ret) 7509 { 7510 ok(sizeof(noticeWithReference) == size, "unexpected size %d\n", size); 7511 ok(!memcmp(buf, noticeWithReference, size), "unexpected value\n"); 7512 LocalFree(buf); 7513 } 7514 } 7515 7516 static void test_decodePolicyQualifierUserNotice(DWORD dwEncoding) 7517 { 7518 BOOL ret; 7519 CERT_POLICY_QUALIFIER_USER_NOTICE *notice; 7520 DWORD size; 7521 7522 ret = pCryptDecodeObjectEx(dwEncoding, 7523 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, 7524 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL, 7525 ¬ice, &size); 7526 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 7527 { 7528 skip("no X509_PKIX_POLICY_QUALIFIER_USERNOTICE decode support\n"); 7529 return; 7530 } 7531 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7532 if (ret) 7533 { 7534 ok(notice->pszDisplayText == NULL, "unexpected display text\n"); 7535 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n"); 7536 LocalFree(notice); 7537 } 7538 ret = pCryptDecodeObjectEx(dwEncoding, 7539 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, 7540 noticeWithDisplayText, sizeof(noticeWithDisplayText), 7541 CRYPT_DECODE_ALLOC_FLAG, NULL, ¬ice, &size); 7542 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7543 if (ret) 7544 { 7545 ok(!lstrcmpW(notice->pszDisplayText, noticeText), 7546 "unexpected display text\n"); 7547 ok(notice->pNoticeReference == NULL, "unexpected notice reference\n"); 7548 LocalFree(notice); 7549 } 7550 ret = pCryptDecodeObjectEx(dwEncoding, 7551 X509_PKIX_POLICY_QUALIFIER_USERNOTICE, 7552 noticeWithReference, sizeof(noticeWithReference), 7553 CRYPT_DECODE_ALLOC_FLAG, NULL, ¬ice, &size); 7554 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7555 if (ret) 7556 { 7557 ok(!lstrcmpW(notice->pszDisplayText, noticeText), 7558 "unexpected display text\n"); 7559 ok(notice->pNoticeReference != NULL, "expected a notice reference\n"); 7560 if (notice->pNoticeReference) 7561 { 7562 ok(!strcmp(notice->pNoticeReference->pszOrganization, org), 7563 "unexpected organization %s\n", 7564 notice->pNoticeReference->pszOrganization); 7565 ok(notice->pNoticeReference->cNoticeNumbers == 2, 7566 "expected 2 notice numbers, got %d\n", 7567 notice->pNoticeReference->cNoticeNumbers); 7568 ok(notice->pNoticeReference->rgNoticeNumbers[0] == noticeNumbers[0], 7569 "unexpected notice number %d\n", 7570 notice->pNoticeReference->rgNoticeNumbers[0]); 7571 ok(notice->pNoticeReference->rgNoticeNumbers[1] == noticeNumbers[1], 7572 "unexpected notice number %d\n", 7573 notice->pNoticeReference->rgNoticeNumbers[1]); 7574 } 7575 LocalFree(notice); 7576 } 7577 } 7578 7579 static char oid_any_policy[] = "2.5.29.32.0"; 7580 static const BYTE policiesWithAnyPolicy[] = { 7581 0x30,0x08,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00 7582 }; 7583 static char oid1[] = "1.2.3"; 7584 static char oid_user_notice[] = "1.3.6.1.5.5.7.2.2"; 7585 static const BYTE twoPolicies[] = { 7586 0x30,0x50,0x30,0x06,0x06,0x04,0x55,0x1d,0x20,0x00,0x30,0x46,0x06,0x02,0x2a, 7587 0x03,0x30,0x40,0x30,0x3e,0x06,0x08,0x2b,0x06,0x01,0x05,0x05,0x07,0x02,0x02, 7588 0x30,0x32,0x30,0x0e,0x16,0x04,0x57,0x69,0x6e,0x65,0x30,0x06,0x02,0x01,0x02, 7589 0x02,0x01,0x03,0x1e,0x20,0x00,0x54,0x00,0x68,0x00,0x69,0x00,0x73,0x00,0x20, 7590 0x00,0x69,0x00,0x73,0x00,0x20,0x00,0x61,0x00,0x20,0x00,0x6e,0x00,0x6f,0x00, 7591 0x74,0x00,0x69,0x00,0x63,0x00,0x65 7592 }; 7593 7594 static void test_encodeCertPolicies(DWORD dwEncoding) 7595 { 7596 BOOL ret; 7597 CERT_POLICIES_INFO info; 7598 CERT_POLICY_INFO policy[2]; 7599 CERT_POLICY_QUALIFIER_INFO qualifier; 7600 LPBYTE buf; 7601 DWORD size; 7602 7603 memset(&info, 0, sizeof(info)); 7604 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info, 7605 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7606 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7607 if (ret) 7608 { 7609 ok(sizeof(emptySequence) == size, "unexpected size %d\n", size); 7610 ok(!memcmp(buf, emptySequence, size), "unexpected value\n"); 7611 LocalFree(buf); 7612 } 7613 memset(policy, 0, sizeof(policy)); 7614 info.cPolicyInfo = 1; 7615 info.rgPolicyInfo = policy; 7616 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info, 7617 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7618 ok(!ret && (GetLastError() == E_INVALIDARG || 7619 GetLastError() == OSS_LIMITED /* Win9x/NT4 */), 7620 "expected E_INVALIDARG or OSS_LIMITED, got %08x\n", GetLastError()); 7621 policy[0].pszPolicyIdentifier = oid_any_policy; 7622 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info, 7623 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7624 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7625 if (ret) 7626 { 7627 ok(sizeof(policiesWithAnyPolicy) == size, "unexpected size %d\n", size); 7628 ok(!memcmp(buf, policiesWithAnyPolicy, size), "unexpected value\n"); 7629 LocalFree(buf); 7630 } 7631 policy[1].pszPolicyIdentifier = oid1; 7632 memset(&qualifier, 0, sizeof(qualifier)); 7633 qualifier.pszPolicyQualifierId = oid_user_notice; 7634 qualifier.Qualifier.cbData = sizeof(noticeWithReference); 7635 qualifier.Qualifier.pbData = noticeWithReference; 7636 policy[1].cPolicyQualifier = 1; 7637 policy[1].rgPolicyQualifier = &qualifier; 7638 info.cPolicyInfo = 2; 7639 ret = pCryptEncodeObjectEx(dwEncoding, X509_CERT_POLICIES, &info, 7640 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7641 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7642 if (ret) 7643 { 7644 ok(sizeof(twoPolicies) == size, "unexpected size %d\n", size); 7645 ok(!memcmp(buf, twoPolicies, size), "unexpected value\n"); 7646 LocalFree(buf); 7647 } 7648 } 7649 7650 static void test_decodeCertPolicies(DWORD dwEncoding) 7651 { 7652 BOOL ret; 7653 CERT_POLICIES_INFO *info; 7654 DWORD size; 7655 7656 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES, 7657 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL, 7658 &info, &size); 7659 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7660 if (ret) 7661 { 7662 ok(info->cPolicyInfo == 0, "unexpected policy info %d\n", 7663 info->cPolicyInfo); 7664 LocalFree(info); 7665 } 7666 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES, 7667 policiesWithAnyPolicy, sizeof(policiesWithAnyPolicy), 7668 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size); 7669 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7670 if (ret) 7671 { 7672 ok(info->cPolicyInfo == 1, "unexpected policy info %d\n", 7673 info->cPolicyInfo); 7674 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy), 7675 "unexpected policy id %s\n", 7676 info->rgPolicyInfo[0].pszPolicyIdentifier); 7677 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0, 7678 "unexpected policy qualifier count %d\n", 7679 info->rgPolicyInfo[0].cPolicyQualifier); 7680 LocalFree(info); 7681 } 7682 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES, 7683 twoPolicies, sizeof(twoPolicies), 7684 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size); 7685 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7686 if (ret) 7687 { 7688 ok(info->cPolicyInfo == 2, "unexpected policy info %d\n", 7689 info->cPolicyInfo); 7690 ok(!strcmp(info->rgPolicyInfo[0].pszPolicyIdentifier, oid_any_policy), 7691 "unexpected policy id %s\n", 7692 info->rgPolicyInfo[0].pszPolicyIdentifier); 7693 ok(info->rgPolicyInfo[0].cPolicyQualifier == 0, 7694 "unexpected policy qualifier count %d\n", 7695 info->rgPolicyInfo[0].cPolicyQualifier); 7696 ok(!strcmp(info->rgPolicyInfo[1].pszPolicyIdentifier, oid1), 7697 "unexpected policy id %s\n", 7698 info->rgPolicyInfo[1].pszPolicyIdentifier); 7699 ok(info->rgPolicyInfo[1].cPolicyQualifier == 1, 7700 "unexpected policy qualifier count %d\n", 7701 info->rgPolicyInfo[1].cPolicyQualifier); 7702 ok(!strcmp( 7703 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId, 7704 oid_user_notice), "unexpected policy qualifier id %s\n", 7705 info->rgPolicyInfo[1].rgPolicyQualifier[0].pszPolicyQualifierId); 7706 ok(info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData == 7707 sizeof(noticeWithReference), "unexpected qualifier size %d\n", 7708 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.cbData); 7709 ok(!memcmp( 7710 info->rgPolicyInfo[1].rgPolicyQualifier[0].Qualifier.pbData, 7711 noticeWithReference, sizeof(noticeWithReference)), 7712 "unexpected qualifier value\n"); 7713 LocalFree(info); 7714 } 7715 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES, 7716 twoPolicies, sizeof(twoPolicies), 0, NULL, NULL, &size); 7717 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7718 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 7719 if (info) 7720 { 7721 ret = pCryptDecodeObjectEx(dwEncoding, X509_CERT_POLICIES, 7722 twoPolicies, sizeof(twoPolicies), 0, NULL, info, &size); 7723 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7724 HeapFree(GetProcessHeap(), 0, info); 7725 } 7726 } 7727 7728 static const BYTE policyMappingWithOneMapping[] = { 7729 0x30,0x0a,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04 }; 7730 static const BYTE policyMappingWithTwoMappings[] = { 7731 0x30,0x14,0x30,0x08,0x06,0x02,0x2a,0x03,0x06,0x02,0x53,0x04,0x30,0x08,0x06, 7732 0x02,0x2b,0x04,0x06,0x02,0x55,0x06 }; 7733 static const LPCSTR mappingOids[] = { X509_POLICY_MAPPINGS, 7734 szOID_POLICY_MAPPINGS, szOID_LEGACY_POLICY_MAPPINGS }; 7735 7736 static void test_encodeCertPolicyMappings(DWORD dwEncoding) 7737 { 7738 static char oid2[] = "2.3.4"; 7739 static char oid3[] = "1.3.4"; 7740 static char oid4[] = "2.5.6"; 7741 BOOL ret; 7742 CERT_POLICY_MAPPINGS_INFO info = { 0 }; 7743 CERT_POLICY_MAPPING mapping[2]; 7744 LPBYTE buf; 7745 DWORD size, i; 7746 7747 /* Each of the mapping OIDs is equivalent, so check with all of them */ 7748 for (i = 0; i < ARRAY_SIZE(mappingOids); i++) 7749 { 7750 memset(&info, 0, sizeof(info)); 7751 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info, 7752 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7753 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND), 7754 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7755 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 7756 { 7757 win_skip("no policy mappings support\n"); 7758 return; 7759 } 7760 if (ret) 7761 { 7762 ok(size == sizeof(emptySequence), "unexpected size %d\n", size); 7763 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)), 7764 "unexpected value\n"); 7765 LocalFree(buf); 7766 } 7767 mapping[0].pszIssuerDomainPolicy = NULL; 7768 mapping[0].pszSubjectDomainPolicy = NULL; 7769 info.cPolicyMapping = 1; 7770 info.rgPolicyMapping = mapping; 7771 SetLastError(0xdeadbeef); 7772 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info, 7773 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7774 ok(!ret && GetLastError() == E_INVALIDARG, 7775 "expected E_INVALIDARG, got %08x\n", GetLastError()); 7776 mapping[0].pszIssuerDomainPolicy = oid1; 7777 mapping[0].pszSubjectDomainPolicy = oid2; 7778 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info, 7779 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7780 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7781 if (ret) 7782 { 7783 ok(size == sizeof(policyMappingWithOneMapping), 7784 "unexpected size %d\n", size); 7785 ok(!memcmp(buf, policyMappingWithOneMapping, size), 7786 "unexpected value\n"); 7787 LocalFree(buf); 7788 } 7789 mapping[1].pszIssuerDomainPolicy = oid3; 7790 mapping[1].pszSubjectDomainPolicy = oid4; 7791 info.cPolicyMapping = 2; 7792 ret = pCryptEncodeObjectEx(dwEncoding, mappingOids[i], &info, 7793 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7794 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7795 if (ret) 7796 { 7797 ok(size == sizeof(policyMappingWithTwoMappings), 7798 "unexpected size %d\n", size); 7799 ok(!memcmp(buf, policyMappingWithTwoMappings, size), 7800 "unexpected value\n"); 7801 LocalFree(buf); 7802 } 7803 } 7804 } 7805 7806 static void test_decodeCertPolicyMappings(DWORD dwEncoding) 7807 { 7808 DWORD size, i; 7809 CERT_POLICY_MAPPINGS_INFO *info; 7810 BOOL ret; 7811 7812 /* Each of the mapping OIDs is equivalent, so check with all of them */ 7813 for (i = 0; i < ARRAY_SIZE(mappingOids); i++) 7814 { 7815 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i], 7816 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL, 7817 &info, &size); 7818 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND), 7819 "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7820 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 7821 { 7822 win_skip("no policy mappings support\n"); 7823 return; 7824 } 7825 if (ret) 7826 { 7827 ok(info->cPolicyMapping == 0, 7828 "expected 0 policy mappings, got %d\n", info->cPolicyMapping); 7829 LocalFree(info); 7830 } 7831 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i], 7832 policyMappingWithOneMapping, sizeof(policyMappingWithOneMapping), 7833 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size); 7834 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7835 if (ret) 7836 { 7837 ok(info->cPolicyMapping == 1, 7838 "expected 1 policy mappings, got %d\n", info->cPolicyMapping); 7839 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"), 7840 "unexpected issuer policy %s\n", 7841 info->rgPolicyMapping[0].pszIssuerDomainPolicy); 7842 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy, 7843 "2.3.4"), "unexpected subject policy %s\n", 7844 info->rgPolicyMapping[0].pszSubjectDomainPolicy); 7845 LocalFree(info); 7846 } 7847 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i], 7848 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 7849 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size); 7850 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7851 if (ret) 7852 { 7853 ok(info->cPolicyMapping == 2, 7854 "expected 2 policy mappings, got %d\n", info->cPolicyMapping); 7855 ok(!strcmp(info->rgPolicyMapping[0].pszIssuerDomainPolicy, "1.2.3"), 7856 "unexpected issuer policy %s\n", 7857 info->rgPolicyMapping[0].pszIssuerDomainPolicy); 7858 ok(!strcmp(info->rgPolicyMapping[0].pszSubjectDomainPolicy, 7859 "2.3.4"), "unexpected subject policy %s\n", 7860 info->rgPolicyMapping[0].pszSubjectDomainPolicy); 7861 ok(!strcmp(info->rgPolicyMapping[1].pszIssuerDomainPolicy, "1.3.4"), 7862 "unexpected issuer policy %s\n", 7863 info->rgPolicyMapping[1].pszIssuerDomainPolicy); 7864 ok(!strcmp(info->rgPolicyMapping[1].pszSubjectDomainPolicy, 7865 "2.5.6"), "unexpected subject policy %s\n", 7866 info->rgPolicyMapping[1].pszSubjectDomainPolicy); 7867 LocalFree(info); 7868 } 7869 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i], 7870 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0, 7871 NULL, NULL, &size); 7872 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7873 info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, size); 7874 if (info) 7875 { 7876 ret = pCryptDecodeObjectEx(dwEncoding, mappingOids[i], 7877 policyMappingWithTwoMappings, sizeof(policyMappingWithTwoMappings), 0, 7878 NULL, info, &size); 7879 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7880 HeapFree(GetProcessHeap(), 0, info); 7881 } 7882 } 7883 } 7884 7885 static const BYTE policyConstraintsWithRequireExplicit[] = { 7886 0x30,0x03,0x80,0x01,0x00 }; 7887 static const BYTE policyConstraintsWithInhibitMapping[] = { 7888 0x30,0x03,0x81,0x01,0x01 }; 7889 static const BYTE policyConstraintsWithBoth[] = { 7890 0x30,0x06,0x80,0x01,0x01,0x81,0x01,0x01 }; 7891 7892 static void test_encodeCertPolicyConstraints(DWORD dwEncoding) 7893 { 7894 CERT_POLICY_CONSTRAINTS_INFO info = { 0 }; 7895 LPBYTE buf; 7896 DWORD size; 7897 BOOL ret; 7898 7899 /* Even though RFC 5280 explicitly states CAs must not issue empty 7900 * policy constraints (section 4.2.1.11), the API doesn't prevent it. 7901 */ 7902 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info, 7903 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7904 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND), 7905 "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7906 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 7907 { 7908 win_skip("no policy constraints support\n"); 7909 return; 7910 } 7911 if (ret) 7912 { 7913 ok(size == sizeof(emptySequence), "unexpected size %d\n", size); 7914 ok(!memcmp(buf, emptySequence, sizeof(emptySequence)), 7915 "unexpected value\n"); 7916 LocalFree(buf); 7917 } 7918 /* If fRequireExplicitPolicy is set but dwRequireExplicitPolicySkipCerts 7919 * is not, then a skip of 0 is encoded. 7920 */ 7921 info.fRequireExplicitPolicy = TRUE; 7922 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info, 7923 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7924 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7925 if (ret) 7926 { 7927 ok(size == sizeof(policyConstraintsWithRequireExplicit), 7928 "unexpected size %d\n", size); 7929 ok(!memcmp(buf, policyConstraintsWithRequireExplicit, 7930 sizeof(policyConstraintsWithRequireExplicit)), "unexpected value\n"); 7931 LocalFree(buf); 7932 } 7933 /* With inhibit policy mapping */ 7934 info.fRequireExplicitPolicy = FALSE; 7935 info.dwRequireExplicitPolicySkipCerts = 0; 7936 info.fInhibitPolicyMapping = TRUE; 7937 info.dwInhibitPolicyMappingSkipCerts = 1; 7938 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info, 7939 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7940 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7941 if (ret) 7942 { 7943 ok(size == sizeof(policyConstraintsWithInhibitMapping), 7944 "unexpected size %d\n", size); 7945 ok(!memcmp(buf, policyConstraintsWithInhibitMapping, 7946 sizeof(policyConstraintsWithInhibitMapping)), "unexpected value\n"); 7947 LocalFree(buf); 7948 } 7949 /* And with both */ 7950 info.fRequireExplicitPolicy = TRUE; 7951 info.dwRequireExplicitPolicySkipCerts = 1; 7952 ret = pCryptEncodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, &info, 7953 CRYPT_ENCODE_ALLOC_FLAG, NULL, &buf, &size); 7954 ok(ret, "CryptEncodeObjectEx failed: %08x\n", GetLastError()); 7955 if (ret) 7956 { 7957 ok(size == sizeof(policyConstraintsWithBoth), "unexpected size %d\n", 7958 size); 7959 ok(!memcmp(buf, policyConstraintsWithBoth, 7960 sizeof(policyConstraintsWithBoth)), "unexpected value\n"); 7961 LocalFree(buf); 7962 } 7963 } 7964 7965 static void test_decodeCertPolicyConstraints(DWORD dwEncoding) 7966 { 7967 CERT_POLICY_CONSTRAINTS_INFO *info; 7968 DWORD size; 7969 BOOL ret; 7970 7971 /* Again, even though CAs must not issue such constraints, they can be 7972 * decoded. 7973 */ 7974 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, 7975 emptySequence, sizeof(emptySequence), CRYPT_DECODE_ALLOC_FLAG, NULL, 7976 &info, &size); 7977 ok(ret || broken(GetLastError() == ERROR_FILE_NOT_FOUND), 7978 "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7979 if (!ret && GetLastError() == ERROR_FILE_NOT_FOUND) 7980 { 7981 win_skip("no policy mappings support\n"); 7982 return; 7983 } 7984 if (ret) 7985 { 7986 ok(!info->fRequireExplicitPolicy, 7987 "expected require explicit = FALSE\n"); 7988 ok(!info->fInhibitPolicyMapping, 7989 "expected implicit mapping = FALSE\n"); 7990 LocalFree(info); 7991 } 7992 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, 7993 policyConstraintsWithRequireExplicit, 7994 sizeof(policyConstraintsWithRequireExplicit), CRYPT_DECODE_ALLOC_FLAG, 7995 NULL, &info, &size); 7996 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 7997 if (ret) 7998 { 7999 ok(info->fRequireExplicitPolicy, 8000 "expected require explicit = TRUE\n"); 8001 ok(info->dwRequireExplicitPolicySkipCerts == 0, "expected 0, got %d\n", 8002 info->dwRequireExplicitPolicySkipCerts); 8003 ok(!info->fInhibitPolicyMapping, 8004 "expected implicit mapping = FALSE\n"); 8005 LocalFree(info); 8006 } 8007 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, 8008 policyConstraintsWithInhibitMapping, 8009 sizeof(policyConstraintsWithInhibitMapping), CRYPT_DECODE_ALLOC_FLAG, 8010 NULL, &info, &size); 8011 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 8012 if (ret) 8013 { 8014 ok(!info->fRequireExplicitPolicy, 8015 "expected require explicit = FALSE\n"); 8016 ok(info->fInhibitPolicyMapping, 8017 "expected implicit mapping = TRUE\n"); 8018 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n", 8019 info->dwInhibitPolicyMappingSkipCerts); 8020 LocalFree(info); 8021 } 8022 ret = pCryptDecodeObjectEx(dwEncoding, X509_POLICY_CONSTRAINTS, 8023 policyConstraintsWithBoth, sizeof(policyConstraintsWithBoth), 8024 CRYPT_DECODE_ALLOC_FLAG, NULL, &info, &size); 8025 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 8026 if (ret) 8027 { 8028 ok(info->fRequireExplicitPolicy, 8029 "expected require explicit = TRUE\n"); 8030 ok(info->dwRequireExplicitPolicySkipCerts == 1, "expected 1, got %d\n", 8031 info->dwRequireExplicitPolicySkipCerts); 8032 ok(info->fInhibitPolicyMapping, 8033 "expected implicit mapping = TRUE\n"); 8034 ok(info->dwInhibitPolicyMappingSkipCerts == 1, "expected 1, got %d\n", 8035 info->dwInhibitPolicyMappingSkipCerts); 8036 LocalFree(info); 8037 } 8038 } 8039 8040 static const BYTE rsaPrivKeyDer[] = { 8041 0x30,0x82,0x04,0xa5,0x02,0x01,0x00,0x02,0x82,0x01,0x01,0x00, 8042 0xae,0xba,0x3c,0x41,0xeb,0x25,0x41,0xb0,0x1c,0x41,0xd4,0x26, 8043 0xf9,0xf8,0x31,0x64,0x7e,0x97,0x65,0x54,0x9c,0x90,0xdf,0x34, 8044 0x07,0xfb,0xb0,0x69,0x99,0x3b,0x45,0x39,0x06,0xe4,0x3a,0x7a, 8045 0x01,0xe0,0xeb,0x3f,0xe1,0xd5,0x91,0xe0,0x16,0xe0,0xf2,0x35, 8046 0x59,0xdf,0x32,0x2d,0x69,0x3a,0x4a,0xbc,0xd1,0xba,0x1b,0x3b, 8047 0x7a,0x55,0x76,0xba,0x11,0xdd,0x2f,0xc7,0x58,0x66,0xf2,0x6c, 8048 0xd1,0x68,0x27,0x6c,0x85,0x74,0x0b,0xc9,0x7b,0x1a,0xde,0x3c, 8049 0x62,0x73,0xe2,0x9e,0x36,0x3a,0x29,0x3b,0x91,0x85,0x3d,0xd2, 8050 0xe1,0xe5,0x61,0x84,0x1e,0x28,0xfd,0xb7,0x97,0x68,0xc1,0xbb, 8051 0x0f,0x93,0x14,0xc2,0x03,0x60,0x41,0x11,0x7a,0xda,0x76,0x01, 8052 0x65,0x08,0xe6,0x0c,0xf6,0xfc,0x1d,0x64,0x12,0x7b,0x42,0xb0, 8053 0xb8,0xfe,0x61,0xe5,0xe2,0xe5,0x61,0x44,0xcc,0x94,0xe8,0xc0, 8054 0x4f,0x58,0x9a,0xea,0x99,0xaf,0x9c,0xa4,0xf2,0xd7,0x2b,0x31, 8055 0x90,0x3b,0x41,0x2e,0x4a,0x74,0x7c,0x1a,0xfc,0x42,0xa9,0x17, 8056 0xff,0x53,0x20,0x76,0xa7,0xf0,0x2c,0xb9,0xd5,0x1f,0xa9,0x8a, 8057 0x77,0xa8,0x09,0x5c,0x0e,0xd1,0x54,0xc5,0xf2,0x86,0xf1,0x2f, 8058 0x23,0xd6,0x63,0xba,0xe9,0x2b,0x73,0xf9,0xf0,0xdc,0xcb,0xf9, 8059 0xcb,0xe8,0x40,0x62,0x47,0x09,0x85,0xe1,0x9c,0xfd,0xcf,0x75, 8060 0x5a,0x65,0xfd,0x86,0x1c,0x50,0xfa,0x24,0x36,0x0f,0x54,0x5e, 8061 0x81,0xe7,0xf6,0x63,0x2d,0x87,0x0c,0x50,0x03,0x25,0x49,0xe7, 8062 0xc5,0x20,0xaa,0xbc,0x6c,0xf9,0xbe,0x49,0x8f,0x4f,0xb8,0x9a, 8063 0x73,0x9f,0x55,0x43,0x02,0x03,0x01,0x00,0x01,0x02,0x82,0x01, 8064 0x01,0x00,0x99,0x03,0xcd,0x5b,0x69,0x03,0x32,0x98,0x78,0xd6, 8065 0x89,0x65,0x2c,0xc9,0xd6,0xef,0x8c,0x11,0x27,0x93,0x46,0x9d, 8066 0x74,0x6a,0xcb,0x86,0xf6,0x02,0x34,0x47,0xfc,0xa2,0x29,0x4f, 8067 0xdb,0x8a,0x17,0x75,0x12,0x6f,0xda,0x65,0x3f,0x1f,0xc0,0xc9, 8068 0x74,0x33,0x96,0xa5,0xe8,0xfa,0x6d,0xc9,0xb7,0xc3,0xcd,0xe3, 8069 0x2e,0x90,0x12,0xdd,0x1f,0x61,0x69,0xdd,0x8b,0x47,0x07,0x3a, 8070 0xf8,0x98,0xa5,0x76,0x91,0xf7,0xee,0x93,0x26,0xf3,0x66,0x54, 8071 0xac,0x44,0xb3,0x6f,0x8b,0x09,0x44,0xb2,0x00,0x84,0x03,0x37, 8072 0x6d,0x61,0xed,0xa4,0x04,0x97,0x40,0x16,0x63,0xc2,0xd0,0xdc, 8073 0xd3,0xb3,0xee,0xba,0xbe,0x95,0xfd,0x80,0xe0,0xda,0xde,0xfc, 8074 0xcc,0x15,0x02,0x97,0x1d,0x68,0x43,0x2f,0x9c,0xc8,0x20,0x23, 8075 0xeb,0x00,0x4c,0x74,0x3d,0x27,0x20,0x14,0x23,0x95,0xfc,0x8c, 8076 0xb7,0x7e,0x7f,0xb0,0xdb,0xaf,0x8a,0x48,0x1b,0xfe,0x59,0xab, 8077 0x75,0xe2,0xbf,0x69,0xf2,0x73,0xe3,0xb9,0x92,0xa9,0x90,0x03, 8078 0xe5,0xd4,0x2d,0x86,0xff,0x12,0x54,0xb3,0xbb,0xe2,0xce,0x81, 8079 0x58,0x71,0xa4,0xde,0x45,0x05,0xf8,0x2d,0x45,0xf5,0xd8,0x5e, 8080 0x4c,0x5d,0x06,0x69,0x0c,0x86,0x9f,0x66,0x9f,0xb1,0x60,0xfd, 8081 0xf2,0x33,0x85,0x15,0xd5,0x18,0xf7,0xba,0x99,0x65,0x15,0x1d, 8082 0xfa,0xaa,0x76,0xdd,0x25,0xed,0xdf,0x90,0x6e,0xba,0x61,0x96, 8083 0x79,0xde,0xd2,0xda,0x66,0x03,0x74,0x3b,0x13,0x39,0x68,0xbc, 8084 0x94,0x01,0x00,0x2d,0xf8,0xf0,0x8c,0xbd,0x4c,0x9c,0x7e,0x87, 8085 0x9c,0x62,0x9f,0xb6,0x90,0x11,0x02,0x81,0x81,0x00,0xe3,0x5e, 8086 0xfe,0xdd,0xed,0x76,0xb6,0x4e,0xfc,0x5b,0xe0,0x20,0x99,0x7b, 8087 0x48,0x3b,0x1e,0x5f,0x7f,0x9f,0xa4,0x68,0xbe,0xc3,0x7f,0xb8, 8088 0x62,0x98,0xb0,0x95,0x8a,0xfa,0x0d,0xa3,0x79,0x63,0x39,0xf7, 8089 0xdb,0x76,0x3d,0x53,0x4a,0x0a,0x33,0xdf,0xe0,0x47,0x22,0xd5, 8090 0x96,0x80,0xc7,0xcd,0x24,0xef,0xac,0x49,0x46,0x37,0x6c,0x25, 8091 0xcf,0x6c,0x4d,0xe5,0x31,0xf8,0x2f,0xd2,0x59,0x74,0x00,0x38, 8092 0xdb,0xce,0xd1,0x72,0xc3,0xa8,0x30,0x70,0xd8,0x02,0x20,0xe7, 8093 0x56,0xe7,0xca,0xf0,0x3b,0x52,0x5d,0x11,0xbe,0x53,0x4e,0xd0, 8094 0xd9,0x2e,0xa6,0xb8,0xe2,0xd9,0xbf,0xb9,0x77,0xe7,0x3b,0xed, 8095 0x5e,0xd7,0x16,0x4a,0x3a,0xc5,0x86,0xd7,0x74,0x20,0xa7,0x8e, 8096 0xbf,0xb7,0x33,0xdb,0x51,0xe9,0x02,0x81,0x81,0x00,0xc4,0xba, 8097 0x57,0xf0,0x6e,0xcf,0xe8,0xce,0xce,0x9d,0x4a,0xe9,0x0f,0xe1, 8098 0xab,0x91,0x62,0xaa,0x66,0x5d,0x82,0x66,0x1c,0x72,0x18,0x6f, 8099 0x68,0x9c,0x7d,0x5e,0xfc,0xaf,0x4a,0xd6,0x8e,0xc6,0xae,0x40, 8100 0xf2,0x40,0x84,0x93,0xee,0x7c,0x87,0xa9,0xa6,0xcd,0x2b,0xc3, 8101 0xe6,0x29,0x3a,0xe2,0x4a,0xed,0xb0,0x4d,0x9f,0xc0,0xe9,0xd6, 8102 0xa3,0xca,0x97,0xee,0xac,0xab,0xa4,0x32,0x05,0x40,0x4d,0xf2, 8103 0x95,0x99,0xaf,0xa0,0xe1,0xe1,0xe7,0x3a,0x64,0xa4,0x70,0x6b, 8104 0x3d,0x1d,0x7b,0xf1,0x53,0xfa,0xb0,0xe0,0xe2,0x68,0x1a,0x61, 8105 0x2c,0x37,0xa5,0x39,0x7b,0xb2,0xcf,0xe6,0x5f,0x9b,0xc6,0x64, 8106 0xaf,0x48,0x86,0xfb,0xc1,0xf3,0x39,0x97,0x10,0x36,0xf5,0xa9, 8107 0x3d,0x08,0xa5,0x2f,0xe6,0x4b,0x02,0x81,0x81,0x00,0x86,0xe7, 8108 0x02,0x08,0xe2,0xaf,0xa0,0x93,0x54,0x9f,0x9e,0x67,0x39,0x29, 8109 0x30,0x3e,0x03,0x53,0x5e,0x01,0x76,0x26,0xbf,0xa8,0x76,0xcb, 8110 0x0b,0x94,0xd4,0x90,0xa5,0x98,0x9f,0x26,0xf3,0x0a,0xb0,0x86, 8111 0x22,0xac,0x10,0xce,0xae,0x0b,0x47,0xa3,0xf9,0x09,0xbb,0xdd, 8112 0x46,0x22,0xba,0x69,0x39,0x15,0x0a,0xff,0x9e,0xad,0x9b,0x79, 8113 0x03,0x8c,0x9a,0xda,0xf5,0xbe,0xef,0x80,0xba,0x9a,0x5c,0xd7, 8114 0x5f,0x73,0x62,0x49,0xd9,0x54,0x9d,0x09,0x16,0xe0,0x8c,0x6d, 8115 0x35,0xde,0xe9,0x45,0x87,0xac,0xe2,0x93,0x78,0x7d,0x2d,0x32, 8116 0x34,0xe9,0xbc,0xf9,0xcd,0x7e,0xac,0x86,0x7a,0x61,0xb3,0xe8, 8117 0xae,0x70,0xa7,0x44,0xfb,0x81,0xde,0xf3,0x4e,0x6f,0x61,0x7b, 8118 0x0c,0xbc,0xc2,0x03,0xca,0xa1,0x02,0x81,0x80,0x69,0x5b,0x4a, 8119 0xa1,0x4f,0x17,0x35,0x9d,0x1b,0xf6,0x0d,0x1a,0x48,0x11,0x19, 8120 0xab,0x20,0xe6,0x15,0x30,0x5b,0x17,0x88,0x80,0x6a,0x29,0xb0, 8121 0x22,0xae,0xd9,0xe2,0x05,0x96,0xd4,0xd5,0x5d,0xfe,0x10,0x76, 8122 0x2c,0xab,0x53,0xf6,0x52,0xe6,0xec,0xaa,0x92,0x12,0xb0,0x35, 8123 0x61,0x3b,0x51,0xd9,0xc2,0xf5,0xba,0x7c,0xa5,0xfa,0x15,0xa3, 8124 0x5e,0x6a,0x83,0xbe,0x21,0xa6,0x2b,0xcb,0xb8,0x26,0x86,0x96, 8125 0x2b,0xda,0x6d,0x14,0xcb,0xc0,0xe3,0xfa,0xe6,0x3d,0xf6,0x90, 8126 0xa2,0x6b,0xb0,0x50,0xc3,0x5f,0x5a,0xf0,0xa5,0xc4,0x0a,0xea, 8127 0x7d,0x5a,0x95,0x30,0x74,0x10,0xf7,0x55,0x98,0xbd,0x65,0x4a, 8128 0xa2,0x52,0xf8,0x1d,0x64,0xbf,0x20,0xf1,0xe4,0x1d,0x28,0x67, 8129 0xb1,0x6b,0x95,0xfd,0x85,0x02,0x81,0x81,0x00,0xda,0xb4,0x31, 8130 0x34,0xe1,0xec,0x9a,0x1e,0x07,0xd7,0xda,0x20,0x46,0xbf,0x6b, 8131 0xf0,0x45,0xbd,0x50,0xa2,0x0f,0x8a,0x14,0x51,0x52,0x83,0x7c, 8132 0x47,0xc8,0x9c,0x4e,0x68,0x6b,0xae,0x00,0x25,0x63,0xdd,0x13, 8133 0x2a,0x66,0x65,0xb6,0x74,0x91,0x5b,0xb6,0x47,0x3e,0x8e,0x46, 8134 0x62,0xcd,0x9d,0xc1,0xf7,0x14,0x14,0xbc,0x60,0xd6,0x3c,0x7c, 8135 0x3a,0xce,0xff,0x96,0x04,0x84,0xf6,0x44,0x1a,0xf8,0xdb,0x40, 8136 0x1c,0xf2,0xf1,0x4d,0xb2,0x68,0x3e,0xa3,0x0b,0xc6,0xb1,0xd0, 8137 0xa6,0x88,0x18,0x68,0xa1,0x05,0x2a,0xfc,0x2b,0x3a,0xa1,0xe6, 8138 0x31,0x4a,0x46,0x88,0x39,0x1e,0x44,0x11,0x6c,0xc5,0x8b,0xb6, 8139 0x8b,0xce,0x3d,0xd5,0xcb,0xbd,0xf0,0xd4,0xd9,0xfb,0x02,0x35, 8140 0x96,0x39,0x26,0x85,0xf9 }; 8141 static const BYTE rsaPrivKeyModulus[] = { 8142 0x43,0x55,0x9f,0x73,0x9a,0xb8,0x4f,0x8f,0x49,0xbe,0xf9,0x6c, 8143 0xbc,0xaa,0x20,0xc5,0xe7,0x49,0x25,0x03,0x50,0x0c,0x87,0x2d, 8144 0x63,0xf6,0xe7,0x81,0x5e,0x54,0x0f,0x36,0x24,0xfa,0x50,0x1c, 8145 0x86,0xfd,0x65,0x5a,0x75,0xcf,0xfd,0x9c,0xe1,0x85,0x09,0x47, 8146 0x62,0x40,0xe8,0xcb,0xf9,0xcb,0xdc,0xf0,0xf9,0x73,0x2b,0xe9, 8147 0xba,0x63,0xd6,0x23,0x2f,0xf1,0x86,0xf2,0xc5,0x54,0xd1,0x0e, 8148 0x5c,0x09,0xa8,0x77,0x8a,0xa9,0x1f,0xd5,0xb9,0x2c,0xf0,0xa7, 8149 0x76,0x20,0x53,0xff,0x17,0xa9,0x42,0xfc,0x1a,0x7c,0x74,0x4a, 8150 0x2e,0x41,0x3b,0x90,0x31,0x2b,0xd7,0xf2,0xa4,0x9c,0xaf,0x99, 8151 0xea,0x9a,0x58,0x4f,0xc0,0xe8,0x94,0xcc,0x44,0x61,0xe5,0xe2, 8152 0xe5,0x61,0xfe,0xb8,0xb0,0x42,0x7b,0x12,0x64,0x1d,0xfc,0xf6, 8153 0x0c,0xe6,0x08,0x65,0x01,0x76,0xda,0x7a,0x11,0x41,0x60,0x03, 8154 0xc2,0x14,0x93,0x0f,0xbb,0xc1,0x68,0x97,0xb7,0xfd,0x28,0x1e, 8155 0x84,0x61,0xe5,0xe1,0xd2,0x3d,0x85,0x91,0x3b,0x29,0x3a,0x36, 8156 0x9e,0xe2,0x73,0x62,0x3c,0xde,0x1a,0x7b,0xc9,0x0b,0x74,0x85, 8157 0x6c,0x27,0x68,0xd1,0x6c,0xf2,0x66,0x58,0xc7,0x2f,0xdd,0x11, 8158 0xba,0x76,0x55,0x7a,0x3b,0x1b,0xba,0xd1,0xbc,0x4a,0x3a,0x69, 8159 0x2d,0x32,0xdf,0x59,0x35,0xf2,0xe0,0x16,0xe0,0x91,0xd5,0xe1, 8160 0x3f,0xeb,0xe0,0x01,0x7a,0x3a,0xe4,0x06,0x39,0x45,0x3b,0x99, 8161 0x69,0xb0,0xfb,0x07,0x34,0xdf,0x90,0x9c,0x54,0x65,0x97,0x7e, 8162 0x64,0x31,0xf8,0xf9,0x26,0xd4,0x41,0x1c,0xb0,0x41,0x25,0xeb, 8163 0x41,0x3c,0xba,0xae }; 8164 static const BYTE rsaPrivKeyPrime1[] = { 8165 0xe9,0x51,0xdb,0x33,0xb7,0xbf,0x8e,0xa7,0x20,0x74,0xd7,0x86, 8166 0xc5,0x3a,0x4a,0x16,0xd7,0x5e,0xed,0x3b,0xe7,0x77,0xb9,0xbf, 8167 0xd9,0xe2,0xb8,0xa6,0x2e,0xd9,0xd0,0x4e,0x53,0xbe,0x11,0x5d, 8168 0x52,0x3b,0xf0,0xca,0xe7,0x56,0xe7,0x20,0x02,0xd8,0x70,0x30, 8169 0xa8,0xc3,0x72,0xd1,0xce,0xdb,0x38,0x00,0x74,0x59,0xd2,0x2f, 8170 0xf8,0x31,0xe5,0x4d,0x6c,0xcf,0x25,0x6c,0x37,0x46,0x49,0xac, 8171 0xef,0x24,0xcd,0xc7,0x80,0x96,0xd5,0x22,0x47,0xe0,0xdf,0x33, 8172 0x0a,0x4a,0x53,0x3d,0x76,0xdb,0xf7,0x39,0x63,0x79,0xa3,0x0d, 8173 0xfa,0x8a,0x95,0xb0,0x98,0x62,0xb8,0x7f,0xc3,0xbe,0x68,0xa4, 8174 0x9f,0x7f,0x5f,0x1e,0x3b,0x48,0x7b,0x99,0x20,0xe0,0x5b,0xfc, 8175 0x4e,0xb6,0x76,0xed,0xdd,0xfe,0x5e,0xe3 }; 8176 static const BYTE rsaPrivKeyPrime2[] = { 8177 0x4b,0xe6,0x2f,0xa5,0x08,0x3d,0xa9,0xf5,0x36,0x10,0x97,0x39, 8178 0xf3,0xc1,0xfb,0x86,0x48,0xaf,0x64,0xc6,0x9b,0x5f,0xe6,0xcf, 8179 0xb2,0x7b,0x39,0xa5,0x37,0x2c,0x61,0x1a,0x68,0xe2,0xe0,0xb0, 8180 0xfa,0x53,0xf1,0x7b,0x1d,0x3d,0x6b,0x70,0xa4,0x64,0x3a,0xe7, 8181 0xe1,0xe1,0xa0,0xaf,0x99,0x95,0xf2,0x4d,0x40,0x05,0x32,0xa4, 8182 0xab,0xac,0xee,0x97,0xca,0xa3,0xd6,0xe9,0xc0,0x9f,0x4d,0xb0, 8183 0xed,0x4a,0xe2,0x3a,0x29,0xe6,0xc3,0x2b,0xcd,0xa6,0xa9,0x87, 8184 0x7c,0xee,0x93,0x84,0x40,0xf2,0x40,0xae,0xc6,0x8e,0xd6,0x4a, 8185 0xaf,0xfc,0x5e,0x7d,0x9c,0x68,0x6f,0x18,0x72,0x1c,0x66,0x82, 8186 0x5d,0x66,0xaa,0x62,0x91,0xab,0xe1,0x0f,0xe9,0x4a,0x9d,0xce, 8187 0xce,0xe8,0xcf,0x6e,0xf0,0x57,0xba,0xc4 }; 8188 static const BYTE rsaPrivKeyExponent1[] = { 8189 0xa1,0xca,0x03,0xc2,0xbc,0x0c,0x7b,0x61,0x6f,0x4e,0xf3,0xde, 8190 0x81,0xfb,0x44,0xa7,0x70,0xae,0xe8,0xb3,0x61,0x7a,0x86,0xac, 8191 0x7e,0xcd,0xf9,0xbc,0xe9,0x34,0x32,0x2d,0x7d,0x78,0x93,0xe2, 8192 0xac,0x87,0x45,0xe9,0xde,0x35,0x6d,0x8c,0xe0,0x16,0x09,0x9d, 8193 0x54,0xd9,0x49,0x62,0x73,0x5f,0xd7,0x5c,0x9a,0xba,0x80,0xef, 8194 0xbe,0xf5,0xda,0x9a,0x8c,0x03,0x79,0x9b,0xad,0x9e,0xff,0x0a, 8195 0x15,0x39,0x69,0xba,0x22,0x46,0xdd,0xbb,0x09,0xf9,0xa3,0x47, 8196 0x0b,0xae,0xce,0x10,0xac,0x22,0x86,0xb0,0x0a,0xf3,0x26,0x9f, 8197 0x98,0xa5,0x90,0xd4,0x94,0x0b,0xcb,0x76,0xa8,0xbf,0x26,0x76, 8198 0x01,0x5e,0x53,0x03,0x3e,0x30,0x29,0x39,0x67,0x9e,0x9f,0x54, 8199 0x93,0xa0,0xaf,0xe2,0x08,0x02,0xe7,0x86 }; 8200 static const BYTE rsaPrivKeyExponent2[] = { 8201 0x85,0xfd,0x95,0x6b,0xb1,0x67,0x28,0x1d,0xe4,0xf1,0x20,0xbf, 8202 0x64,0x1d,0xf8,0x52,0xa2,0x4a,0x65,0xbd,0x98,0x55,0xf7,0x10, 8203 0x74,0x30,0x95,0x5a,0x7d,0xea,0x0a,0xc4,0xa5,0xf0,0x5a,0x5f, 8204 0xc3,0x50,0xb0,0x6b,0xa2,0x90,0xf6,0x3d,0xe6,0xfa,0xe3,0xc0, 8205 0xcb,0x14,0x6d,0xda,0x2b,0x96,0x86,0x26,0xb8,0xcb,0x2b,0xa6, 8206 0x21,0xbe,0x83,0x6a,0x5e,0xa3,0x15,0xfa,0xa5,0x7c,0xba,0xf5, 8207 0xc2,0xd9,0x51,0x3b,0x61,0x35,0xb0,0x12,0x92,0xaa,0xec,0xe6, 8208 0x52,0xf6,0x53,0xab,0x2c,0x76,0x10,0xfe,0x5d,0xd5,0xd4,0x96, 8209 0x05,0xe2,0xd9,0xae,0x22,0xb0,0x29,0x6a,0x80,0x88,0x17,0x5b, 8210 0x30,0x15,0xe6,0x20,0xab,0x19,0x11,0x48,0x1a,0x0d,0xf6,0x1b, 8211 0x9d,0x35,0x17,0x4f,0xa1,0x4a,0x5b,0x69 }; 8212 static const BYTE rsaPrivKeyCoefficient[] = { 8213 0xf9,0x85,0x26,0x39,0x96,0x35,0x02,0xfb,0xd9,0xd4,0xf0,0xbd, 8214 0xcb,0xd5,0x3d,0xce,0x8b,0xb6,0x8b,0xc5,0x6c,0x11,0x44,0x1e, 8215 0x39,0x88,0x46,0x4a,0x31,0xe6,0xa1,0x3a,0x2b,0xfc,0x2a,0x05, 8216 0xa1,0x68,0x18,0x88,0xa6,0xd0,0xb1,0xc6,0x0b,0xa3,0x3e,0x68, 8217 0xb2,0x4d,0xf1,0xf2,0x1c,0x40,0xdb,0xf8,0x1a,0x44,0xf6,0x84, 8218 0x04,0x96,0xff,0xce,0x3a,0x7c,0x3c,0xd6,0x60,0xbc,0x14,0x14, 8219 0xf7,0xc1,0x9d,0xcd,0x62,0x46,0x8e,0x3e,0x47,0xb6,0x5b,0x91, 8220 0x74,0xb6,0x65,0x66,0x2a,0x13,0xdd,0x63,0x25,0x00,0xae,0x6b, 8221 0x68,0x4e,0x9c,0xc8,0x47,0x7c,0x83,0x52,0x51,0x14,0x8a,0x0f, 8222 0xa2,0x50,0xbd,0x45,0xf0,0x6b,0xbf,0x46,0x20,0xda,0xd7,0x07, 8223 0x1e,0x9a,0xec,0xe1,0x34,0x31,0xb4,0xda }; 8224 static const BYTE rsaPrivKeyPrivateExponent[] = { 8225 0x11,0x90,0xb6,0x9f,0x62,0x9c,0x87,0x7e,0x9c,0x4c,0xbd,0x8c, 8226 0xf0,0xf8,0x2d,0x00,0x01,0x94,0xbc,0x68,0x39,0x13,0x3b,0x74, 8227 0x03,0x66,0xda,0xd2,0xde,0x79,0x96,0x61,0xba,0x6e,0x90,0xdf, 8228 0xed,0x25,0xdd,0x76,0xaa,0xfa,0x1d,0x15,0x65,0x99,0xba,0xf7, 8229 0x18,0xd5,0x15,0x85,0x33,0xf2,0xfd,0x60,0xb1,0x9f,0x66,0x9f, 8230 0x86,0x0c,0x69,0x06,0x5d,0x4c,0x5e,0xd8,0xf5,0x45,0x2d,0xf8, 8231 0x05,0x45,0xde,0xa4,0x71,0x58,0x81,0xce,0xe2,0xbb,0xb3,0x54, 8232 0x12,0xff,0x86,0x2d,0xd4,0xe5,0x03,0x90,0xa9,0x92,0xb9,0xe3, 8233 0x73,0xf2,0x69,0xbf,0xe2,0x75,0xab,0x59,0xfe,0x1b,0x48,0x8a, 8234 0xaf,0xdb,0xb0,0x7f,0x7e,0xb7,0x8c,0xfc,0x95,0x23,0x14,0x20, 8235 0x27,0x3d,0x74,0x4c,0x00,0xeb,0x23,0x20,0xc8,0x9c,0x2f,0x43, 8236 0x68,0x1d,0x97,0x02,0x15,0xcc,0xfc,0xde,0xda,0xe0,0x80,0xfd, 8237 0x95,0xbe,0xba,0xee,0xb3,0xd3,0xdc,0xd0,0xc2,0x63,0x16,0x40, 8238 0x97,0x04,0xa4,0xed,0x61,0x6d,0x37,0x03,0x84,0x00,0xb2,0x44, 8239 0x09,0x8b,0x6f,0xb3,0x44,0xac,0x54,0x66,0xf3,0x26,0x93,0xee, 8240 0xf7,0x91,0x76,0xa5,0x98,0xf8,0x3a,0x07,0x47,0x8b,0xdd,0x69, 8241 0x61,0x1f,0xdd,0x12,0x90,0x2e,0xe3,0xcd,0xc3,0xb7,0xc9,0x6d, 8242 0xfa,0xe8,0xa5,0x96,0x33,0x74,0xc9,0xc0,0x1f,0x3f,0x65,0xda, 8243 0x6f,0x12,0x75,0x17,0x8a,0xdb,0x4f,0x29,0xa2,0xfc,0x47,0x34, 8244 0x02,0xf6,0x86,0xcb,0x6a,0x74,0x9d,0x46,0x93,0x27,0x11,0x8c, 8245 0xef,0xd6,0xc9,0x2c,0x65,0x89,0xd6,0x78,0x98,0x32,0x03,0x69, 8246 0x5b,0xcd,0x03,0x99 }; 8247 8248 static void test_decodeRsaPrivateKey(DWORD dwEncoding) 8249 { 8250 LPBYTE buf = NULL; 8251 DWORD bufSize = 0; 8252 BOOL ret; 8253 8254 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY, 8255 rsaPrivKeyDer, sizeof(rsaPrivKeyDer)-10, 8256 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 8257 ok(!ret && (GetLastError() == CRYPT_E_ASN1_EOD), 8258 "Expected CRYPT_E_ASN1_EOD, got %08x\n", 8259 GetLastError()); 8260 8261 buf = NULL; 8262 bufSize = 0; 8263 ret = pCryptDecodeObjectEx(dwEncoding, PKCS_RSA_PRIVATE_KEY, 8264 rsaPrivKeyDer, sizeof(rsaPrivKeyDer), 8265 CRYPT_DECODE_ALLOC_FLAG, NULL, &buf, &bufSize); 8266 ok(ret, "CryptDecodeObjectEx failed: %08x\n", GetLastError()); 8267 8268 if (ret) 8269 { 8270 BLOBHEADER *hdr = (BLOBHEADER *)buf; 8271 RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(buf + sizeof(BLOBHEADER)); 8272 static const int bitlen = 2048; 8273 BYTE *modulus = (BYTE*)(rsaPubKey + 1); 8274 BYTE *prime1 = modulus + bitlen/8; 8275 BYTE *prime2 = prime1 + bitlen/16; 8276 BYTE *exponent1 = prime2 + bitlen/16; 8277 BYTE *exponent2 = exponent1 + bitlen/16; 8278 BYTE *coefficient = exponent2 + bitlen/16; 8279 BYTE *privateExponent = coefficient + bitlen/16; 8280 8281 ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + 8282 (bitlen * 9 / 16), 8283 "Wrong size %d\n", bufSize); 8284 8285 ok(hdr->bType == PRIVATEKEYBLOB, 8286 "Expected type PRIVATEKEYBLOB (%d), got %d\n", PRIVATEKEYBLOB, 8287 hdr->bType); 8288 ok(hdr->bVersion == CUR_BLOB_VERSION, 8289 "Expected version CUR_BLOB_VERSION (%d), got %d\n", 8290 CUR_BLOB_VERSION, hdr->bVersion); 8291 ok(hdr->reserved == 0, "Expected reserved 0, got %d\n", 8292 hdr->reserved); 8293 ok(hdr->aiKeyAlg == CALG_RSA_KEYX, 8294 "Expected CALG_RSA_KEYX, got %08x\n", hdr->aiKeyAlg); 8295 8296 ok(rsaPubKey->magic == 0x32415352, 8297 "Expected magic 0x32415352, got 0x%x\n", rsaPubKey->magic); 8298 ok(rsaPubKey->bitlen == bitlen, 8299 "Expected bitlen %d, got %d\n", bitlen, rsaPubKey->bitlen); 8300 ok(rsaPubKey->pubexp == 65537, 8301 "Expected pubexp 65537, got %d\n", rsaPubKey->pubexp); 8302 8303 ok(!memcmp(modulus, rsaPrivKeyModulus, bitlen/8), 8304 "unexpected modulus\n"); 8305 ok(!memcmp(prime1, rsaPrivKeyPrime1, bitlen/16), 8306 "unexpected prime1\n"); 8307 ok(!memcmp(prime2, rsaPrivKeyPrime2, bitlen/16), 8308 "unexpected prime2\n"); 8309 ok(!memcmp(exponent1, rsaPrivKeyExponent1, bitlen/16), 8310 "unexpected exponent1\n"); 8311 ok(!memcmp(exponent2, rsaPrivKeyExponent2, bitlen/16), 8312 "unexpected exponent2\n"); 8313 ok(!memcmp(coefficient, rsaPrivKeyCoefficient, bitlen/16), 8314 "unexpected coefficient\n"); 8315 ok(!memcmp(privateExponent, rsaPrivKeyPrivateExponent, bitlen/8), 8316 "unexpected privateExponent\n"); 8317 8318 LocalFree(buf); 8319 } 8320 } 8321 8322 /* Free *pInfo with HeapFree */ 8323 static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo) 8324 { 8325 BOOL ret; 8326 DWORD size = 0; 8327 HCRYPTKEY key; 8328 8329 /* This crashes 8330 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, NULL); 8331 */ 8332 ret = CryptExportPublicKeyInfoEx(0, 0, 0, NULL, 0, NULL, NULL, &size); 8333 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 8334 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 8335 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, 0, NULL, 0, NULL, NULL, 8336 &size); 8337 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 8338 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 8339 ret = CryptExportPublicKeyInfoEx(0, 0, X509_ASN_ENCODING, NULL, 0, NULL, 8340 NULL, &size); 8341 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 8342 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 8343 ret = CryptExportPublicKeyInfoEx(0, AT_SIGNATURE, X509_ASN_ENCODING, NULL, 8344 0, NULL, NULL, &size); 8345 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 8346 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 8347 /* Test with no key */ 8348 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, NULL, 8349 0, NULL, NULL, &size); 8350 ok(!ret && GetLastError() == NTE_NO_KEY, "Expected NTE_NO_KEY, got %08x\n", 8351 GetLastError()); 8352 ret = CryptGenKey(csp, AT_SIGNATURE, 0, &key); 8353 ok(ret, "CryptGenKey failed: %08x\n", GetLastError()); 8354 if (ret) 8355 { 8356 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, X509_ASN_ENCODING, 8357 NULL, 0, NULL, NULL, &size); 8358 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", GetLastError()); 8359 *pInfo = HeapAlloc(GetProcessHeap(), 0, size); 8360 if (*pInfo) 8361 { 8362 ret = CryptExportPublicKeyInfoEx(csp, AT_SIGNATURE, 8363 X509_ASN_ENCODING, NULL, 0, NULL, *pInfo, &size); 8364 ok(ret, "CryptExportPublicKeyInfoEx failed: %08x\n", 8365 GetLastError()); 8366 if (ret) 8367 { 8368 /* By default (we passed NULL as the OID) the OID is 8369 * szOID_RSA_RSA. 8370 */ 8371 ok(!strcmp((*pInfo)->Algorithm.pszObjId, szOID_RSA_RSA), 8372 "Expected %s, got %s\n", szOID_RSA_RSA, 8373 (*pInfo)->Algorithm.pszObjId); 8374 } 8375 } 8376 } 8377 CryptDestroyKey(key); 8378 } 8379 8380 static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2, 8381 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, 0x10, 0xc4, 0xd7, 0x7f, 0x0e, 0x6f, 0xa6, 8382 0x8c, 0xaa, 0x47, 0x47, 0x40, 0xe7, 0xb7, 0x0b, 0x4a, 0x7f, 0x30, 0x09, 0x06, 8383 0x05, 0x2b, 0x0e, 0x03, 0x02, 0x1d, 0x05, 0x00, 0x30, 0x1f, 0x31, 0x1d, 0x30, 8384 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40, 8385 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 8386 0x6f, 0x6d, 0x30, 0x1e, 0x17, 0x0d, 0x36, 0x39, 0x30, 0x31, 0x30, 0x31, 0x30, 8387 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x17, 0x0d, 0x37, 0x30, 0x30, 0x31, 0x30, 8388 0x31, 0x30, 0x36, 0x30, 0x30, 0x30, 0x30, 0x5a, 0x30, 0x1f, 0x31, 0x1d, 0x30, 8389 0x1b, 0x06, 0x03, 0x55, 0x04, 0x03, 0x13, 0x14, 0x61, 0x72, 0x69, 0x63, 0x40, 8390 0x63, 0x6f, 0x64, 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 8391 0x6f, 0x6d, 0x30, 0x5c, 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 8392 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00, 0x03, 0x4b, 0x00, 0x30, 0x48, 0x02, 0x41, 8393 0x00, 0xa1, 0xaf, 0x4a, 0xea, 0xa7, 0x83, 0x57, 0xc0, 0x37, 0x33, 0x7e, 0x29, 8394 0x5e, 0x0d, 0xfc, 0x44, 0x74, 0x3a, 0x1d, 0xc3, 0x1b, 0x1d, 0x96, 0xed, 0x4e, 8395 0xf4, 0x1b, 0x98, 0xec, 0x69, 0x1b, 0x04, 0xea, 0x25, 0xcf, 0xb3, 0x2a, 0xf5, 8396 0xd9, 0x22, 0xd9, 0x8d, 0x08, 0x39, 0x81, 0xc6, 0xe0, 0x4f, 0x12, 0x37, 0x2a, 8397 0x3f, 0x80, 0xa6, 0x6c, 0x67, 0x43, 0x3a, 0xdd, 0x95, 0x0c, 0xbb, 0x2f, 0x6b, 8398 0x02, 0x03, 0x01, 0x00, 0x01, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03, 0x02, 8399 0x1d, 0x05, 0x00, 0x03, 0x41, 0x00, 0x8f, 0xa2, 0x5b, 0xd6, 0xdf, 0x34, 0xd0, 8400 0xa2, 0xa7, 0x47, 0xf1, 0x13, 0x79, 0xd3, 0xf3, 0x39, 0xbd, 0x4e, 0x2b, 0xa3, 8401 0xf4, 0x63, 0x37, 0xac, 0x5a, 0x0c, 0x5e, 0x4d, 0x0d, 0x54, 0x87, 0x4f, 0x31, 8402 0xfb, 0xa0, 0xce, 0x8f, 0x9a, 0x2f, 0x4d, 0x48, 0xc6, 0x84, 0x8d, 0xf5, 0x70, 8403 0x74, 0x17, 0xa5, 0xf3, 0x66, 0x47, 0x06, 0xd6, 0x64, 0x45, 0xbc, 0x52, 0xef, 8404 0x49, 0xe5, 0xf9, 0x65, 0xf3 }; 8405 8406 static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info) 8407 { 8408 BOOL ret; 8409 HCRYPTKEY key; 8410 PCCERT_CONTEXT context; 8411 DWORD dwSize; 8412 ALG_ID ai; 8413 8414 /* These crash 8415 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, NULL); 8416 ret = CryptImportPublicKeyInfoEx(0, 0, NULL, 0, 0, NULL, &key); 8417 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, NULL); 8418 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL, 8419 NULL); 8420 */ 8421 ret = CryptImportPublicKeyInfoEx(0, 0, info, 0, 0, NULL, &key); 8422 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 8423 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 8424 ret = CryptImportPublicKeyInfoEx(csp, 0, info, 0, 0, NULL, &key); 8425 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 8426 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 8427 ret = CryptImportPublicKeyInfoEx(0, X509_ASN_ENCODING, info, 0, 0, NULL, 8428 &key); 8429 ok(!ret && GetLastError() == ERROR_INVALID_PARAMETER, 8430 "Expected ERROR_INVALID_PARAMETER, got %08x\n", GetLastError()); 8431 8432 /* Export key with standard algorithm (CALG_RSA_KEYX) */ 8433 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, 0, 0, NULL, 8434 &key); 8435 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError()); 8436 8437 dwSize = sizeof(ai); 8438 ret = CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0); 8439 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError()); 8440 if(ret) 8441 { 8442 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize); 8443 ok(ai == CALG_RSA_KEYX, "Default ALG_ID is %04x (expected CALG_RSA_KEYX)\n", ai); 8444 } 8445 8446 CryptDestroyKey(key); 8447 8448 /* Repeat with forced algorithm */ 8449 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, info, CALG_RSA_SIGN, 0, NULL, 8450 &key); 8451 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError()); 8452 8453 dwSize = sizeof(ai); 8454 ret = CryptGetKeyParam(key, KP_ALGID, (LPVOID)&ai, &dwSize, 0); 8455 ok(ret, "CryptGetKeyParam failed: %08x\n", GetLastError()); 8456 if(ret) 8457 { 8458 ok(dwSize == sizeof(ai), "CryptGetKeyParam returned size %d\n",dwSize); 8459 ok(ai == CALG_RSA_SIGN, "ALG_ID is %04x (expected CALG_RSA_SIGN)\n", ai); 8460 } 8461 8462 CryptDestroyKey(key); 8463 8464 /* Test importing a public key from a certificate context */ 8465 context = CertCreateCertificateContext(X509_ASN_ENCODING, expiredCert, 8466 sizeof(expiredCert)); 8467 ok(context != NULL, "CertCreateCertificateContext failed: %08x\n", 8468 GetLastError()); 8469 if (context) 8470 { 8471 ok(!strcmp(szOID_RSA_RSA, 8472 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId), 8473 "Expected %s, got %s\n", szOID_RSA_RSA, 8474 context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId); 8475 ret = CryptImportPublicKeyInfoEx(csp, X509_ASN_ENCODING, 8476 &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, NULL, &key); 8477 ok(ret, "CryptImportPublicKeyInfoEx failed: %08x\n", GetLastError()); 8478 CryptDestroyKey(key); 8479 CertFreeCertificateContext(context); 8480 } 8481 } 8482 8483 static const char cspName[] = "WineCryptTemp"; 8484 8485 static void testPortPublicKeyInfo(void) 8486 { 8487 HCRYPTPROV csp; 8488 BOOL ret; 8489 PCERT_PUBLIC_KEY_INFO info = NULL; 8490 8491 /* Just in case a previous run failed, delete this thing */ 8492 CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL, 8493 CRYPT_DELETEKEYSET); 8494 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL, 8495 CRYPT_NEWKEYSET); 8496 ok(ret,"CryptAcquireContextA failed\n"); 8497 8498 testExportPublicKey(csp, &info); 8499 testImportPublicKey(csp, info); 8500 8501 HeapFree(GetProcessHeap(), 0, info); 8502 CryptReleaseContext(csp, 0); 8503 ret = CryptAcquireContextA(&csp, cspName, MS_DEF_PROV_A, PROV_RSA_FULL, 8504 CRYPT_DELETEKEYSET); 8505 ok(ret,"CryptAcquireContextA failed\n"); 8506 } 8507 8508 START_TEST(encode) 8509 { 8510 static const DWORD encodings[] = { X509_ASN_ENCODING, PKCS_7_ASN_ENCODING, 8511 X509_ASN_ENCODING | PKCS_7_ASN_ENCODING }; 8512 HMODULE hCrypt32; 8513 DWORD i; 8514 8515 hCrypt32 = GetModuleHandleA("crypt32.dll"); 8516 pCryptDecodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptDecodeObjectEx"); 8517 pCryptEncodeObjectEx = (void*)GetProcAddress(hCrypt32, "CryptEncodeObjectEx"); 8518 if (!pCryptDecodeObjectEx || !pCryptEncodeObjectEx) 8519 { 8520 win_skip("CryptDecodeObjectEx() is not available\n"); 8521 return; 8522 } 8523 8524 for (i = 0; i < ARRAY_SIZE(encodings); i++) 8525 { 8526 test_encodeInt(encodings[i]); 8527 test_decodeInt(encodings[i]); 8528 test_encodeEnumerated(encodings[i]); 8529 test_decodeEnumerated(encodings[i]); 8530 test_encodeFiletime(encodings[i]); 8531 test_decodeFiletime(encodings[i]); 8532 test_encodeName(encodings[i]); 8533 test_decodeName(encodings[i]); 8534 test_encodeUnicodeName(encodings[i]); 8535 test_decodeUnicodeName(encodings[i]); 8536 test_encodeNameValue(encodings[i]); 8537 test_decodeNameValue(encodings[i]); 8538 test_encodeUnicodeNameValue(encodings[i]); 8539 test_decodeUnicodeNameValue(encodings[i]); 8540 test_encodeAltName(encodings[i]); 8541 test_decodeAltName(encodings[i]); 8542 test_encodeOctets(encodings[i]); 8543 test_decodeOctets(encodings[i]); 8544 test_encodeBits(encodings[i]); 8545 test_decodeBits(encodings[i]); 8546 test_encodeBasicConstraints(encodings[i]); 8547 test_decodeBasicConstraints(encodings[i]); 8548 test_encodeRsaPublicKey(encodings[i]); 8549 test_decodeRsaPublicKey(encodings[i]); 8550 test_encodeSequenceOfAny(encodings[i]); 8551 test_decodeSequenceOfAny(encodings[i]); 8552 test_encodeExtensions(encodings[i]); 8553 test_decodeExtensions(encodings[i]); 8554 test_encodePublicKeyInfo(encodings[i]); 8555 test_decodePublicKeyInfo(encodings[i]); 8556 test_encodeCertToBeSigned(encodings[i]); 8557 test_decodeCertToBeSigned(encodings[i]); 8558 test_encodeCert(encodings[i]); 8559 test_decodeCert(encodings[i]); 8560 test_encodeCRLDistPoints(encodings[i]); 8561 test_decodeCRLDistPoints(encodings[i]); 8562 test_encodeCRLIssuingDistPoint(encodings[i]); 8563 test_decodeCRLIssuingDistPoint(encodings[i]); 8564 test_encodeCRLToBeSigned(encodings[i]); 8565 test_decodeCRLToBeSigned(encodings[i]); 8566 test_encodeEnhancedKeyUsage(encodings[i]); 8567 test_decodeEnhancedKeyUsage(encodings[i]); 8568 test_encodeAuthorityKeyId(encodings[i]); 8569 test_decodeAuthorityKeyId(encodings[i]); 8570 test_encodeAuthorityKeyId2(encodings[i]); 8571 test_decodeAuthorityKeyId2(encodings[i]); 8572 test_encodeAuthorityInfoAccess(encodings[i]); 8573 test_decodeAuthorityInfoAccess(encodings[i]); 8574 test_encodeCTL(encodings[i]); 8575 test_decodeCTL(encodings[i]); 8576 test_encodePKCSContentInfo(encodings[i]); 8577 test_decodePKCSContentInfo(encodings[i]); 8578 test_encodePKCSAttribute(encodings[i]); 8579 test_decodePKCSAttribute(encodings[i]); 8580 test_encodePKCSAttributes(encodings[i]); 8581 test_decodePKCSAttributes(encodings[i]); 8582 test_encodePKCSSMimeCapabilities(encodings[i]); 8583 test_decodePKCSSMimeCapabilities(encodings[i]); 8584 test_encodePKCSSignerInfo(encodings[i]); 8585 test_decodePKCSSignerInfo(encodings[i]); 8586 test_encodeCMSSignerInfo(encodings[i]); 8587 test_decodeCMSSignerInfo(encodings[i]); 8588 test_encodeNameConstraints(encodings[i]); 8589 test_decodeNameConstraints(encodings[i]); 8590 test_encodePolicyQualifierUserNotice(encodings[i]); 8591 test_decodePolicyQualifierUserNotice(encodings[i]); 8592 test_encodeCertPolicies(encodings[i]); 8593 test_decodeCertPolicies(encodings[i]); 8594 test_encodeCertPolicyMappings(encodings[i]); 8595 test_decodeCertPolicyMappings(encodings[i]); 8596 test_encodeCertPolicyConstraints(encodings[i]); 8597 test_decodeCertPolicyConstraints(encodings[i]); 8598 test_decodeRsaPrivateKey(encodings[i]); 8599 } 8600 testPortPublicKeyInfo(); 8601 } 8602