summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Kehrer <paul.l.kehrer@gmail.com>2017-12-01 04:54:32 +0800
committerAlex Gaynor <alex.gaynor@gmail.com>2017-11-30 14:54:32 -0600
commitbdb7639ad53427fae38695d2dc5bf5bd794787c8 (patch)
tree29c0148f15453c89b3ca89808b6481cdb68c23dc
parente73818600065821d588af475b024f4eb518c3509 (diff)
downloadpyopenssl-bdb7639ad53427fae38695d2dc5bf5bd794787c8.tar.gz
Export keying material support (#725)
* added method to export keying material from an ssl connection * updated tests to use bytestrings to avoid breaking python3 tests * added additional comments to test * simplify export_keying_material * add changelog * address review feedback
-rw-r--r--CHANGELOG.rst2
-rw-r--r--src/OpenSSL/SSL.py24
-rw-r--r--tests/test_ssl.py22
3 files changed, 48 insertions, 0 deletions
diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 3f5590f..ae094cf 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -25,6 +25,8 @@ Changes:
- Fixed a potential use-after-free in the verify callback and resolved a memory leak when loading PKCS12 files with ``cacerts``.
`#723 <https://github.com/pyca/pyopenssl/pull/723>`_
+- Added ``Connection.export_keying_material`` for RFC 5705 compatible export of keying material.
+ `#725 <https://github.com/pyca/pyopenssl/pull/725>`_
----
diff --git a/src/OpenSSL/SSL.py b/src/OpenSSL/SSL.py
index ec33814..b664254 100644
--- a/src/OpenSSL/SSL.py
+++ b/src/OpenSSL/SSL.py
@@ -2031,6 +2031,30 @@ class Connection(object):
_lib.SSL_SESSION_get_master_key(session, outp, length)
return _ffi.buffer(outp, length)[:]
+ def export_keying_material(self, label, olen, context=None):
+ """
+ Obtain keying material for application use.
+
+ :param label - a disambiguating label string as described in RFC 5705
+ :param olen - the length of the exported key material in bytes
+ :param context - a per-association context value
+ :return the exported key material bytes or None
+ """
+ outp = _no_zero_allocator("unsigned char[]", olen)
+ context_buf = _ffi.NULL
+ context_len = 0
+ use_context = 0
+ if context is not None:
+ context_buf = context
+ context_len = len(context)
+ use_context = 1
+ success = _lib.SSL_export_keying_material(self._ssl, outp, olen,
+ label, len(label),
+ context_buf, context_len,
+ use_context)
+ _openssl_assert(success == 1)
+ return _ffi.buffer(outp, olen)[:]
+
def sock_shutdown(self, *args, **kwargs):
"""
See shutdown(2)
diff --git a/tests/test_ssl.py b/tests/test_ssl.py
index 76d8c4d..03dd935 100644
--- a/tests/test_ssl.py
+++ b/tests/test_ssl.py
@@ -3379,6 +3379,28 @@ class TestMemoryBIO(object):
assert server_conn.client_random() != server_conn.server_random()
assert client_conn.client_random() != client_conn.server_random()
+ # Export key material for other uses.
+ cekm = client_conn.export_keying_material(b'LABEL', 32)
+ sekm = server_conn.export_keying_material(b'LABEL', 32)
+ assert cekm is not None
+ assert sekm is not None
+ assert cekm == sekm
+ assert len(sekm) == 32
+
+ # Export key material for other uses with additional context.
+ cekmc = client_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
+ sekmc = server_conn.export_keying_material(b'LABEL', 32, b'CONTEXT')
+ assert cekmc is not None
+ assert sekmc is not None
+ assert cekmc == sekmc
+ assert cekmc != cekm
+ assert sekmc != sekm
+ # Export with alternate label
+ cekmt = client_conn.export_keying_material(b'test', 32, b'CONTEXT')
+ sekmt = server_conn.export_keying_material(b'test', 32, b'CONTEXT')
+ assert cekmc != cekmt
+ assert sekmc != sekmt
+
# Here are the bytes we'll try to send.
important_message = b'One if by land, two if by sea.'