# -*- coding: utf-8 -*- # # Copyright (C) 2015 FreeIPA Contributors see COPYING for license # """ Test the `ipapython/ipap11helper/p11helper.c` module. """ from binascii import hexlify import os import os.path import logging import subprocess import tempfile import pytest from ipaplatform.paths import paths from ipapython import p11helper as _ipap11helper pytestmark = pytest.mark.tier0 CONFIG_DATA = """ # SoftHSM v2 configuration file directories.tokendir = %s/tokens objectstore.backend = file """ LIBSOFTHSM = paths.LIBSOFTHSM2_SO SOFTHSM2_UTIL = paths.SOFTHSM2_UTIL logging.basicConfig(level=logging.INFO) log = logging.getLogger('t') master_key_label = u"master-ž" # random non-ascii character to test unicode master_key_id = "m" replica1_key_label = u"replica1" replica1_key_id = "id1" replica1_import_label = u"replica1-import" replica1_import_id = "id1-import" replica1_new_label = u"replica1-new-label-ž" replica2_key_label = u"replica2" replica2_key_id = "id2" replica_non_existent_label = u"replica-nonexistent" @pytest.fixture(scope="module") def p11(request): token_path = tempfile.mkdtemp(prefix='pytest_', suffix='_pkcs11') os.chdir(token_path) os.mkdir('tokens') with open('softhsm2.conf', 'w') as cfg: cfg.write(CONFIG_DATA % token_path) os.environ['SOFTHSM2_CONF'] = os.path.join(token_path, 'softhsm2.conf') subprocess.check_call([SOFTHSM2_UTIL, '--init-token', '--slot', '0', '--label', 'test', '--pin', '1234', '--so-pin', '1234']) try: p11 = _ipap11helper.P11_Helper(0, "1234", LIBSOFTHSM) except _ipap11helper.Error: pytest.fail('Failed to initialize the helper object.', pytrace=False) def fin(): try: p11.finalize() except _ipap11helper.Error: pytest.fail('Failed to finalize the helper object.', pytrace=False) finally: del os.environ['SOFTHSM2_CONF'] request.addfinalizer(fin) return p11 class test_p11helper(object): def test_generate_master_key(self, p11): assert p11.generate_master_key(master_key_label, master_key_id, key_length=16, cka_wrap=True, cka_unwrap=True) def test_search_for_master_key(self, p11): master_key = p11.find_keys(_ipap11helper.KEY_CLASS_SECRET_KEY, label=master_key_label, id=master_key_id) assert len(master_key) == 1, "The master key should exist." def test_generate_replica_key_pair(self, p11): assert p11.generate_replica_key_pair(replica1_key_label, replica1_key_id, pub_cka_wrap=True, priv_cka_unwrap=True) def test_find_key(self, p11): rep1_pub = p11.find_keys(_ipap11helper.KEY_CLASS_PUBLIC_KEY, label=replica1_key_label, cka_wrap=True) assert len(rep1_pub) == 1, ("replica key pair has to contain " "1 pub key instead of %s" % len(rep1_pub)) rep1_priv = p11.find_keys(_ipap11helper.KEY_CLASS_PRIVATE_KEY, label=replica1_key_label, cka_unwrap=True) assert len(rep1_priv) == 1, ("replica key pair has to contain 1 " "private key instead of %s" % len(rep1_priv)) def test_find_key_by_uri(self, p11): rep1_pub = p11.find_keys(uri="pkcs11:object=replica1;objecttype=public") assert len(rep1_pub) == 1, ("replica key pair has to contain 1 pub " "key instead of %s" % len(rep1_pub)) def test_get_attribute_from_object(self, p11): rep1_pub = p11.find_keys(_ipap11helper.KEY_CLASS_PUBLIC_KEY, label=replica1_key_label, cka_wrap=True)[0] iswrap = p11.get_attribute(rep1_pub, _ipap11helper.CKA_WRAP) assert iswrap is True, "replica public key has to have CKA_WRAP = TRUE" def test_generate_replica_keypair_with_extractable_private_key(self, p11): assert p11.generate_replica_key_pair(replica2_key_label, replica2_key_id, pub_cka_wrap=True, priv_cka_unwrap=True, priv_cka_extractable=True) def test_find_key_on_nonexistent_key_pair(self, p11): test_list = p11.find_keys(_ipap11helper.KEY_CLASS_PUBLIC_KEY, label=replica_non_existent_label) assert len(test_list) == 0, ("list should be empty because label " "'%s' should not exist" % replica_non_existent_label) def test_export_import_of_public_key(self, p11): rep1_pub = p11.find_keys(_ipap11helper.KEY_CLASS_PUBLIC_KEY, label=replica1_key_label, cka_wrap=True)[0] pub = p11.export_public_key(rep1_pub) log.debug("Exported public key %s", hexlify(pub)) with open("public_key.asn1.der", "wb") as f: f.write(pub) rep1_pub_import = p11.import_public_key(replica1_import_label, replica1_import_id, pub, cka_wrap=True) log.debug('imported replica 1 public key: %s', rep1_pub_import) # test public key import rep1_modulus_orig = p11.get_attribute(rep1_pub, _ipap11helper.CKA_MODULUS) rep1_modulus_import = p11.get_attribute(rep1_pub_import, _ipap11helper.CKA_MODULUS) log.debug('rep1_modulus_orig = 0x%s', hexlify(rep1_modulus_orig)) log.debug('rep1_modulus_import = 0x%s', hexlify(rep1_modulus_import)) assert rep1_modulus_import == rep1_modulus_orig rep1_pub_exp_orig = p11.get_attribute( rep1_pub, _ipap11helper.CKA_PUBLIC_EXPONENT) rep1_pub_exp_import = p11.get_attribute( rep1_pub_import, _ipap11helper.CKA_PUBLIC_EXPONENT) log.debug('rep1_pub_exp_orig = 0x%s', hexlify(rep1_pub_exp_orig)) log.debug('rep1_pub_exp_import = 0x%s', hexlify(rep1_pub_exp_import)) assert rep1_pub_exp_import == rep1_pub_exp_orig def test_wrap_unwrap_key_by_master_key_with_AES(self, p11): master_key = p11.find_keys(_ipap11helper.KEY_CLASS_SECRET_KEY, label=master_key_label, id=master_key_id)[0] rep2_priv = p11.find_keys(_ipap11helper.KEY_CLASS_PRIVATE_KEY, label=replica2_key_label, cka_unwrap=True)[0] log.debug("wrapping dnssec priv key by master key") wrapped_priv = p11.export_wrapped_key( rep2_priv, master_key, _ipap11helper.MECH_AES_KEY_WRAP_PAD ) assert wrapped_priv log.debug("wrapped_dnssec priv key: %s", hexlify(wrapped_priv)) with open("wrapped_priv.der", "wb") as f: f.write(wrapped_priv) assert p11.import_wrapped_private_key( u'test_import_wrapped_priv', '1', wrapped_priv, master_key, _ipap11helper.MECH_AES_KEY_WRAP_PAD, _ipap11helper.KEY_TYPE_RSA ) def test_wrap_unwrap_key_by_master_key_with_RSA_PKCS(self, p11): master_key = p11.find_keys(_ipap11helper.KEY_CLASS_SECRET_KEY, label=master_key_label, id=master_key_id)[0] rep2_pub = p11.find_keys(_ipap11helper.KEY_CLASS_PUBLIC_KEY, label=replica2_key_label, cka_wrap=True)[0] rep2_priv = p11.find_keys(_ipap11helper.KEY_CLASS_PRIVATE_KEY, label=replica2_key_label, cka_unwrap=True)[0] wrapped = p11.export_wrapped_key(master_key, rep2_pub, _ipap11helper.MECH_RSA_PKCS) assert wrapped log.debug("wrapped key MECH_RSA_PKCS (secret master wrapped by pub " "key): %s", hexlify(wrapped)) assert p11.import_wrapped_secret_key(u'test_import_wrapped', '2', wrapped, rep2_priv, _ipap11helper.MECH_RSA_PKCS, _ipap11helper.KEY_TYPE_AES) def test_wrap_unwrap_by_master_key_with_RSA_PKCS_OAEP(self, p11): master_key = p11.find_keys(_ipap11helper.KEY_CLASS_SECRET_KEY, label=master_key_label, id=master_key_id)[0] rep2_pub = p11.find_keys(_ipap11helper.KEY_CLASS_PUBLIC_KEY, label=replica2_key_label, cka_wrap=True)[0] rep2_priv = p11.find_keys(_ipap11helper.KEY_CLASS_PRIVATE_KEY, label=replica2_key_label, cka_unwrap=True)[0] wrapped = p11.export_wrapped_key(master_key, rep2_pub, _ipap11helper.MECH_RSA_PKCS_OAEP) assert wrapped log.debug("wrapped key MECH_RSA_PKCS_OAEP (secret master wrapped by " "pub key): %s", hexlify(wrapped)) assert p11.import_wrapped_secret_key(u'test_import_wrapped', '3', wrapped, rep2_priv, _ipap11helper.MECH_RSA_PKCS_OAEP, _ipap11helper.KEY_TYPE_AES) def test_set_attribute_on_object(self, p11): rep1_pub = p11.find_keys(_ipap11helper.KEY_CLASS_PUBLIC_KEY, label=replica1_key_label, cka_wrap=True)[0] test_label = replica1_new_label p11.set_attribute(rep1_pub, _ipap11helper.CKA_LABEL, test_label) assert p11.get_attribute(rep1_pub, _ipap11helper.CKA_LABEL) \ == test_label, "The labels do not match." def test_do_not_generate_identical_master_keys(self, p11): with pytest.raises(_ipap11helper.DuplicationError): p11.generate_master_key(master_key_label, master_key_id, key_length=16) master_key = p11.find_keys(_ipap11helper.KEY_CLASS_SECRET_KEY, label=master_key_label) assert len(master_key) == 1, ("There shouldn't be multiple keys " "with the same label.") def test_delete_key(self, p11): master_key = p11.find_keys(_ipap11helper.KEY_CLASS_SECRET_KEY, label=master_key_label, id=master_key_id)[0] rep1_pub = p11.find_keys(_ipap11helper.KEY_CLASS_PUBLIC_KEY, label=replica1_new_label, cka_wrap=True)[0] rep2_priv = p11.find_keys(_ipap11helper.KEY_CLASS_PRIVATE_KEY, label=replica2_key_label, cka_unwrap=True)[0] for key in (rep1_pub, rep2_priv, master_key): p11.delete_key(key) master_key = p11.find_keys(_ipap11helper.KEY_CLASS_SECRET_KEY, label=master_key_label, id=master_key_id) assert len(master_key) == 0, "The master key should be deleted." rep1_pub = p11.find_keys(_ipap11helper.KEY_CLASS_PUBLIC_KEY, label=replica1_new_label, cka_wrap=True) assert len(rep1_pub) == 0, ("The public key of replica1 pair should " "be deleted.") rep2_priv = p11.find_keys(_ipap11helper.KEY_CLASS_PRIVATE_KEY, label=replica2_key_label, cka_unwrap=True) assert len(rep2_priv) == 0, ("The private key of replica2 pair should" " be deleted.")