From 79d86a335c4c46a3ea8a3bfa3ea4e2f68a83278b Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 13 Feb 2023 23:54:41 +0100 Subject: [PATCH] Adding more tests and renaming old ones. Signed-off-by: Pol Henarejos --- tests/const.py | 24 ++++++++ tests/pico-hsm/test_005_dkek.py | 37 ++++++++++++ .../pico-hsm/{test_pin.py => test_010_pin.py} | 37 ++++++------ ...keypair_gen.py => test_020_keypair_gen.py} | 2 + tests/pico-hsm/test_021_key_import.py | 57 +++++++++++++++++++ ...est_signature.py => test_030_signature.py} | 4 +- tests/pico-hsm/test_040_decrypt.py | 48 ++++++++++++++++ 7 files changed, 191 insertions(+), 18 deletions(-) create mode 100644 tests/const.py create mode 100644 tests/pico-hsm/test_005_dkek.py rename tests/pico-hsm/{test_pin.py => test_010_pin.py} (58%) rename tests/pico-hsm/{test_keypair_gen.py => test_020_keypair_gen.py} (91%) create mode 100644 tests/pico-hsm/test_021_key_import.py rename tests/pico-hsm/{test_signature.py => test_030_signature.py} (95%) create mode 100644 tests/pico-hsm/test_040_decrypt.py diff --git a/tests/const.py b/tests/const.py new file mode 100644 index 0000000..56f64c3 --- /dev/null +++ b/tests/const.py @@ -0,0 +1,24 @@ +""" +/* + * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +""" + +DEFAULT_PIN = '648219' +DEFAULT_SOPIN = '57621880' +DEFAULT_RETRIES = 3 +DEFAULT_DKEK = [0x1] * 32 +DEFAULT_DKEK_SHARES = 2 diff --git a/tests/pico-hsm/test_005_dkek.py b/tests/pico-hsm/test_005_dkek.py new file mode 100644 index 0000000..0e1d974 --- /dev/null +++ b/tests/pico-hsm/test_005_dkek.py @@ -0,0 +1,37 @@ +""" +/* + * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +""" + +import pytest +import hashlib +from utils import APDUResponse, SWCodes +from const import DEFAULT_PIN, DEFAULT_RETRIES, DEFAULT_DKEK, DEFAULT_DKEK_SHARES + +def test_dkek(device): + device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES) + device.login(DEFAULT_PIN) + resp = device.import_dkek(DEFAULT_DKEK) + assert(resp[0] == DEFAULT_DKEK_SHARES) + assert(resp[1] == DEFAULT_DKEK_SHARES-1) + + resp = device.import_dkek(DEFAULT_DKEK) + assert(resp[1] == DEFAULT_DKEK_SHARES-2) + + kcv = hashlib.sha256(b'\x00'*32).digest()[:8] + assert(bytes(resp[2:]) == kcv) + diff --git a/tests/pico-hsm/test_pin.py b/tests/pico-hsm/test_010_pin.py similarity index 58% rename from tests/pico-hsm/test_pin.py rename to tests/pico-hsm/test_010_pin.py index 2e96a0e..7a2d366 100644 --- a/tests/pico-hsm/test_pin.py +++ b/tests/pico-hsm/test_010_pin.py @@ -19,30 +19,35 @@ import pytest from utils import APDUResponse, SWCodes +from const import DEFAULT_PIN, DEFAULT_RETRIES -PIN = '648219' +WRONG_PIN = '112233' +RETRIES = DEFAULT_RETRIES -def test_pin(device): - device.initialize(retries=3) +def test_pin_init_retries(device): + device.initialize(retries=RETRIES) retries = device.get_login_retries() - assert(retries == 3) + assert(retries == RETRIES) - device.login(PIN) +def test_pin_login(device): + device.initialize(retries=RETRIES) + device.login(DEFAULT_PIN) + +def test_pin_retries(device): + device.initialize(retries=RETRIES) + device.login(DEFAULT_PIN) + + for ret in range(RETRIES-1): + with pytest.raises(APDUResponse) as e: + device.login(WRONG_PIN) + assert(e.value.sw1 == 0x63 and e.value.sw2 == (0xC0 | (RETRIES-1-ret))) with pytest.raises(APDUResponse) as e: - device.login('112233') - assert(e.value.sw1 == 0x63 and e.value.sw2 == 0xC2) - - with pytest.raises(APDUResponse) as e: - device.login('112233') - assert(e.value.sw1 == 0x63 and e.value.sw2 == 0xC1) - - with pytest.raises(APDUResponse) as e: - device.login('112233') + device.login(WRONG_PIN) assert(e.value.sw == SWCodes.SW_PIN_BLOCKED.value) - device.initialize(retries=3) + device.initialize(retries=RETRIES) retries = device.get_login_retries() - assert(retries == 3) + assert(retries == RETRIES) diff --git a/tests/pico-hsm/test_keypair_gen.py b/tests/pico-hsm/test_020_keypair_gen.py similarity index 91% rename from tests/pico-hsm/test_keypair_gen.py rename to tests/pico-hsm/test_020_keypair_gen.py index 30254ad..abff9d1 100644 --- a/tests/pico-hsm/test_keypair_gen.py +++ b/tests/pico-hsm/test_020_keypair_gen.py @@ -29,6 +29,7 @@ def test_gen_ecc(device, curve): resp = device.list_keys() assert((DOPrefixes.KEY_PREFIX.value, keyid) in resp) device.delete_file(DOPrefixes.KEY_PREFIX.value << 8 | keyid) + device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX.value << 8 | keyid) @pytest.mark.parametrize( "modulus", [1024, 2048, 4096] @@ -39,4 +40,5 @@ def test_gen_rsa(device, modulus): resp = device.list_keys() assert((DOPrefixes.KEY_PREFIX.value, keyid) in resp) device.delete_file(DOPrefixes.KEY_PREFIX.value << 8 | keyid) + device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX.value << 8 | keyid) diff --git a/tests/pico-hsm/test_021_key_import.py b/tests/pico-hsm/test_021_key_import.py new file mode 100644 index 0000000..5b7a341 --- /dev/null +++ b/tests/pico-hsm/test_021_key_import.py @@ -0,0 +1,57 @@ +""" +/* + * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +""" + +import pytest +import hashlib +from utils import KeyType, DOPrefixes +from cryptography.hazmat.primitives.asymmetric import rsa, ec +from const import DEFAULT_RETRIES, DEFAULT_DKEK_SHARES, DEFAULT_DKEK + +def test_prepare_dkek(device): + device.initialize(retries=DEFAULT_RETRIES, dkek_shares=DEFAULT_DKEK_SHARES) + resp = device.import_dkek(DEFAULT_DKEK) + resp = device.import_dkek(DEFAULT_DKEK) + kcv = hashlib.sha256(b'\x00'*32).digest()[:8] + assert(bytes(resp[2:]) == kcv) + +@pytest.mark.parametrize( + "modulus", [1024, 2048, 4096] +) +def test_import_rsa(device, modulus): + pkey = rsa.generate_private_key( + public_exponent=65537, + key_size=modulus, + ) + keyid = device.import_key(pkey) + pubkey = device.public_key(keyid) + assert(pubkey.public_numbers() == pkey.public_key().public_numbers()) + device.delete_file(DOPrefixes.KEY_PREFIX.value << 8 | keyid) + device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX.value << 8 | keyid) + + +@pytest.mark.parametrize( + "curve", [ec.SECP192R1, ec.SECP256R1, ec.SECP384R1, ec.SECP521R1, ec.SECP256K1, ec.BrainpoolP256R1, ec.BrainpoolP384R1, ec.BrainpoolP512R1] +) +def test_import_ecc(device, curve): + pkey = ec.generate_private_key(curve()) + keyid = device.import_key(pkey) + pubkey = device.public_key(keyid, param=curve().name) + assert(pubkey.public_numbers() == pkey.public_key().public_numbers()) + device.delete_file(DOPrefixes.KEY_PREFIX.value << 8 | keyid) + device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX.value << 8 | keyid) diff --git a/tests/pico-hsm/test_signature.py b/tests/pico-hsm/test_030_signature.py similarity index 95% rename from tests/pico-hsm/test_signature.py rename to tests/pico-hsm/test_030_signature.py index 8d2272b..887d239 100644 --- a/tests/pico-hsm/test_signature.py +++ b/tests/pico-hsm/test_030_signature.py @@ -33,7 +33,7 @@ data = b'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam neque u ) def test_signature_ecc(device, curve, scheme): keyid = device.keypair_generation(KeyType.ECC, curve) - pubkey = device.public_key(type=KeyType.ECC, keyid=keyid, param=curve) + pubkey = device.public_key(keyid=keyid, param=curve) if (scheme == Algorithm.ALGO_EC_RAW): datab = hashlib.sha512(data).digest() else: @@ -50,7 +50,7 @@ def test_signature_ecc(device, curve, scheme): ) def test_signature_rsa(device, modulus, scheme): keyid = device.keypair_generation(KeyType.RSA, modulus) - pubkey = device.public_key(type=KeyType.RSA, keyid=keyid) + pubkey = device.public_key(keyid=keyid) signature = device.sign(keyid=keyid, scheme=scheme, data=data) device.delete_file(DOPrefixes.KEY_PREFIX.value << 8 | keyid) device.verify(pubkey, data, signature, scheme) diff --git a/tests/pico-hsm/test_040_decrypt.py b/tests/pico-hsm/test_040_decrypt.py new file mode 100644 index 0000000..8890d2e --- /dev/null +++ b/tests/pico-hsm/test_040_decrypt.py @@ -0,0 +1,48 @@ +""" +/* + * This file is part of the Pico HSM distribution (https://github.com/polhenarejos/pico-hsm). + * Copyright (c) 2022 Pol Henarejos. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +""" + +import pytest +from utils import KeyType, DOPrefixes, Algorithm +from binascii import hexlify +import hashlib +from cryptography.hazmat.primitives.asymmetric import padding +from cryptography.hazmat.primitives import hashes + +data = b'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nullam neque urna, iaculis quis auctor scelerisque, auctor ut risus. In rhoncus, odio consequat consequat ultrices, ex libero dictum risus, accumsan interdum nisi orci ac neque. Ut vitae sem in metus hendrerit facilisis. Mauris maximus tristique mi, quis blandit lectus convallis eget.' + +@pytest.mark.parametrize( + "modulus", [1024,2048,4096] +) +@pytest.mark.parametrize( + "pad", [padding.PKCS1v15(), padding.OAEP( + mgf=padding.MGF1(algorithm=hashes.SHA256()), + algorithm=hashes.SHA256(), + label=None + )] +) +def test_decrypt_rsa(device, modulus, pad): + + keyid = device.keypair_generation(KeyType.RSA, modulus) + pubkey = device.public_key(keyid=keyid) + message = data[:(modulus//8)-100] + ciphered = pubkey.encrypt(message, pad) + datab = device.decrypt(keyid, ciphered, pad) + device.delete_file(DOPrefixes.KEY_PREFIX.value << 8 | keyid) + assert(datab == message) +