Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Memory leak in EVP_PKEY_new_raw_private_key #108

Open
maxtropets opened this issue Feb 26, 2025 · 2 comments
Open

Memory leak in EVP_PKEY_new_raw_private_key #108

maxtropets opened this issue Feb 26, 2025 · 2 comments

Comments

@maxtropets
Copy link

TL;DR

  • Key type: EVP_PKEY_X25519
  • Reproduced on Azure Linux 3.0 with SymCrypt backend, openssl 3.3.2
  • ASAN reports memory leaks when creating a private key from raw data with EVP_PKEY_new_raw_private_key.
  • strace-ing proves SymCrypt backend is used.
  • Building openssl 3.3.2 from source and linking against it fixed the leak, therefore pointing to SymCrypt backend involvement.

More details

I'm not sure if X25519 is fully supported here. I found microsoft/SymCrypt#43 and this, which is about adding support for multiple EdDSA variations, and it seems it hasn't been done yet.

However, I'm able to successfully create X25519 keys in a freshly created Azure Linux 3.0 container.

Questions to address

  • Is X25519 supported by SymCrypt? And if not, is it OK that EVP_PKEY_CTX_new_id(EVP_PKEY_X25519, NULL) succeeds?
  • Am I using correct/wrong OpenSSL API to create/copy the keys?
  • If the latter, how do I change it to avoid the leak?

Code to repro

#include <cassert>
#include <openssl/evp.h>
#include <vector>

int main()
{
  const int curve_nid = EVP_PKEY_X25519;

  // Generate a brand new key.
  EVP_PKEY* key = EVP_PKEY_new();
  auto pctx = EVP_PKEY_CTX_new_id(curve_nid, NULL);

  assert(pctx != nullptr);
  assert(EVP_PKEY_keygen_init(pctx) == 1);
  assert(EVP_PKEY_keygen(pctx, &key) == 1);

  EVP_PKEY_CTX_free(pctx);

  // Copy private key bytes.
  std::vector<uint8_t> raw_priv(EVP_PKEY_size(key));
  size_t raw_priv_len = raw_priv.size();
  EVP_PKEY_get_raw_private_key(key, raw_priv.data(), &raw_priv_len);

  // Create new private key from raw bytes
  // ! LEAKS MEMORY !
  EVP_PKEY* another_key = EVP_PKEY_new_raw_private_key(
    curve_nid, nullptr, raw_priv.data(), raw_priv.size());

  // Free both.
  EVP_PKEY_free(key);
  EVP_PKEY_free(another_key);

  // Try to force-cleanup all potential leftovers, does not mitigate the leak.
  EVP_cleanup();
  CRYPTO_cleanup_all_ex_data();
}

Compile (replace paths if needed): clang file_name.cpp /usr/lib/libcrypto.so.3 /usr/lib/libstdc++.so -g -fsanitize=address

Run: ./a.out

Produces:

root [ /workspace ]# ./a.out
                                                                                                                                                        =================================================================
==691==ERROR: LeakSanitizer: detected memory leaks

Direct leak of 56 byte(s) in 1 object(s) allocated from:
    #0 0x55e549f548df in malloc (/workspace/a.out+0x1158df)
    microsoft/SymCrypt#1 0x7ff165f63c30 in CRYPTO_malloc (/usr/lib/libcrypto.so.3+0x218c30)

SUMMARY: AddressSanitizer: 56 byte(s) leaked in 1 allocation(s).

Strace:

root [ /workspace ]# strace -o out.txt ./a.out
...
root [ /workspace ]# grep "symcrypt" out.txt
access("/etc/pki/tls/symcrypt_prov.cnf", R_OK) = 0
openat(AT_FDCWD, "/etc/pki/tls/symcrypt_prov.cnf", O_RDONLY) = 3
openat(AT_FDCWD, "/usr/lib/ossl-modules/symcryptprovider.so", O_RDONLY|O_CLOEXEC) = 3
openat(AT_FDCWD, "/usr/lib/libsymcrypt.so.103", O_RDONLY|O_CLOEXEC) = 3
@mamckee
Copy link
Collaborator

mamckee commented Feb 26, 2025

The address sanitizer output leads me to believe the leak is in the SymCrypt provider, not SymCrypt itself (https://github.com/microsoft/SymCrypt-OpenSSL). When did you first notice this leak? Was it after an upgrade?

@maxtropets
Copy link
Author

Thank you for taking a look.

  • We first noticed when moving to Azure Linux 3.0, which is an ongoing effort.
  • We've never run this version of openssl under address sanitizer before.

@samuel-lee-msft samuel-lee-msft transferred this issue from microsoft/SymCrypt Feb 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants