fix(Crypto): Prevent stdin password prompt when loading protected key (#4627) (#5128)

This commit is contained in:
Matej Kenda
2025-12-18 17:25:30 +01:00
committed by GitHub
parent 8410eb1a6f
commit 5bbd542b6b
3 changed files with 59 additions and 7 deletions

View File

@@ -230,8 +230,8 @@ private:
if (pFile)
{
pem_password_cb* pCB = pass.empty() ? (pem_password_cb*)nullptr : &passCB;
void* pPassword = pass.empty() ? (void*)nullptr : (void*)pass.c_str();
pem_password_cb* pCB = &passCB;
void* pPassword = const_cast<char*>(pass.c_str());
if (readFunc(pFile, &pKey, pCB, pPassword))
{
fclose(pFile); pFile = nullptr;
@@ -248,14 +248,16 @@ private:
if (!*ppKey) goto error;
return true;
}
if (getFunc) EVP_PKEY_free(pKey);
EVP_PKEY_free(pKey);
if (!getFunc) *ppKey = nullptr;
goto error;
}
else
{
std::string msg = Poco::format("EVPPKey::loadKey('%s')\n", keyFile);
getError(msg);
if (getFunc) EVP_PKEY_free(pKey);
EVP_PKEY_free(pKey);
if (!getFunc) *ppKey = nullptr;
throw IOException(msg);
}
}
@@ -295,8 +297,8 @@ private:
EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey;
if (pKey)
{
pem_password_cb* pCB = pass.empty() ? (pem_password_cb*)nullptr : &passCB;
void* pPassword = pass.empty() ? (void*)nullptr : (void*)pass.c_str();
pem_password_cb* pCB = &passCB;
void* pPassword = const_cast<char*>(pass.c_str());
if (readFunc(pBIO, &pKey, pCB, pPassword))
{
BIO_free(pBIO); pBIO = nullptr;
@@ -313,7 +315,8 @@ private:
if (!*ppKey) goto error;
return true;
}
if (getFunc) EVP_PKEY_free(pKey);
EVP_PKEY_free(pKey);
if (!getFunc) *ppKey = nullptr;
goto error;
}
else goto error;

View File

@@ -571,6 +571,53 @@ void EVPTest::testECEVPSaveLoadFileNoPass()
}
void EVPTest::testECEVPLoadKeyWrongPassword()
{
// Test for issue #4627: Loading a password-protected key with empty password
// should throw an exception, not prompt stdin.
try
{
std::string curveName = ECKey::getCurveName();
if (!curveName.empty())
{
EVPPKey key(curveName);
TemporaryFile filePub;
TemporaryFile filePriv;
key.save(filePub.path(), filePriv.path(), "testpwd");
// Try to load with empty password - should throw, not prompt stdin
try
{
EVPPKey keyBadPass("", filePriv.path(), "");
fail("Loading password-protected key with empty password should throw");
}
catch (const Poco::Exception&)
{
// Expected - key requires password but none provided
}
// Try to load with wrong password - should also throw
try
{
EVPPKey keyBadPass("", filePriv.path(), "wrongpwd");
fail("Loading password-protected key with wrong password should throw");
}
catch (const Poco::Exception&)
{
// Expected - wrong password
}
}
else
std::cerr << "No elliptic curves found!" << std::endl;
}
catch (Poco::Exception& ex)
{
std::cerr << ex.displayText() << std::endl;
throw;
}
}
void EVPTest::testRSAEVPKeyFromX509()
{
std::istringstream str(anyPemRSA);
@@ -744,6 +791,7 @@ CppUnit::Test* EVPTest::suite()
CppUnit_addTest(pSuite, EVPTest, testECEVPSaveLoadStreamNoPass);
CppUnit_addTest(pSuite, EVPTest, testECEVPSaveLoadFile);
CppUnit_addTest(pSuite, EVPTest, testECEVPSaveLoadFileNoPass);
CppUnit_addTest(pSuite, EVPTest, testECEVPLoadKeyWrongPassword);
CppUnit_addTest(pSuite, EVPTest, testRSAEVPKeyFromX509);
CppUnit_addTest(pSuite, EVPTest, testRSAEVPKeyFromPKCS12);
#if OPENSSL_VERSION_NUMBER >= 0x10000000L

View File

@@ -33,6 +33,7 @@ public:
void testECEVPSaveLoadStreamNoPass();
void testECEVPSaveLoadFile();
void testECEVPSaveLoadFileNoPass();
void testECEVPLoadKeyWrongPassword();
void testRSAEVPKeyFromX509();
void testRSAEVPKeyFromPKCS12();