7

I'm starting learn OpenSSL programming in C/C++. An issue I encountered is, how could I safely wipe out the memory for private keys?

For example, I may have code:

EVP_PKEY *private_key = PEM_read_bio_PrivateKey( bio, ,,,)
RSA *r = EVP_PKEY_get1_RSA( private_key);

I'd like to wipe out private_key from memory cleanly before using EVP_PKEY_free() to free it.

I'd appreciate for helps and/or your suggestions. Thanks.

jww
  • 97,681
  • 90
  • 411
  • 885
pokeba
  • 81
  • 1
  • 5
  • Will `memset(...)` work for you? – ryyker Mar 18 '17 at 00:09
  • 1
    Safely clearing memory is yuite a complicated subject. It depends on the implementation how to accomplish this. Note that not only erasing the key is. Reading them and storing already is a problem, if you want to prevent other processes to e.g. read the memory. – too honest for this site Mar 18 '17 at 01:47

1 Answers1

5

EVP_PKEY *private_key = PEM_read_bio_PrivateKey( bio, ,,,)

I'd like to wipe out private_key from memory cleanly before using EVP_PKEY_free to free it.

OpenSSL's EVP_PKEY_free wipes the private key for you. You don't have to do anything special.

RSA *r = EVP_PKEY_get1_RSA( private_key);

The get1 means the reference count was bumped and you effectively got your own copy of the object. A get0 means you got a pointer to an existing object, and you should not call free on it. Because of get1, you must call RSA_free on it to ensure it gets deleted. As with EVP_PKEY_free, RSA_free will wipe the key.

Please don't call memset. These are opaque structures, and you have to follow a number of pointers to correctly clear the sub-objects. A lot more fields have been hidden in OpenSSL 1.1.0, so its going to be more difficult to follow the pointers (if you wanted to). Also see Error: “invalid use of incomplete type ‘RSA {aka struct rsa_st}” in OpenSSL 1.1.0, Visual Studio and error C2027: use of undefined type 'rsa_st' in OpenSSL 1.1.0, EVP_get_cipherbyname and “undefined struct/union evp_cipher_st” in OpenSSL 1.1.0, etc.


Here's some additional reading you might be interested in:

When functions like EVP_PKEY_free and RSA_free are called, they eventually end in a call to OPENSSL_cleanse before memory is returned to the operating system. In the case of an RSA private key, its called at leats 8 times to wipe the byte arrays associated with n, e, d, p, q, dp, dq, and invq.

Community
  • 1
  • 1
jww
  • 97,681
  • 90
  • 411
  • 885
  • jww, thanks very much. I checked the source code for openssl 1.0.1u which I'm using. I don't see any OPENSSL_cleanse() call invoked from EVP_PKEY_free(). But I do see lots of OPENSSL_cleanse() called from RSA_free(). Since the rsa key is just a reference from the EVP_PKEY struct memory area, could I safely assume that when I do RSA_free(), it will wipe the rsa key and thus, it also cleaned up the memory of EVP_PKEY struct? – pokeba Mar 20 '17 at 19:23
  • `EVP_PKEY_free()` eventually calls `EVP_PKEY_free_it()` that uses the `ameth` pointer of the `EVP_PKEY` structure to call the function responsible for cleansing private key data for the particular key type... Abstractions, abstractions everywhere! – buherator May 17 '18 at 12:25