URL: https://github.com/freeipa/freeipa/pull/510 Author: tiran Title: #510: Vault: port key wrapping to python-cryptography Action: opened
PR body: """ https://fedorahosted.org/freeipa/ticket/6650 Signed-off-by: Christian Heimes <chei...@redhat.com> """ To pull the PR as Git branch: git remote add ghfreeipa https://github.com/freeipa/freeipa git fetch ghfreeipa pull/510/head:pr510 git checkout pr510
From 9ec7548f1181f4b5baa2386833a1c3d1732eda87 Mon Sep 17 00:00:00 2001 From: Christian Heimes <chei...@redhat.com> Date: Sat, 25 Feb 2017 13:09:11 +0100 Subject: [PATCH] Vault: port key wrapping to python-cryptography https://fedorahosted.org/freeipa/ticket/6650 Signed-off-by: Christian Heimes <chei...@redhat.com> --- ipaclient/plugins/vault.py | 102 ++++++++++++++++++--------------------------- 1 file changed, 41 insertions(+), 61 deletions(-) diff --git a/ipaclient/plugins/vault.py b/ipaclient/plugins/vault.py index 9efb1f1..073d3b5 100644 --- a/ipaclient/plugins/vault.py +++ b/ipaclient/plugins/vault.py @@ -31,10 +31,11 @@ from cryptography.hazmat.primitives import hashes from cryptography.hazmat.primitives.kdf.pbkdf2 import PBKDF2HMAC from cryptography.hazmat.primitives.asymmetric import padding -from cryptography.hazmat.primitives.serialization import load_pem_public_key,\ - load_pem_private_key - -import nss.nss as nss +from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes +from cryptography.hazmat.primitives.padding import PKCS7 +from cryptography.hazmat.primitives.serialization import ( + load_pem_public_key, load_pem_private_key) +from cryptography.x509 import load_der_x509_certificate from ipaclient.frontend import MethodOverride from ipalib.frontend import Local, Method, Object @@ -762,32 +763,25 @@ def forward(self, *args, **options): name='vault_type', error=_('Invalid vault type')) - # initialize NSS database - nss.nss_init(api.env.nss_dir) - # retrieve transport certificate config = self.api.Command.vaultconfig_show()['result'] transport_cert_der = config['transport_cert'] - nss_transport_cert = nss.Certificate(transport_cert_der) + transport_cert = load_der_x509_certificate( + transport_cert_der, default_backend()) + public_key = transport_cert.public_key() # generate session key - mechanism = nss.CKM_DES3_CBC_PAD - slot = nss.get_best_slot(mechanism) - key_length = slot.get_best_key_length(mechanism) - session_key = slot.key_gen(mechanism, None, key_length) + key_length = max(algorithms.TripleDES.key_sizes) + algo = algorithms.TripleDES(os.urandom(key_length // 8)) + nonce = os.urandom(algo.block_size // 8) # wrap session key with transport certificate - # pylint: disable=no-member - public_key = nss_transport_cert.subject_public_key_info.public_key - # pylint: enable=no-member - wrapped_session_key = nss.pub_wrap_sym_key(mechanism, - public_key, - session_key) - - options['session_key'] = wrapped_session_key.data + wrapped_session_key = public_key.encrypt( + algo.key, + padding.PKCS1v15() + ) - nonce_length = nss.get_iv_length(mechanism) - nonce = nss.generate_random(nonce_length) + options['session_key'] = wrapped_session_key options['nonce'] = nonce vault_data = {} @@ -797,19 +791,16 @@ def forward(self, *args, **options): vault_data[u'encrypted_key'] = base64.b64encode(encrypted_key)\ .decode('utf-8') - json_vault_data = json.dumps(vault_data) + json_vault_data = json.dumps(vault_data).encode('utf-8') # wrap vault_data with session key - iv_si = nss.SecItem(nonce) - iv_param = nss.param_from_iv(mechanism, iv_si) - - encoding_ctx = nss.create_context_by_sym_key(mechanism, - nss.CKA_ENCRYPT, - session_key, - iv_param) + padder = PKCS7(algo.block_size).padder() + padded_data = padder.update(json_vault_data) + padded_data += padder.finalize() - wrapped_vault_data = encoding_ctx.cipher_op(json_vault_data)\ - + encoding_ctx.digest_final() + cipher = Cipher(algo, modes.CBC(nonce), backend=default_backend()) + encryptor = cipher.encryptor() + wrapped_vault_data = encryptor.update(padded_data) + encryptor.finalize() options['vault_data'] = wrapped_vault_data @@ -925,49 +916,38 @@ def forward(self, *args, **options): vault_type = vault['ipavaulttype'][0] - # initialize NSS database - nss.nss_init(api.env.nss_dir) - # retrieve transport certificate config = self.api.Command.vaultconfig_show()['result'] transport_cert_der = config['transport_cert'] - nss_transport_cert = nss.Certificate(transport_cert_der) + transport_cert = load_der_x509_certificate( + transport_cert_der, default_backend()) + public_key = transport_cert.public_key() # generate session key - mechanism = nss.CKM_DES3_CBC_PAD - slot = nss.get_best_slot(mechanism) - key_length = slot.get_best_key_length(mechanism) - session_key = slot.key_gen(mechanism, None, key_length) + key_length = max(algorithms.TripleDES.key_sizes) + algo = algorithms.TripleDES(os.urandom(key_length // 8)) # wrap session key with transport certificate - # pylint: disable=no-member - public_key = nss_transport_cert.subject_public_key_info.public_key - # pylint: enable=no-member - wrapped_session_key = nss.pub_wrap_sym_key(mechanism, - public_key, - session_key) + wrapped_session_key = public_key.encrypt( + algo.key, + padding.PKCS1v15() + ) # send retrieval request to server - options['session_key'] = wrapped_session_key.data - + options['session_key'] = wrapped_session_key response = self.api.Command.vault_retrieve_internal(*args, **options) - result = response['result'] nonce = result['nonce'] # unwrap data with session key - wrapped_vault_data = result['vault_data'] - - iv_si = nss.SecItem(nonce) - iv_param = nss.param_from_iv(mechanism, iv_si) - - decoding_ctx = nss.create_context_by_sym_key(mechanism, - nss.CKA_DECRYPT, - session_key, - iv_param) - - json_vault_data = decoding_ctx.cipher_op(wrapped_vault_data)\ - + decoding_ctx.digest_final() + cipher = Cipher(algo, modes.CBC(nonce), backend=default_backend()) + decryptor = cipher.decryptor() + padded_data = decryptor.update(result['vault_data']) + padded_data += decryptor.finalize() + + unpadder = PKCS7(algo.block_size).unpadder() + json_vault_data = unpadder.update(padded_data) + json_vault_data += unpadder.finalize() vault_data = json.loads(json_vault_data.decode('utf-8')) data = base64.b64decode(vault_data[u'data'].encode('utf-8'))
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code