static void test_incorrect_api_usage(void) { BOOL result; HCRYPTPROV hProv, hProv2; HCRYPTHASH hHash, hHash2; HCRYPTKEY hKey, hKey2; BYTE temp; DWORD dwLen, dwTemp; /* This is to document incorrect api usage in the * "Uru - Ages beyond Myst Demo" installer as reported by Paul Vriens. * * The installer destroys a hash object after having released the context * with which the hash was created. This is not allowed according to MSDN, * since CryptReleaseContext destroys all hash and key objects belonging to * the respective context. However, while wine used to crash, Windows is more * robust here and returns an ERROR_INVALID_PARAMETER code. */ result = pCryptAcquireContextA(&hProv, szBadKeySet, szRsaBaseProv, PROV_RSA_FULL, CRYPT_NEWKEYSET); ok (result, "%08x\n", GetLastError()); if (!result) return; result = pCryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash); ok (result, "%d\n", GetLastError()); if (!result) return; pCryptDestroyHash(hHash); result = pCryptGenKey(hProv, CALG_RC4, 0, &hKey); ok (result, "%d\n", GetLastError()); if (!result) return; result = pCryptGenKey(hProv, CALG_RC4, 0, &hKey2); ok (result, "%d\n", GetLastError()); if (!result) return; result = pCryptDestroyKey(hKey2); ok (result, "%d\n", GetLastError()); dwTemp = CRYPT_MODE_ECB; result = pCryptSetKeyParam(hKey2, KP_MODE, (BYTE*)&dwTemp, sizeof(DWORD)); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptAcquireContextA(&hProv2, szBadKeySet, NULL, PROV_RSA_FULL, CRYPT_DELETEKEYSET); ok (result, "%d\n", GetLastError()); if (!result) return; result = pCryptReleaseContext(hProv, 0); ok (result, "%d\n", GetLastError()); if (!result) return; result = pCryptReleaseContext(hProv, 0); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptGenRandom(hProv, 1, &temp); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); #ifdef CRASHES_ON_NT40 result = pCryptContextAddRef(hProv, NULL, 0); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); #endif result = pCryptCreateHash(hProv, CALG_SHA, 0, 0, &hHash2); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); dwLen = 1; result = pCryptDecrypt(hKey, 0, TRUE, 0, &temp, &dwLen); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); dwLen = 1; result = pCryptEncrypt(hKey, 0, TRUE, 0, &temp, &dwLen, 1); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptDeriveKey(hProv, CALG_RC4, hHash, 0, &hKey2); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); #ifdef CRASHES_ON_NT40 result = pCryptDuplicateHash(hHash, NULL, 0, &hHash2); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptDuplicateKey(hKey, NULL, 0, &hKey2); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); #endif dwLen = 1; result = pCryptExportKey(hKey, 0, 0, 0, &temp, &dwLen); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptGenKey(hProv, CALG_RC4, 0, &hKey2); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); dwLen = 1; result = pCryptGetHashParam(hHash, 0, &temp, &dwLen, 0); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); dwLen = 1; result = pCryptGetKeyParam(hKey, 0, &temp, &dwLen, 0); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); dwLen = 1; result = pCryptGetProvParam(hProv, 0, &temp, &dwLen, 0); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptGetUserKey(hProv, 0, &hKey2); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptHashData(hHash, &temp, 1, 0); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptHashSessionKey(hHash, hKey, 0); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptImportKey(hProv, &temp, 1, 0, 0, &hKey2); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); if (pCryptSignHashW) { dwLen = 1; result = pCryptSignHashW(hHash, 0, NULL, 0, &temp, &dwLen); ok (!result && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), "%d\n", GetLastError()); } else win_skip("CryptSignHashW is not available\n"); result = pCryptSetKeyParam(hKey, 0, &temp, 1); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptSetHashParam(hHash, 0, &temp, 1); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptSetProvParam(hProv, 0, &temp, 1); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); if (pCryptVerifySignatureW) { result = pCryptVerifySignatureW(hHash, &temp, 1, hKey, NULL, 0); ok (!result && (GetLastError() == ERROR_INVALID_PARAMETER || GetLastError() == ERROR_CALL_NOT_IMPLEMENTED), "%d\n", GetLastError()); } else win_skip("CryptVerifySignatureW is not available\n"); result = pCryptDestroyHash(hHash); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); result = pCryptDestroyKey(hKey); ok (!result && GetLastError() == ERROR_INVALID_PARAMETER, "%d\n", GetLastError()); }
/* メッセージの復号化 */ BOOL TRecvDlg::DecryptMsg() { HCRYPTKEY hKey=0, hExKey=0; char *capa_hex, *skey_hex, *msg_hex, *p; BYTE skey[MAX_BUF]; int len, msgLen; HCRYPTPROV target_csp; if ((capa_hex = separate_token(msg.msgBuf, ':', &p)) == NULL) return FALSE; cryptCapa = strtoul(capa_hex, 0, 16); target_csp = (cryptCapa & IPMSG_RSA_1024) && cfg->pubKey.Key() ? cfg->hCsp : cfg->hSmallCsp; hExKey = target_csp == cfg->hCsp ? cfg->hPrivKey : cfg->hSmallPrivKey; if ((skey_hex = separate_token(NULL, ':', &p)) == NULL) return FALSE; if ((msg_hex = separate_token(NULL, 0, &p)) == NULL) return FALSE; if (cryptCapa & IPMSG_BLOWFISH_128) { // blowfish hexstr2bin_bigendian(skey_hex, skey, sizeof(skey), &len); // 公開鍵取得 if (!pCryptDecrypt(hExKey, 0, TRUE, 0, (BYTE *)skey, (DWORD *)&len)) return wsprintf(msg.msgBuf, "CryptDecrypt Err(%X)", GetLastError()), FALSE; CBlowFish bl(skey, len); hexstr2bin(msg_hex, (BYTE *)msg.msgBuf, sizeof(msg.msgBuf), &msgLen); bl.Decrypt((BYTE *)msg.msgBuf, (BYTE *)msg.msgBuf, msgLen); } else { // RC2 // Skey Blob を作る skey[0] = SIMPLEBLOB; skey[1] = CUR_BLOB_VERSION; *(WORD *)(skey + 2) = 0; *(ALG_ID *)(skey + 4) = CALG_RC2; *(ALG_ID *)(skey + 8) = CALG_RSA_KEYX; hexstr2bin_bigendian(skey_hex, skey + SKEY_HEADER_SIZE, sizeof(skey) - SKEY_HEADER_SIZE, &len); // セッションキーの import if (!pCryptImportKey(target_csp, skey, len + SKEY_HEADER_SIZE, hExKey, 0, &hKey)) return wsprintf(msg.msgBuf, "CryptImportKey Err(%X)", GetLastError()), FALSE; // メッセージの Decrypt hexstr2bin(msg_hex, (BYTE *)msg.msgBuf, sizeof(msg.msgBuf), &msgLen); if (!pCryptDecrypt(hKey, 0, TRUE, 0, (BYTE *)msg.msgBuf, (DWORD *)&msgLen)) return wsprintf(msg.msgBuf, "CryptDecrypt Err(%X)", GetLastError()), FALSE; pCryptDestroyKey(hKey); } // UNIX 形式の改行を変換 if (cryptCapa & (IPMSG_BLOWFISH_128|IPMSG_RC2_40)) MsgMng::UnixNewLineToLocal(msg.msgBuf, msg.msgBuf, sizeof(msg.msgBuf)); if ((msg.command & IPMSG_UTF8OPT) == 0) { char *u8buf = AtoU8(msg.msgBuf); int u8len = strlen(u8buf), diff=0; u8len = min(u8len, MAX_UDPBUF-1); int dif = u8len - strlen(msg.msgBuf); if (msg.exOffset && diff > 0) { memmove(msg.msgBuf + msg.exOffset + diff, msg.msgBuf + msg.exOffset, diff); } strncpyz(msg.msgBuf, u8buf, u8len+1); } return TRUE; }