diff --git a/CHANGELOG.rst b/CHANGELOG.rst index b6401aac6..fc81dec1f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -23,6 +23,8 @@ Deprecations: Changes: ^^^^^^^^ +- Fix memory leak in ``OpenSSL.crypto.dump_privatekey()`` with ``FILETYPE_TEXT``. + `#496 `_ - Enable use of CRL (and more) in verify context. `#483 `_ diff --git a/doc/api/crypto.rst b/doc/api/crypto.rst index 5f7df24cb..c6501b4c6 100644 --- a/doc/api/crypto.rst +++ b/doc/api/crypto.rst @@ -73,14 +73,7 @@ Certificate signing requests Private keys ~~~~~~~~~~~~ -.. py:function:: dump_privatekey(type, pkey[, cipher, passphrase]) - - Dump the private key *pkey* into a buffer string encoded with the type - *type*, optionally (if *type* is :py:const:`FILETYPE_PEM`) encrypting it - using *cipher* and *passphrase*. - - *passphrase* must be either a string or a callback for providing the - pass phrase. +.. autofunction:: dump_privatekey .. py:function:: load_privatekey(type, buffer[, passphrase]) diff --git a/src/OpenSSL/crypto.py b/src/OpenSSL/crypto.py index 173539351..1116d5ed0 100644 --- a/src/OpenSSL/crypto.py +++ b/src/OpenSSL/crypto.py @@ -1698,16 +1698,17 @@ def dump_publickey(type, pkey): def dump_privatekey(type, pkey, cipher=None, passphrase=None): """ - Dump a private key to a buffer - - :param type: The file type (one of FILETYPE_PEM, FILETYPE_ASN1, or - FILETYPE_TEXT) - :param pkey: The PKey to dump - :param cipher: (optional) if encrypted PEM format, the cipher to - use + Dump the private key *pkey* into a buffer string encoded with the type + *type*. Optionally (if *type* is :const:`FILETYPE_PEM`) encrypting it + using *cipher* and *passphrase*. + + :param type: The file type (one of :const:`FILETYPE_PEM`, + :const:`FILETYPE_ASN1`, or :const:`FILETYPE_TEXT`) + :param PKey pkey: The PKey to dump + :param cipher: (optional) if encrypted PEM format, the cipher to use :param passphrase: (optional) if encrypted PEM format, this can be either - the passphrase to use, or a callback for providing the - passphrase. + the passphrase to use, or a callback for providing the passphrase. + :return: The buffer with the dumped key in :rtype: bytes """ @@ -1733,16 +1734,17 @@ def dump_privatekey(type, pkey, cipher=None, passphrase=None): elif type == FILETYPE_ASN1: result_code = _lib.i2d_PrivateKey_bio(bio, pkey._pkey) elif type == FILETYPE_TEXT: - rsa = _lib.EVP_PKEY_get1_RSA(pkey._pkey) + rsa = _ffi.gc( + _lib.EVP_PKEY_get1_RSA(pkey._pkey), + _lib.RSA_free + ) result_code = _lib.RSA_print(bio, rsa, 0) - # TODO RSA_free(rsa)? else: raise ValueError( "type argument must be FILETYPE_PEM, FILETYPE_ASN1, or " "FILETYPE_TEXT") - if result_code == 0: - _raise_current_error() + _openssl_assert(result_code != 0) return _bio_to_string(bio)