From 7ae76354efb39b0b347f661c3c2858f0db790faa Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Mon, 13 Mar 2023 18:03:21 +0100 Subject: [PATCH] Added more tests for key_export. Signed-off-by: Pol Henarejos --- tests/pico-hsm/test_021_key_import.py | 8 +-- tests/pico-hsm/test_025_key_export.py | 79 ++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 6 deletions(-) diff --git a/tests/pico-hsm/test_021_key_import.py b/tests/pico-hsm/test_021_key_import.py index b0e0b7f..a2779d1 100644 --- a/tests/pico-hsm/test_021_key_import.py +++ b/tests/pico-hsm/test_021_key_import.py @@ -42,8 +42,8 @@ def test_import_rsa(device, 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) + device.delete_file(DOPrefixes.KEY_PREFIX.value << 8, keyid) + device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX.value << 8, keyid) @pytest.mark.parametrize( @@ -54,8 +54,8 @@ def test_import_ecc(device, 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) + device.delete_file(DOPrefixes.KEY_PREFIX.value << 8, keyid) + device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX.value << 8, keyid) @pytest.mark.parametrize( "size", [128, 192, 256] diff --git a/tests/pico-hsm/test_025_key_export.py b/tests/pico-hsm/test_025_key_export.py index b22b165..1082bb1 100644 --- a/tests/pico-hsm/test_025_key_export.py +++ b/tests/pico-hsm/test_025_key_export.py @@ -19,13 +19,19 @@ import pytest from utils import KeyType, DOPrefixes, APDUResponse, SWCodes +from binascii import hexlify +import hashlib from const import DEFAULT_DKEK +from cryptography.hazmat.primitives import cmac +from cryptography.hazmat.primitives.ciphers import algorithms, Cipher, modes +from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives import serialization def test_initialize(device): device.initialize(key_domains=1) assert(device.get_key_domains() == 1) - device.set_key_domain(key_domain=0, total=1) + device.set_key_domain(key_domain=0, total=2) keyid_in = -1 keyid_out = -1 @@ -57,6 +63,75 @@ def test_export_key_in_fail(device): def test_export_import_dkek(device): resp = device.import_dkek(DEFAULT_DKEK, key_domain=0) + resp = device.import_dkek(DEFAULT_DKEK, key_domain=0) def test_export_key_in_ok(device): - resp = device.export_key(2) + resp = bytes(device.export_key(keyid_in)) + kcv = hashlib.sha256(b'\x00'*32).digest()[:8] + assert(kcv == resp[:8]) + assert(resp[8] == 12) + assert(resp[9:21] == b"\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03") + + pkey = hashlib.sha256(b'\x00'*32+b'\x00\x00\x00\x02').digest() + c = cmac.CMAC(algorithms.AES(pkey)) + c.update(resp[:-16]) + resCMAC = c.finalize() + assert(resCMAC == resp[-16:]) + +def test_delete_keys_in_out(device): + device.delete_file(DOPrefixes.KEY_PREFIX.value, keyid_in) + device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX.value, keyid_in) + device.delete_file(DOPrefixes.KEY_PREFIX.value, keyid_out) + device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX.value, keyid_out) + +def test_export_import(device): + pkey_gen = ec.generate_private_key(ec.BrainpoolP256R1()) + keyid = device.import_key(pkey_gen) + + resp = bytes(device.export_key(keyid)) + kcv = hashlib.sha256(b'\x00'*32).digest()[:8] + assert(kcv == resp[:8]) + assert(resp[8] == 12) + assert(resp[9:21] == b"\x00\x0A\x04\x00\x7F\x00\x07\x02\x02\x02\x02\x03") + + pkey = hashlib.sha256(b'\x00'*32+b'\x00\x00\x00\x02').digest() + c = cmac.CMAC(algorithms.AES(pkey)) + c.update(resp[:-16]) + resCMAC = c.finalize() + assert(resCMAC == resp[-16:]) + + iv = b'\x00'*16 + pkey = hashlib.sha256(b'\x00'*32+b'\x00\x00\x00\x01').digest() + cipher = Cipher(algorithms.AES(pkey), modes.CBC(iv)) + decryptor = cipher.decryptor() + payload = decryptor.update(resp[27:-16]) + decryptor.finalize() + + rnd = payload[:8] + ofs = 8 + key_size = int.from_bytes(payload[ofs:ofs+2], 'big') + ofs += 2 + A_len = int.from_bytes(payload[ofs:ofs+2], 'big') + ofs += 2+A_len + B_len = int.from_bytes(payload[ofs:ofs+2], 'big') + ofs += 2+B_len + P_len = int.from_bytes(payload[ofs:ofs+2], 'big') + ofs += 2+P_len + N_len = int.from_bytes(payload[ofs:ofs+2], 'big') + ofs += 2+N_len + G_len = int.from_bytes(payload[ofs:ofs+2], 'big') + ofs += 2+G_len + d_len = int.from_bytes(payload[ofs:ofs+2], 'big') + ofs += 2 + d = payload[ofs:ofs+d_len] + ofs += d_len + Q_len = int.from_bytes(payload[ofs:ofs+2], 'big') + ofs += 2 + Q = payload[ofs:ofs+Q_len] + ofs += Q_len + + pkey_ex = ec.EllipticCurvePrivateNumbers(int.from_bytes(d, 'big'), ec.EllipticCurvePublicKey.from_encoded_point(ec.BrainpoolP256R1(), Q).public_numbers()).private_key() + assert(pkey_gen.private_bytes(serialization.Encoding.DER, serialization.PrivateFormat.PKCS8, serialization.NoEncryption()) == pkey_ex.private_bytes(serialization.Encoding.DER, serialization.PrivateFormat.PKCS8, serialization.NoEncryption())) + assert(pkey_gen.public_key().public_bytes(serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint) == pkey_ex.public_key().public_bytes(serialization.Encoding.X962, serialization.PublicFormat.UncompressedPoint)) + + device.delete_file(DOPrefixes.KEY_PREFIX.value, keyid) + device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX.value, keyid)