From 685c7f25fc6dc2a968012e1129c0a160bacf6945 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 22 Aug 2023 17:19:23 +0200 Subject: [PATCH 1/5] Revert previous fix. Signed-off-by: Pol Henarejos --- pico-hsm-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-hsm-sdk b/pico-hsm-sdk index 4cfbc19..81a598f 160000 --- a/pico-hsm-sdk +++ b/pico-hsm-sdk @@ -1 +1 @@ -Subproject commit 4cfbc19aa7df0c22d738e6567b62745358af2aaa +Subproject commit 81a598f464d715278772ac300d9f8ca7cdb1c25d From a6072b4ce85b3fbbebb69878eb0875764e20d969 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 23 Aug 2023 16:38:51 +0200 Subject: [PATCH 2/5] Curve25519 and Curve448 are encoded using ECDH template. Signed-off-by: Pol Henarejos --- src/hsm/cvc.c | 103 +++++++++++++++++++++++++++++--------------------- 1 file changed, 60 insertions(+), 43 deletions(-) diff --git a/src/hsm/cvc.c b/src/hsm/cvc.c index c91c4b4..8ecca6e 100644 --- a/src/hsm/cvc.c +++ b/src/hsm/cvc.c @@ -75,6 +75,8 @@ const uint8_t *pointA[] = { size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, size_t buf_len) { uint8_t Y_buf[MBEDTLS_ECP_MAX_PT_LEN]; const uint8_t oid_ecdsa[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x02, 0x02, 0x03 }; + const uint8_t oid_ri[] = { 0x04, 0x00, 0x7F, 0x00, 0x07, 0x02, 0x02, 0x05, 0x02, 0x03 }; + const uint8_t *oid = oid_ecdsa; size_t p_size = mbedtls_mpi_size(&ecdsa->grp.P), a_size = mbedtls_mpi_size(&ecdsa->grp.A); size_t b_size = mbedtls_mpi_size(&ecdsa->grp.B), g_size = 1 + mbedtls_mpi_size(&ecdsa->grp.G.X) + mbedtls_mpi_size(&ecdsa->grp.G.X); @@ -91,9 +93,18 @@ size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, siz size_t otot_size = asn1_len_tag(0x85, o_size), ytot_size = asn1_len_tag(0x86, y_size); size_t ctot_size = asn1_len_tag(0x87, c_size); size_t oid_len = asn1_len_tag(0x6, sizeof(oid_ecdsa)); - size_t tot_len = asn1_len_tag(0x7f49, - oid_len + ptot_size + atot_size + btot_size + gtot_size + otot_size + ytot_size + - ctot_size); + size_t tot_len = 0, tot_data_len = 0; + if (mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { + g_size--; + gtot_size--; + tot_data_len = oid_len + ptot_size + otot_size + gtot_size + ytot_size; + oid = oid_ri; + } + else { + tot_data_len = oid_len + ptot_size + atot_size + btot_size + gtot_size + otot_size + ytot_size + + ctot_size; + } + tot_len = asn1_len_tag(0x7f49, tot_data_len); if (buf == NULL || buf_len == 0) { return tot_len; } @@ -102,50 +113,56 @@ size_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, siz } uint8_t *p = buf; memcpy(p, "\x7F\x49", 2); p += 2; - p += format_tlv_len( - oid_len + ptot_size + atot_size + btot_size + gtot_size + otot_size + ytot_size + ctot_size, - p); + p += format_tlv_len(tot_data_len, p); //oid - *p++ = 0x6; p += format_tlv_len(sizeof(oid_ecdsa), p); memcpy(p, oid_ecdsa, sizeof(oid_ecdsa)); + *p++ = 0x6; p += format_tlv_len(sizeof(oid_ecdsa), p); memcpy(p, oid, sizeof(oid_ecdsa)); p += sizeof(oid_ecdsa); - //p - *p++ = 0x81; p += format_tlv_len(p_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.P, p, p_size); - p += p_size; - //A - if (a_size) { - *p++ = 0x82; p += format_tlv_len(a_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.A, p, a_size); p += a_size; - } - else { //mbedtls does not set point A for some curves - if (pointA[ecdsa->grp.id] && ecdsa->grp.id < 6) { - *p++ = 0x82; p += format_tlv_len(p_size, p); memcpy(p, pointA[ecdsa->grp.id], p_size); - p += p_size; - } - else { - *p++ = 0x82; p += format_tlv_len(1, p); - *p++ = 0x0; - } - } - //B - *p++ = 0x83; p += format_tlv_len(b_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.B, p, b_size); - p += b_size; - //G - size_t g_new_size = 0; - *p++ = 0x84; p += format_tlv_len(g_size, p); mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->grp.G, MBEDTLS_ECP_PF_UNCOMPRESSED, &g_new_size, p, g_size); - p += g_size; - //order - *p++ = 0x85; p += format_tlv_len(o_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.N, p, o_size); - p += o_size; - //Y - *p++ = 0x86; p += format_tlv_len(y_size, p); memcpy(p, Y_buf, y_size); p += y_size; - //cofactor - *p++ = 0x87; p += format_tlv_len(c_size, p); - if (ecdsa->grp.id == MBEDTLS_ECP_DP_CURVE448) { - *p++ = 4; - } - else if (ecdsa->grp.id == MBEDTLS_ECP_DP_CURVE25519) { - *p++ = 8; + if (mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { + //p + *p++ = 0x81; p += format_tlv_len(p_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.P, p, p_size); + p += p_size; + //order + *p++ = 0x82; p += format_tlv_len(o_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.N, p, o_size); + p += o_size; + //G + size_t g_new_size = 0; + *p++ = 0x83; p += format_tlv_len(g_size, p); mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->grp.G, MBEDTLS_ECP_PF_UNCOMPRESSED, &g_new_size, p, g_size); + p += g_size; + //Y + *p++ = 0x84; p += format_tlv_len(y_size, p); memcpy(p, Y_buf, y_size); p += y_size; } else { + //p + *p++ = 0x81; p += format_tlv_len(p_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.P, p, p_size); + p += p_size; + //A + if (a_size) { + *p++ = 0x82; p += format_tlv_len(a_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.A, p, a_size); p += a_size; + } + else { //mbedtls does not set point A for some curves + if (pointA[ecdsa->grp.id] && ecdsa->grp.id < 6) { + *p++ = 0x82; p += format_tlv_len(p_size, p); memcpy(p, pointA[ecdsa->grp.id], p_size); + p += p_size; + } + else { + *p++ = 0x82; p += format_tlv_len(1, p); + *p++ = 0x0; + } + } + //B + *p++ = 0x83; p += format_tlv_len(b_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.B, p, b_size); + p += b_size; + //G + size_t g_new_size = 0; + *p++ = 0x84; p += format_tlv_len(g_size, p); mbedtls_ecp_point_write_binary(&ecdsa->grp, &ecdsa->grp.G, MBEDTLS_ECP_PF_UNCOMPRESSED, &g_new_size, p, g_size); + p += g_size; + //order + *p++ = 0x85; p += format_tlv_len(o_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.N, p, o_size); + p += o_size; + //Y + *p++ = 0x86; p += format_tlv_len(y_size, p); memcpy(p, Y_buf, y_size); p += y_size; + //cofactor + *p++ = 0x87; p += format_tlv_len(c_size, p); *p++ = 1; } return tot_len; From c6a5272340fdcb6db047899b0c5272c444206ce2 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 23 Aug 2023 16:39:21 +0200 Subject: [PATCH 3/5] Added test for Curve25519 and Curve448 keypair generation. Signed-off-by: Pol Henarejos --- tests/pico-hsm/test_020_keypair_gen.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/pico-hsm/test_020_keypair_gen.py b/tests/pico-hsm/test_020_keypair_gen.py index 486d10a..dcceaa8 100644 --- a/tests/pico-hsm/test_020_keypair_gen.py +++ b/tests/pico-hsm/test_020_keypair_gen.py @@ -24,7 +24,7 @@ def test_gen_initialize(device): device.initialize() @pytest.mark.parametrize( - "curve", ['secp192r1', 'secp256r1', 'secp384r1', 'secp521r1', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1', 'secp192k1', 'secp256k1'] + "curve", ['secp192r1', 'secp256r1', 'secp384r1', 'secp521r1', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1', 'secp192k1', 'secp256k1', 'curve25519', 'curve448'] ) def test_gen_ecc(device, curve): keyid = device.key_generation(KeyType.ECC, curve) From 0e1c82196aa5daeb3fe8c4ec7bc252dd55f38275 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 23 Aug 2023 16:39:32 +0200 Subject: [PATCH 4/5] Added test for Curve25519 and Curve448 key import. Signed-off-by: Pol Henarejos --- tests/pico-hsm/test_021_key_import.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/pico-hsm/test_021_key_import.py b/tests/pico-hsm/test_021_key_import.py index 02c1fc5..1eca43b 100644 --- a/tests/pico-hsm/test_021_key_import.py +++ b/tests/pico-hsm/test_021_key_import.py @@ -21,7 +21,8 @@ import pytest import hashlib import os from picohsm import DOPrefixes -from cryptography.hazmat.primitives.asymmetric import rsa, ec +from cryptography.hazmat.primitives.asymmetric import rsa, ec, x25519, x448 +from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat from picohsm.const import DEFAULT_RETRIES, DEFAULT_DKEK_SHARES from const import DEFAULT_DKEK @@ -58,6 +59,17 @@ def test_import_ecc(device, curve): device.delete_file(DOPrefixes.KEY_PREFIX, keyid) device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX, keyid) +@pytest.mark.parametrize( + "curve", [x25519.X25519PrivateKey, x448.X448PrivateKey] +) +def test_import_montgomery(device, curve): + pkey = curve.generate() + keyid = device.import_key(pkey) + pubkey = device.public_key(keyid, param=curve) + assert(pubkey.public_bytes(Encoding.Raw, PublicFormat.Raw) == pkey.public_key().public_bytes(Encoding.Raw, PublicFormat.Raw)) + device.delete_file(DOPrefixes.KEY_PREFIX, keyid) + device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX, keyid) + @pytest.mark.parametrize( "size", [128, 192, 256] ) From e18c4132680cc2efac2f5baf40bfbd19aaf13e44 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Wed, 23 Aug 2023 16:42:34 +0200 Subject: [PATCH 5/5] Added X25519 and X448 exchange test. Signed-off-by: Pol Henarejos --- tests/pico-hsm/test_022_key_exchange.py | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/tests/pico-hsm/test_022_key_exchange.py b/tests/pico-hsm/test_022_key_exchange.py index bc74543..707314d 100644 --- a/tests/pico-hsm/test_022_key_exchange.py +++ b/tests/pico-hsm/test_022_key_exchange.py @@ -20,7 +20,7 @@ import pytest import hashlib from picohsm import DOPrefixes -from cryptography.hazmat.primitives.asymmetric import ec +from cryptography.hazmat.primitives.asymmetric import ec, x25519, x448 from picohsm.const import DEFAULT_RETRIES, DEFAULT_DKEK_SHARES from const import DEFAULT_DKEK @@ -51,3 +51,24 @@ def test_exchange_ecc(device, curve): device.delete_file(DOPrefixes.KEY_PREFIX, keyid) device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX, keyid) + +@pytest.mark.parametrize( + "curve", [x25519.X25519PrivateKey, x448.X448PrivateKey] +) +def test_exchange_montgomery(device, curve): + pkeyA = curve.generate() + pbkeyA = pkeyA.public_key() + keyid = device.import_key(pkeyA) + pkeyB = curve.generate() + pbkeyB = pkeyB.public_key() + + sharedB = pkeyB.exchange(pbkeyA) + sharedA = device.exchange(keyid, pbkeyB) + + assert(sharedA == sharedB) + + sharedAA = pkeyA.exchange(pbkeyB) + assert(sharedA == sharedAA) + + device.delete_file(DOPrefixes.KEY_PREFIX, keyid) + device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX, keyid)