1 /* 2 * Unit test suite for crypt32.dll's OID support functions. 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 #define CRYPT_OID_INFO_HAS_EXTRA_FIELDS 26 #include <wincrypt.h> 27 #include <winreg.h> 28 29 #include "wine/test.h" 30 31 32 static BOOL (WINAPI *pCryptEnumOIDInfo)(DWORD,DWORD,void*,PFN_CRYPT_ENUM_OID_INFO); 33 34 35 struct OIDToAlgID 36 { 37 LPCSTR oid; 38 LPCSTR altOid; 39 DWORD algID; 40 DWORD altAlgID; 41 }; 42 43 static const struct OIDToAlgID oidToAlgID[] = { 44 { szOID_RSA_RSA, NULL, CALG_RSA_KEYX }, 45 { szOID_RSA_MD2RSA, NULL, CALG_MD2 }, 46 { szOID_RSA_MD4RSA, NULL, CALG_MD4 }, 47 { szOID_RSA_MD5RSA, NULL, CALG_MD5 }, 48 { szOID_RSA_SHA1RSA, NULL, CALG_SHA }, 49 { szOID_RSA_DH, NULL, CALG_DH_SF }, 50 { szOID_RSA_SMIMEalgESDH, NULL, CALG_DH_EPHEM }, 51 { szOID_RSA_SMIMEalgCMS3DESwrap, NULL, CALG_3DES }, 52 { szOID_RSA_SMIMEalgCMSRC2wrap, NULL, CALG_RC2 }, 53 { szOID_RSA_MD2, NULL, CALG_MD2 }, 54 { szOID_RSA_MD4, NULL, CALG_MD4 }, 55 { szOID_RSA_MD5, NULL, CALG_MD5 }, 56 { szOID_RSA_RC2CBC, NULL, CALG_RC2 }, 57 { szOID_RSA_RC4, NULL, CALG_RC4 }, 58 { szOID_RSA_DES_EDE3_CBC, NULL, CALG_3DES }, 59 { szOID_ANSI_X942_DH, NULL, CALG_DH_SF }, 60 { szOID_X957_DSA, NULL, CALG_DSS_SIGN }, 61 { szOID_X957_SHA1DSA, NULL, CALG_SHA }, 62 { szOID_OIWSEC_md4RSA, NULL, CALG_MD4 }, 63 { szOID_OIWSEC_md5RSA, NULL, CALG_MD5 }, 64 { szOID_OIWSEC_md4RSA2, NULL, CALG_MD4 }, 65 { szOID_OIWSEC_desCBC, NULL, CALG_DES }, 66 { szOID_OIWSEC_dsa, NULL, CALG_DSS_SIGN }, 67 { szOID_OIWSEC_shaDSA, NULL, CALG_SHA }, 68 { szOID_OIWSEC_shaRSA, NULL, CALG_SHA }, 69 { szOID_OIWSEC_sha, NULL, CALG_SHA }, 70 { szOID_OIWSEC_rsaXchg, NULL, CALG_RSA_KEYX }, 71 { szOID_OIWSEC_sha1, NULL, CALG_SHA }, 72 { szOID_OIWSEC_dsaSHA1, NULL, CALG_SHA }, 73 { szOID_OIWSEC_sha1RSASign, NULL, CALG_SHA }, 74 { szOID_OIWDIR_md2RSA, NULL, CALG_MD2 }, 75 { szOID_INFOSEC_mosaicUpdatedSig, NULL, CALG_SHA }, 76 { szOID_INFOSEC_mosaicKMandUpdSig, NULL, CALG_DSS_SIGN }, 77 { szOID_NIST_sha256, NULL, CALG_SHA_256, -1 }, 78 { szOID_NIST_sha384, NULL, CALG_SHA_384, -1 }, 79 { szOID_NIST_sha512, NULL, CALG_SHA_512, -1 } 80 }; 81 82 static const struct OIDToAlgID algIDToOID[] = { 83 { szOID_RSA_RSA, NULL, CALG_RSA_KEYX }, 84 { szOID_RSA_SMIMEalgESDH, NULL, CALG_DH_EPHEM }, 85 { szOID_RSA_MD2, NULL, CALG_MD2 }, 86 { szOID_RSA_MD4, NULL, CALG_MD4 }, 87 { szOID_RSA_MD5, NULL, CALG_MD5 }, 88 { szOID_RSA_RC2CBC, NULL, CALG_RC2 }, 89 { szOID_RSA_RC4, NULL, CALG_RC4 }, 90 { szOID_RSA_DES_EDE3_CBC, NULL, CALG_3DES }, 91 { szOID_ANSI_X942_DH, NULL, CALG_DH_SF }, 92 { szOID_X957_DSA, szOID_OIWSEC_dsa /* some Win98 */, CALG_DSS_SIGN }, 93 { szOID_OIWSEC_desCBC, NULL, CALG_DES }, 94 { szOID_OIWSEC_sha1, NULL, CALG_SHA }, 95 }; 96 97 static const WCHAR bogusDll[] = { 'b','o','g','u','s','.','d','l','l',0 }; 98 static const WCHAR bogus2Dll[] = { 'b','o','g','u','s','2','.','d','l','l',0 }; 99 100 static void testOIDToAlgID(void) 101 { 102 int i; 103 DWORD alg; 104 105 /* Test with a bogus one */ 106 alg = CertOIDToAlgId("1.2.3"); 107 ok(!alg, "Expected failure, got %d\n", alg); 108 109 for (i = 0; i < ARRAY_SIZE(oidToAlgID); i++) 110 { 111 alg = CertOIDToAlgId(oidToAlgID[i].oid); 112 ok(alg == oidToAlgID[i].algID || (oidToAlgID[i].altAlgID && alg == oidToAlgID[i].altAlgID), 113 "Expected %d, got %d\n", oidToAlgID[i].algID, alg); 114 } 115 } 116 117 static void testAlgIDToOID(void) 118 { 119 int i; 120 LPCSTR oid; 121 122 /* Test with a bogus one */ 123 SetLastError(0xdeadbeef); 124 oid = CertAlgIdToOID(ALG_CLASS_SIGNATURE | ALG_TYPE_ANY | 80); 125 ok(!oid && GetLastError() == 0xdeadbeef, 126 "Didn't expect last error (%08x) to be set\n", GetLastError()); 127 for (i = 0; i < ARRAY_SIZE(algIDToOID); i++) 128 { 129 oid = CertAlgIdToOID(algIDToOID[i].algID); 130 /* Allow failure, not every version of Windows supports every algo */ 131 ok(oid != NULL || broken(!oid), "CertAlgIdToOID failed, expected %s\n", algIDToOID[i].oid); 132 if (oid) 133 { 134 if (strcmp(oid, algIDToOID[i].oid)) 135 { 136 if (algIDToOID[i].altOid) 137 ok(!strcmp(oid, algIDToOID[i].altOid), 138 "Expected %s or %s, got %s\n", algIDToOID[i].oid, 139 algIDToOID[i].altOid, oid); 140 else 141 { 142 /* No need to rerun the test, we already know it failed. */ 143 ok(0, "Expected %s, got %s\n", algIDToOID[i].oid, oid); 144 } 145 } 146 else 147 { 148 /* No need to rerun the test, we already know it succeeded. */ 149 ok(1, "Expected %s, got %s\n", algIDToOID[i].oid, oid); 150 } 151 } 152 } 153 } 154 155 static void test_oidFunctionSet(void) 156 { 157 HCRYPTOIDFUNCSET set1, set2; 158 BOOL ret; 159 LPWSTR buf = NULL; 160 DWORD size; 161 162 /* This crashes 163 set = CryptInitOIDFunctionSet(NULL, 0); 164 */ 165 166 /* The name doesn't mean much */ 167 set1 = CryptInitOIDFunctionSet("funky", 0); 168 ok(set1 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError()); 169 if (set1) 170 { 171 /* These crash 172 ret = CryptGetDefaultOIDDllList(NULL, 0, NULL, NULL); 173 ret = CryptGetDefaultOIDDllList(NULL, 0, NULL, &size); 174 */ 175 size = 0; 176 ret = CryptGetDefaultOIDDllList(set1, 0, NULL, &size); 177 ok(ret, "CryptGetDefaultOIDDllList failed: %08x\n", GetLastError()); 178 if (ret) 179 { 180 buf = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); 181 if (buf) 182 { 183 ret = CryptGetDefaultOIDDllList(set1, 0, buf, &size); 184 ok(ret, "CryptGetDefaultOIDDllList failed: %08x\n", 185 GetLastError()); 186 ok(!*buf, "Expected empty DLL list\n"); 187 HeapFree(GetProcessHeap(), 0, buf); 188 } 189 } 190 } 191 192 /* MSDN says flags must be 0, but it's not checked */ 193 set1 = CryptInitOIDFunctionSet("", 1); 194 ok(set1 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError()); 195 set2 = CryptInitOIDFunctionSet("", 0); 196 ok(set2 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError()); 197 /* There isn't a free function, so there must be only one set per name to 198 * limit leaks. (I guess the sets are freed when crypt32 is unloaded.) 199 */ 200 ok(set1 == set2, "Expected identical sets\n"); 201 if (set1) 202 { 203 /* The empty name function set used here seems to correspond to 204 * DEFAULT. 205 */ 206 } 207 208 /* There's no installed function for a built-in encoding. */ 209 set1 = CryptInitOIDFunctionSet("CryptDllEncodeObject", 0); 210 ok(set1 != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError()); 211 if (set1) 212 { 213 void *funcAddr; 214 HCRYPTOIDFUNCADDR hFuncAddr; 215 216 ret = CryptGetOIDFunctionAddress(set1, X509_ASN_ENCODING, X509_CERT, 0, 217 &funcAddr, &hFuncAddr); 218 ok((!ret && GetLastError() == ERROR_FILE_NOT_FOUND) || 219 broken(ret) /* some Win98 */, 220 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 221 } 222 } 223 224 typedef int (*funcY)(int); 225 226 static int funky(int x) 227 { 228 return x; 229 } 230 231 static void test_installOIDFunctionAddress(void) 232 { 233 BOOL ret; 234 CRYPT_OID_FUNC_ENTRY entry = { CRYPT_DEFAULT_OID, funky }; 235 HCRYPTOIDFUNCSET set; 236 237 /* This crashes 238 ret = CryptInstallOIDFunctionAddress(NULL, 0, NULL, 0, NULL, 0); 239 */ 240 241 /* Installing zero functions should work */ 242 SetLastError(0xdeadbeef); 243 ret = CryptInstallOIDFunctionAddress(NULL, 0, "CryptDllEncodeObject", 0, 244 NULL, 0); 245 ok(ret && GetLastError() == 0xdeadbeef, "Expected success, got %08x\n", 246 GetLastError()); 247 248 /* The function name doesn't much matter */ 249 SetLastError(0xdeadbeef); 250 ret = CryptInstallOIDFunctionAddress(NULL, 0, "OhSoFunky", 0, NULL, 0); 251 ok(ret && GetLastError() == 0xdeadbeef, "Expected success, got %08x\n", 252 GetLastError()); 253 SetLastError(0xdeadbeef); 254 entry.pszOID = X509_CERT; 255 ret = CryptInstallOIDFunctionAddress(NULL, 0, "OhSoFunky", 1, &entry, 0); 256 ok(ret && GetLastError() == 0xdeadbeef, "Expected success, got %08x\n", 257 GetLastError()); 258 set = CryptInitOIDFunctionSet("OhSoFunky", 0); 259 ok(set != 0, "CryptInitOIDFunctionSet failed: %08x\n", GetLastError()); 260 if (set) 261 { 262 funcY funcAddr = NULL; 263 HCRYPTOIDFUNCADDR hFuncAddr = NULL; 264 265 /* This crashes 266 ret = CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, 0, 0, NULL, 267 NULL); 268 */ 269 ret = CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, 0, 0, 270 (void **)&funcAddr, &hFuncAddr); 271 ok(!ret && (GetLastError() == ERROR_FILE_NOT_FOUND || 272 GetLastError() == E_INVALIDARG /* some Win98 */), 273 "Expected ERROR_FILE_NOT_FOUND or E_INVALIDARG, got %d\n", 274 GetLastError()); 275 ret = CryptGetOIDFunctionAddress(set, X509_ASN_ENCODING, X509_CERT, 0, 276 (void **)&funcAddr, &hFuncAddr); 277 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 278 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); 279 ret = CryptGetOIDFunctionAddress(set, 0, X509_CERT, 0, 280 (void **)&funcAddr, &hFuncAddr); 281 ok(ret, "CryptGetOIDFunctionAddress failed: %d\n", GetLastError()); 282 if (funcAddr) 283 { 284 int y = funcAddr(0xabadc0da); 285 286 ok(y == 0xabadc0da, "Unexpected return (%d) from function\n", y); 287 CryptFreeOIDFunctionAddress(hFuncAddr, 0); 288 } 289 } 290 } 291 292 static void test_registerOIDFunction(void) 293 { 294 BOOL ret; 295 296 /* oddly, this succeeds under WinXP; the function name key is merely 297 * omitted. This may be a side effect of the registry code, I don't know. 298 * I don't check it because I doubt anyone would depend on it. 299 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, NULL, 300 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL); 301 */ 302 /* On windows XP, GetLastError is incorrectly being set with an HRESULT, 303 * E_INVALIDARG 304 */ 305 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo", NULL, bogusDll, 306 NULL); 307 ok(!ret && GetLastError() == E_INVALIDARG, 308 "Expected E_INVALIDARG: %d\n", GetLastError()); 309 /* This has no effect, but "succeeds" on XP */ 310 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "foo", 311 "1.2.3.4.5.6.7.8.9.10", NULL, NULL); 312 ok(ret, "Expected pseudo-success, got %d\n", GetLastError()); 313 SetLastError(0xdeadbeef); 314 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject", 315 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL); 316 if (!ret && GetLastError() == ERROR_ACCESS_DENIED) 317 { 318 skip("Need admin rights\n"); 319 return; 320 } 321 ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError()); 322 ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "CryptDllEncodeObject", 323 "1.2.3.4.5.6.7.8.9.10"); 324 ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError()); 325 ret = CryptRegisterOIDFunction(X509_ASN_ENCODING, "bogus", 326 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL); 327 ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError()); 328 ret = CryptUnregisterOIDFunction(X509_ASN_ENCODING, "bogus", 329 "1.2.3.4.5.6.7.8.9.10"); 330 ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError()); 331 /* Unwanted Cryptography\OID\EncodingType 1\bogus\ will still be there */ 332 ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, 333 "SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 1\\bogus"), 334 "Could not delete bogus key\n"); 335 /* Shouldn't have effect but registry keys are created */ 336 ret = CryptRegisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject", 337 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL); 338 ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError()); 339 ret = CryptUnregisterOIDFunction(PKCS_7_ASN_ENCODING, "CryptDllEncodeObject", 340 "1.2.3.4.5.6.7.8.9.10"); 341 ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError()); 342 /* Check with bogus encoding type. Registry keys are still created */ 343 ret = CryptRegisterOIDFunction(0, "CryptDllEncodeObject", 344 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL); 345 ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError()); 346 ret = CryptUnregisterOIDFunction(0, "CryptDllEncodeObject", 347 "1.2.3.4.5.6.7.8.9.10"); 348 ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError()); 349 /* Unwanted Cryptography\OID\EncodingType 0\CryptDllEncodeObject\ 350 * will still be there 351 */ 352 ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, 353 "SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 0\\CryptDllEncodeObject"), 354 "Could not delete CryptDllEncodeObject key\n"); 355 /* This is written with value 3 verbatim. Thus, the encoding type isn't 356 * (for now) treated as a mask. Registry keys are created. 357 */ 358 ret = CryptRegisterOIDFunction(3, "CryptDllEncodeObject", 359 "1.2.3.4.5.6.7.8.9.10", bogusDll, NULL); 360 ok(ret, "CryptRegisterOIDFunction failed: %d\n", GetLastError()); 361 ret = CryptUnregisterOIDFunction(3, "CryptDllEncodeObject", 362 "1.2.3.4.5.6.7.8.9.10"); 363 ok(ret, "CryptUnregisterOIDFunction failed: %d\n", GetLastError()); 364 /* Unwanted Cryptography\OID\EncodingType 3\CryptDllEncodeObject 365 * will still be there. 366 */ 367 ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, 368 "SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 3\\CryptDllEncodeObject"), 369 "Could not delete CryptDllEncodeObject key\n"); 370 ok(!RegDeleteKeyA(HKEY_LOCAL_MACHINE, 371 "SOFTWARE\\Microsoft\\Cryptography\\OID\\EncodingType 3"), 372 "Could not delete 'EncodingType 3' key\n"); 373 } 374 375 static void test_registerDefaultOIDFunction(void) 376 { 377 static const char fmt[] = 378 "Software\\Microsoft\\Cryptography\\OID\\EncodingType %d\\%s\\DEFAULT"; 379 static const char func[] = "CertDllOpenStoreProv"; 380 char buf[MAX_PATH]; 381 BOOL ret; 382 LSTATUS rc; 383 HKEY key; 384 385 ret = CryptRegisterDefaultOIDFunction(0, NULL, 0, NULL); 386 ok(!ret && GetLastError() == E_INVALIDARG, 387 "Expected E_INVALIDARG, got %08x\n", GetLastError()); 388 /* This succeeds on WinXP, although the bogus entry is unusable. 389 ret = CryptRegisterDefaultOIDFunction(0, NULL, 0, bogusDll); 390 */ 391 /* Register one at index 0 */ 392 SetLastError(0xdeadbeef); 393 ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 0, 394 bogusDll); 395 if (!ret && GetLastError() == ERROR_ACCESS_DENIED) 396 { 397 skip("Need admin rights\n"); 398 return; 399 } 400 ok(ret, "CryptRegisterDefaultOIDFunction failed: %08x\n", GetLastError()); 401 /* Reregistering should fail */ 402 ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 0, 403 bogusDll); 404 ok(!ret && GetLastError() == ERROR_FILE_EXISTS, 405 "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError()); 406 /* Registering the same one at index 1 should also fail */ 407 ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 1, 408 bogusDll); 409 ok(!ret && GetLastError() == ERROR_FILE_EXISTS, 410 "Expected ERROR_FILE_EXISTS, got %08x\n", GetLastError()); 411 /* Registering a different one at index 1 succeeds */ 412 ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 1, 413 bogus2Dll); 414 ok(ret, "CryptRegisterDefaultOIDFunction failed: %08x\n", GetLastError()); 415 sprintf(buf, fmt, 0, func); 416 rc = RegOpenKeyA(HKEY_LOCAL_MACHINE, buf, &key); 417 ok(rc == 0, "Expected key to exist, RegOpenKeyA failed: %d\n", rc); 418 if (rc == 0) 419 { 420 static const CHAR dllA[] = "Dll"; 421 static const CHAR bogusDll_A[] = "bogus.dll"; 422 static const CHAR bogus2Dll_A[] = "bogus2.dll"; 423 CHAR dllBuf[MAX_PATH]; 424 DWORD type, size; 425 LPSTR ptr; 426 427 size = ARRAY_SIZE(dllBuf); 428 rc = RegQueryValueExA(key, dllA, NULL, &type, (LPBYTE)dllBuf, &size); 429 ok(rc == 0, 430 "Expected Dll value to exist, RegQueryValueExA failed: %d\n", rc); 431 ok(type == REG_MULTI_SZ, "Expected type REG_MULTI_SZ, got %d\n", type); 432 /* bogusDll was registered first, so that should be first */ 433 ptr = dllBuf; 434 ok(!lstrcmpiA(ptr, bogusDll_A), "Unexpected dll\n"); 435 ptr += lstrlenA(ptr) + 1; 436 ok(!lstrcmpiA(ptr, bogus2Dll_A), "Unexpected dll\n"); 437 RegCloseKey(key); 438 } 439 /* Unregister both of them */ 440 ret = CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 441 bogusDll); 442 ok(ret, "CryptUnregisterDefaultOIDFunction failed: %08x\n", 443 GetLastError()); 444 ret = CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 445 bogus2Dll); 446 ok(ret, "CryptUnregisterDefaultOIDFunction failed: %08x\n", 447 GetLastError()); 448 /* Now that they're both unregistered, unregistering should fail */ 449 ret = CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 450 bogusDll); 451 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 452 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); 453 454 /* Repeat a few tests on the normal encoding type */ 455 ret = CryptRegisterDefaultOIDFunction(X509_ASN_ENCODING, 456 "CertDllOpenStoreProv", 0, bogusDll); 457 ok(ret, "CryptRegisterDefaultOIDFunction failed\n"); 458 ret = CryptUnregisterDefaultOIDFunction(X509_ASN_ENCODING, 459 "CertDllOpenStoreProv", bogusDll); 460 ok(ret, "CryptUnregisterDefaultOIDFunction failed\n"); 461 ret = CryptUnregisterDefaultOIDFunction(X509_ASN_ENCODING, 462 "CertDllOpenStoreProv", bogusDll); 463 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 464 "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); 465 } 466 467 static void test_getDefaultOIDFunctionAddress(void) 468 { 469 BOOL ret; 470 HCRYPTOIDFUNCSET set; 471 void *funcAddr; 472 HCRYPTOIDFUNCADDR hFuncAddr; 473 474 /* Crash 475 ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, NULL, NULL); 476 ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, &funcAddr, NULL); 477 ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, NULL, &hFuncAddr); 478 ret = CryptGetDefaultOIDFunctionAddress(0, 0, NULL, 0, &funcAddr, 479 &hFuncAddr); 480 */ 481 set = CryptInitOIDFunctionSet("CertDllOpenStoreProv", 0); 482 ok(set != 0, "CryptInitOIDFunctionSet failed: %d\n", GetLastError()); 483 /* This crashes if hFuncAddr is not 0 to begin with */ 484 hFuncAddr = 0; 485 ret = CryptGetDefaultOIDFunctionAddress(set, 0, NULL, 0, &funcAddr, 486 &hFuncAddr); 487 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 488 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); 489 /* This fails with the normal encoding too, so built-in functions aren't 490 * returned. 491 */ 492 ret = CryptGetDefaultOIDFunctionAddress(set, X509_ASN_ENCODING, NULL, 0, 493 &funcAddr, &hFuncAddr); 494 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 495 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); 496 497 /* Even with a registered dll, this fails (since the dll doesn't exist) */ 498 SetLastError(0xdeadbeef); 499 ret = CryptRegisterDefaultOIDFunction(0, "CertDllOpenStoreProv", 0, 500 bogusDll); 501 if (!ret && GetLastError() == ERROR_ACCESS_DENIED) 502 skip("Need admin rights\n"); 503 else 504 ok(ret, "CryptRegisterDefaultOIDFunction failed: %08x\n", GetLastError()); 505 ret = CryptGetDefaultOIDFunctionAddress(set, 0, NULL, 0, &funcAddr, 506 &hFuncAddr); 507 ok(!ret && GetLastError() == ERROR_FILE_NOT_FOUND, 508 "Expected ERROR_FILE_NOT_FOUND, got %d\n", GetLastError()); 509 CryptUnregisterDefaultOIDFunction(0, "CertDllOpenStoreProv", bogusDll); 510 } 511 512 static BOOL WINAPI countOidInfo(PCCRYPT_OID_INFO pInfo, void *pvArg) 513 { 514 (*(DWORD *)pvArg)++; 515 return TRUE; 516 } 517 518 static BOOL WINAPI noOidInfo(PCCRYPT_OID_INFO pInfo, void *pvArg) 519 { 520 return FALSE; 521 } 522 523 static void test_enumOIDInfo(void) 524 { 525 BOOL ret; 526 DWORD count = 0; 527 528 if (!pCryptEnumOIDInfo) 529 { 530 win_skip("CryptEnumOIDInfo() is not available\n"); 531 return; 532 } 533 534 /* This crashes 535 ret = pCryptEnumOIDInfo(7, 0, NULL, NULL); 536 */ 537 538 /* Silly tests, check that more than one thing is enumerated */ 539 ret = pCryptEnumOIDInfo(0, 0, &count, countOidInfo); 540 ok(ret && count > 0, "Expected more than item enumerated\n"); 541 ret = pCryptEnumOIDInfo(0, 0, NULL, noOidInfo); 542 ok(!ret, "Expected FALSE\n"); 543 } 544 545 static void test_findOIDInfo(void) 546 { 547 static WCHAR sha256ECDSA[] = { 's','h','a','2','5','6','E','C','D','S','A',0 }; 548 static WCHAR sha1[] = { 's','h','a','1',0 }; 549 static CHAR oid_rsa_md5[] = szOID_RSA_MD5, oid_sha256[] = szOID_NIST_sha256; 550 static CHAR oid_ecdsa_sha256[] = szOID_ECDSA_SHA256; 551 ALG_ID alg = CALG_SHA1; 552 ALG_ID algs[2] = { CALG_MD5, CALG_RSA_SIGN }; 553 const struct oid_info 554 { 555 DWORD key_type; 556 void *key; 557 const char *oid; 558 ALG_ID algid; 559 ALG_ID broken_algid; 560 } oid_test_info [] = 561 { 562 { CRYPT_OID_INFO_OID_KEY, oid_rsa_md5, szOID_RSA_MD5, CALG_MD5 }, 563 { CRYPT_OID_INFO_NAME_KEY, sha1, szOID_OIWSEC_sha1, CALG_SHA1 }, 564 { CRYPT_OID_INFO_ALGID_KEY, &alg, szOID_OIWSEC_sha1, CALG_SHA1 }, 565 { CRYPT_OID_INFO_SIGN_KEY, algs, szOID_RSA_MD5RSA, CALG_MD5 }, 566 { CRYPT_OID_INFO_OID_KEY, oid_sha256, szOID_NIST_sha256, CALG_SHA_256, -1 }, 567 }; 568 PCCRYPT_OID_INFO info; 569 int i; 570 571 info = CryptFindOIDInfo(0, NULL, 0); 572 ok(info == NULL, "Expected NULL\n"); 573 574 for (i = 0; i < ARRAY_SIZE(oid_test_info); i++) 575 { 576 const struct oid_info *test = &oid_test_info[i]; 577 578 info = CryptFindOIDInfo(test->key_type, test->key, 0); 579 ok(info != NULL, "Failed to find %s.\n", test->oid); 580 if (info) 581 { 582 ok(!strcmp(info->pszOID, test->oid), "Unexpected OID %s, expected %s\n", info->pszOID, test->oid); 583 ok(U(*info).Algid == test->algid || broken(U(*info).Algid == test->broken_algid), 584 "Unexpected Algid %d, expected %d\n", U(*info).Algid, test->algid); 585 } 586 } 587 588 info = CryptFindOIDInfo(CRYPT_OID_INFO_OID_KEY, oid_ecdsa_sha256, 0); 589 if (info) 590 { 591 DWORD *data; 592 593 ok(info->cbSize == sizeof(*info), "Unexpected structure size %d.\n", info->cbSize); 594 ok(!strcmp(info->pszOID, oid_ecdsa_sha256), "Expected %s, got %s\n", oid_ecdsa_sha256, info->pszOID); 595 ok(!lstrcmpW(info->pwszName, sha256ECDSA), "Expected %s, got %s\n", 596 wine_dbgstr_w(sha256ECDSA), wine_dbgstr_w(info->pwszName)); 597 ok(info->dwGroupId == CRYPT_SIGN_ALG_OID_GROUP_ID, 598 "Expected CRYPT_SIGN_ALG_OID_GROUP_ID, got %u\n", info->dwGroupId); 599 ok(U(*info).Algid == CALG_OID_INFO_CNG_ONLY, 600 "Expected CALG_OID_INFO_CNG_ONLY, got %d\n", U(*info).Algid); 601 602 data = (DWORD *)info->ExtraInfo.pbData; 603 ok(info->ExtraInfo.cbData == 8, "Expected 8, got %d\n", info->ExtraInfo.cbData); 604 ok(data[0] == CALG_OID_INFO_PARAMETERS, "Expected CALG_OID_INFO_PARAMETERS, got %x\n", data[0]); 605 ok(data[1] == CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG, 606 "Expected CRYPT_OID_NO_NULL_ALGORITHM_PARA_FLAG, got %x\n", data[1]); 607 608 ok(!lstrcmpW(info->pwszCNGAlgid, BCRYPT_SHA256_ALGORITHM), "Expected %s, got %s\n", 609 wine_dbgstr_w(BCRYPT_SHA256_ALGORITHM), wine_dbgstr_w(info->pwszCNGAlgid)); 610 ok(!lstrcmpW(info->pwszCNGExtraAlgid, CRYPT_OID_INFO_ECC_PARAMETERS_ALGORITHM), "Expected %s, got %s\n", 611 wine_dbgstr_w(CRYPT_OID_INFO_ECC_PARAMETERS_ALGORITHM), wine_dbgstr_w(info->pwszCNGExtraAlgid)); 612 } 613 else 614 win_skip("Host does not support ECDSA_SHA256, skipping test\n"); 615 } 616 617 START_TEST(oid) 618 { 619 HMODULE hCrypt32 = GetModuleHandleA("crypt32.dll"); 620 pCryptEnumOIDInfo = (void*)GetProcAddress(hCrypt32, "CryptEnumOIDInfo"); 621 622 testOIDToAlgID(); 623 testAlgIDToOID(); 624 test_enumOIDInfo(); 625 test_findOIDInfo(); 626 test_oidFunctionSet(); 627 test_installOIDFunctionAddress(); 628 test_registerOIDFunction(); 629 test_registerDefaultOIDFunction(); 630 test_getDefaultOIDFunctionAddress(); 631 } 632