#include #include #include #include #include #include "fold/detect/weak_crypto.hpp" #include "fold/report/finding.hpp" namespace { std::unique_ptr parse(const std::string& code) { return clang::tooling::buildASTFromCodeWithArgs(code, {"-std=c++20"}, "input.cpp"); } } // namespace TEST_CASE("weak-crypto: CommonCrypto MD5 is flagged", "[weak-crypto][commoncrypto]") { auto unit = parse(R"( extern "C" unsigned char *CC_MD5(const void *, unsigned long, unsigned char *); int caller(const void *p, unsigned char *out) { return CC_MD5(p, 4, out) != nullptr; } )"); REQUIRE(unit); auto findings = fold::detectWeakCryptoInContext(unit->getASTContext()); REQUIRE(findings.size() == 1); REQUIRE(findings[0].kind == fold::FindingKind::WeakCrypto); REQUIRE(findings[0].message.find("MD5") != std::string::npos); } TEST_CASE("weak-crypto: AES ECB EVP helper is flagged", "[weak-crypto][ecb]") { auto unit = parse(R"( extern "C" const void *EVP_aes_256_ecb(); const void *caller() { return EVP_aes_256_ecb(); } )"); REQUIRE(unit); auto findings = fold::detectWeakCryptoInContext(unit->getASTContext()); REQUIRE(findings.size() == 1); REQUIRE(findings[0].message.find("ECB") != std::string::npos); } TEST_CASE("weak-crypto: weak digest string lookup is flagged", "[weak-crypto][string-lookup]") { auto unit = parse(R"( extern "C" const void *EVP_get_digestbyname(const char *); const void *caller() { return EVP_get_digestbyname("sha1"); } )"); REQUIRE(unit); auto findings = fold::detectWeakCryptoInContext(unit->getASTContext()); REQUIRE(findings.size() == 1); REQUIRE(findings[0].message.find("SHA-1") != std::string::npos); REQUIRE(findings[0].message.find("EVP_get_digestbyname") != std::string::npos); } TEST_CASE("weak-crypto: strong digest string lookup is not flagged", "[weak-crypto][string-lookup][negative]") { auto unit = parse(R"( extern "C" const void *EVP_get_digestbyname(const char *); const void *caller() { return EVP_get_digestbyname("sha256"); } )"); REQUIRE(unit); auto findings = fold::detectWeakCryptoInContext(unit->getASTContext()); REQUIRE(findings.empty()); }