Skip to content

Memory leak in EVPPKey::loadKey used with files & wrong password #3260

@ericbrts

Description

@ericbrts

Hi all,

Boost test complains that a memory leak occured while constructing an ECKey from a private key file + an incorrect password.
I got back to EVPPKey class, more specifically in

	template <typename K, typename F>
	static bool loadKey(K** ppKey,
		PEM_read_FILE_Key_fn readFunc,
		F getFunc,
		const std::string& keyFile,
		const std::string& pass = "")

signature. In this template's code, there's a missing if (getFunc) EVP_PKEY_free(pKey);, which can be found in the very look-alike signature of EVPPkey::loadkey() with istream.

A simple fix could be (in EVPPkey.h):

	template <typename K, typename F>
	static bool loadKey(K** ppKey,
		PEM_read_FILE_Key_fn readFunc,
		F getFunc,
		const std::string& keyFile,
		const std::string& pass = "")
	{
		poco_assert_dbg (((typeid(K*) == typeid(RSA*) || typeid(K*) == typeid(EC_KEY*)) && getFunc) ||
						((typeid(K*) == typeid(EVP_PKEY*)) && !getFunc));
		poco_check_ptr (ppKey);
		poco_assert_dbg (!*ppKey);

		FILE* pFile = 0;
		if (!keyFile.empty())
		{
			if (!getFunc) *ppKey = (K*)EVP_PKEY_new();
			EVP_PKEY* pKey = getFunc ? EVP_PKEY_new() : (EVP_PKEY*)*ppKey;
			if (pKey)
			{
				pFile = fopen(keyFile.c_str(), "r");
				if (pFile)
				{
					pem_password_cb* pCB = pass.empty() ? (pem_password_cb*)0 : &passCB;
					void* pPassword = pass.empty() ? (void*)0 : (void*)pass.c_str();
					if (readFunc(pFile, &pKey, pCB, pPassword))
					{
						fclose(pFile); pFile = 0;
						if(getFunc)
						{
							*ppKey = (K*)getFunc(pKey);
							EVP_PKEY_free(pKey);
						}
						else
						{
							poco_assert_dbg (typeid(K*) == typeid(EVP_PKEY*));
							*ppKey = (K*)pKey;
						}
						if(!*ppKey) goto error;
						return true;
					}
					// *******************************************************
					if (getFunc) EVP_PKEY_free(pKey); // <============= HERE!
					// *******************************************************
					goto error;
				}
				else
				{
					if (getFunc) EVP_PKEY_free(pKey);
					throw IOException("ECKeyImpl, cannot open file", keyFile);
				}
			}
			else goto error;
		}
		return false;

	error:
		if (pFile) fclose(pFile);
		throw OpenSSLException("EVPKey::loadKey(string)");
	}

Best wishes,
Eric

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions