diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 005214e..c846265 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -13,10 +13,10 @@ name: "CodeQL" on: push: - branches: [ "master", "development" ] + branches: [ "master", "development", "development-eddsa" ] pull_request: # The branches below must be a subset of the branches above - branches: [ "master", "development" ] + branches: [ "master", "development", "development-eddsa" ] schedule: - cron: '23 5 * * 4' workflow_dispatch: @@ -36,7 +36,7 @@ jobs: language: [ 'cpp', 'python' ] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support - mode: [ 'pico', 'esp32', 'local' ] + mode: [ 'pico', 'local' ] steps: - name: Checkout repository diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 31ea897..7d870eb 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -13,10 +13,10 @@ name: "Emulation and test" on: push: - branches: [ "master", "development" ] + branches: [ "master", "development", "development-eddsa" ] pull_request: # The branches below must be a subset of the branches above - branches: [ "master", "development" ] + branches: [ "master", "development", "development-eddsa" ] schedule: - cron: '23 5 * * 4' workflow_dispatch: diff --git a/pico-keys-sdk b/pico-keys-sdk index 07415e6..0a4c7b0 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 07415e6e8be36255fbcd3e5c3aeec394c7b76bac +Subproject commit 0a4c7b098117e58ec4b3452578846d4a36ab3530 diff --git a/src/hsm/cmd_cipher_sym.c b/src/hsm/cmd_cipher_sym.c index 6785643..09bb234 100644 --- a/src/hsm/cmd_cipher_sym.c +++ b/src/hsm/cmd_cipher_sym.c @@ -655,7 +655,7 @@ int cmd_cipher_sym() { secret[64] = { 0 }; mbedtls_aes_init(&ctx); if (hd_keytype != 0x3) { - mbedtls_ecdsa_free(&hd_context); + mbedtls_ecp_keypair_free(&hd_context); return SW_INCORRECT_PARAMS(); } key_size = 32; @@ -689,7 +689,7 @@ int cmd_cipher_sym() { return SW_EXEC_ERROR(); } res_APDU_size = enc.len; - mbedtls_ecdsa_free(&hd_context); + mbedtls_ecp_keypair_free(&hd_context); hd_keytype = 0; } else { diff --git a/src/hsm/cmd_derive_asym.c b/src/hsm/cmd_derive_asym.c index 5d5437e..a1883b7 100644 --- a/src/hsm/cmd_derive_asym.c +++ b/src/hsm/cmd_derive_asym.c @@ -52,13 +52,13 @@ int cmd_derive_asym() { return SW_WRONG_LENGTH(); } if (apdu.data[0] == ALGO_EC_DERIVE) { - mbedtls_ecdsa_context ctx; - mbedtls_ecdsa_init(&ctx); + mbedtls_ecp_keypair ctx; + mbedtls_ecp_keypair_init(&ctx); int r; - r = load_private_key_ecdsa(&ctx, fkey); + r = load_private_key_ec(&ctx, fkey); if (r != PICOKEY_OK) { - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); if (r == PICOKEY_VERIFICATION_FAILED) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } @@ -69,7 +69,7 @@ int cmd_derive_asym() { mbedtls_mpi_init(&nd); r = mbedtls_mpi_read_binary(&a, apdu.data + 1, apdu.nc - 1); if (r != 0) { - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); mbedtls_mpi_free(&a); mbedtls_mpi_free(&nd); return SW_DATA_INVALID(); @@ -77,22 +77,22 @@ int cmd_derive_asym() { r = mbedtls_mpi_add_mod(&ctx.grp, &nd, &ctx.d, &a); mbedtls_mpi_free(&a); if (r != 0) { - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); mbedtls_mpi_free(&nd); return SW_EXEC_ERROR(); } r = mbedtls_mpi_copy(&ctx.d, &nd); mbedtls_mpi_free(&nd); if (r != 0) { - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); return SW_EXEC_ERROR(); } r = store_keys(&ctx, PICO_KEYS_KEY_EC, dest_id); if (r != PICOKEY_OK) { - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); return SW_EXEC_ERROR(); } - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); } else { return SW_WRONG_DATA(); diff --git a/src/hsm/cmd_general_authenticate.c b/src/hsm/cmd_general_authenticate.c index 6f80464..b35ba21 100644 --- a/src/hsm/cmd_general_authenticate.c +++ b/src/hsm/cmd_general_authenticate.c @@ -44,11 +44,11 @@ int cmd_general_authenticate() { if (!fkey) { return SW_EXEC_ERROR(); } - mbedtls_ecdsa_context ectx; - mbedtls_ecdsa_init(&ectx); - r = load_private_key_ecdsa(&ectx, fkey); + mbedtls_ecp_keypair ectx; + mbedtls_ecp_keypair_init(&ectx); + r = load_private_key_ecdh(&ectx, fkey); if (r != PICOKEY_OK) { - mbedtls_ecdsa_free(&ectx); + mbedtls_ecp_keypair_free(&ectx); return SW_EXEC_ERROR(); } mbedtls_ecdh_context ctx; @@ -56,12 +56,12 @@ int cmd_general_authenticate() { mbedtls_ecp_group_id gid = MBEDTLS_ECP_DP_SECP256R1; r = mbedtls_ecdh_setup(&ctx, gid); if (r != 0) { - mbedtls_ecdsa_free(&ectx); + mbedtls_ecp_keypair_free(&ectx); mbedtls_ecdh_free(&ctx); return SW_DATA_INVALID(); } r = mbedtls_mpi_copy(&ctx.ctx.mbed_ecdh.d, &ectx.d); - mbedtls_ecdsa_free(&ectx); + mbedtls_ecp_keypair_free(&ectx); if (r != 0) { mbedtls_ecdh_free(&ctx); return SW_DATA_INVALID(); diff --git a/src/hsm/cmd_key_unwrap.c b/src/hsm/cmd_key_unwrap.c index d6ffadf..4cb27e8 100644 --- a/src/hsm/cmd_key_unwrap.c +++ b/src/hsm/cmd_key_unwrap.c @@ -67,21 +67,21 @@ int cmd_key_unwrap() { } } else if (key_type & PICO_KEYS_KEY_EC) { - mbedtls_ecdsa_context ctx; - mbedtls_ecdsa_init(&ctx); + mbedtls_ecp_keypair ctx; + mbedtls_ecp_keypair_init(&ctx); do { r = dkek_decode_key((uint8_t)++kdom, &ctx, data, data_len, NULL, &allowed, &allowed_len); } while ((r == PICOKEY_ERR_FILE_NOT_FOUND || r == PICOKEY_WRONG_DKEK) && kdom < MAX_KEY_DOMAINS); if (r != PICOKEY_OK) { - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); return SW_EXEC_ERROR(); } r = store_keys(&ctx, PICO_KEYS_KEY_EC, key_id); if ((res_APDU_size = (uint16_t)asn1_cvc_aut(&ctx, PICO_KEYS_KEY_EC, res_APDU, MAX_APDU_DATA, NULL, 0)) == 0) { - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); return SW_EXEC_ERROR(); } - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } diff --git a/src/hsm/cmd_key_wrap.c b/src/hsm/cmd_key_wrap.c index 3825c72..d328f64 100644 --- a/src/hsm/cmd_key_wrap.c +++ b/src/hsm/cmd_key_wrap.c @@ -71,18 +71,18 @@ int cmd_key_wrap() { mbedtls_rsa_free(&ctx); } else if (*dprkd == P15_KEYTYPE_ECC) { - mbedtls_ecdsa_context ctx; - mbedtls_ecdsa_init(&ctx); - r = load_private_key_ecdsa(&ctx, ef); + mbedtls_ecp_keypair ctx; + mbedtls_ecp_keypair_init(&ctx); + r = load_private_key_ec(&ctx, ef); if (r != PICOKEY_OK) { - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); if (r == PICOKEY_VERIFICATION_FAILED) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } return SW_EXEC_ERROR(); } r = dkek_encode_key(kdom, &ctx, PICO_KEYS_KEY_EC, res_APDU, &wrap_len, meta_tag, tag_len); - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); } else if (*dprkd == P15_KEYTYPE_AES) { uint8_t kdata_aes[64]; //maximum AES key size diff --git a/src/hsm/cmd_keypair_gen.c b/src/hsm/cmd_keypair_gen.c index 42ea90b..3c9905c 100644 --- a/src/hsm/cmd_keypair_gen.c +++ b/src/hsm/cmd_keypair_gen.c @@ -78,6 +78,21 @@ int cmd_keypair_gen() { if (ec_id == MBEDTLS_ECP_DP_NONE) { return SW_FUNC_NOT_SUPPORTED(); } + if (ec_id == MBEDTLS_ECP_DP_CURVE25519 || ec_id == MBEDTLS_ECP_DP_CURVE448) { + asn1_ctx_t g = { 0 }; + if (asn1_find_tag(&ctxo, 0x83, &g) != true) { + return SW_WRONG_DATA(); + } +#ifdef MBEDTLS_EDDSA_C + if (ec_id == MBEDTLS_ECP_DP_CURVE25519 && (g.data[0] != 9)) { + ec_id = MBEDTLS_ECP_DP_ED25519; + } + else if (ec_id == MBEDTLS_ECP_DP_CURVE448 && (g.len != 56 || g.data[0] != 5)) { + ec_id = MBEDTLS_ECP_DP_ED448; + } +#endif + } + printf("KEYPAIR ECC %d\r\n", ec_id); mbedtls_ecdsa_context ecdsa; mbedtls_ecdsa_init(&ecdsa); uint8_t index = 0; diff --git a/src/hsm/cmd_signature.c b/src/hsm/cmd_signature.c index 69fba07..d3896a5 100644 --- a/src/hsm/cmd_signature.c +++ b/src/hsm/cmd_signature.c @@ -20,6 +20,9 @@ #include "asn1.h" #include "mbedtls/oid.h" #include "random.h" +#ifdef MBEDTLS_EDDSA_C +#include "mbedtls/eddsa.h" +#endif extern mbedtls_ecp_keypair hd_context; extern uint8_t hd_keytype; @@ -228,8 +231,8 @@ int cmd_signature() { mbedtls_rsa_free(&ctx); } else if (p2 >= ALGO_EC_RAW && p2 <= ALGO_EC_SHA512) { - mbedtls_ecdsa_context ctx; - mbedtls_ecdsa_init(&ctx); + mbedtls_ecp_keypair ctx; + mbedtls_ecp_keypair_init(&ctx); md = MBEDTLS_MD_SHA256; if (p2 == ALGO_EC_RAW) { if (apdu.nc == 32) { @@ -263,9 +266,9 @@ int cmd_signature() { else if (p2 == ALGO_EC_SHA512) { md = MBEDTLS_MD_SHA512; } - int r = load_private_key_ecdsa(&ctx, fkey); + int r = load_private_key_ec(&ctx, fkey); if (r != PICOKEY_OK) { - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); if (r == PICOKEY_VERIFICATION_FAILED) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } @@ -273,36 +276,45 @@ int cmd_signature() { } size_t olen = 0; uint8_t buf[MBEDTLS_ECDSA_MAX_LEN]; - if (mbedtls_ecdsa_write_signature(&ctx, md, apdu.data, apdu.nc, buf, MBEDTLS_ECDSA_MAX_LEN, - &olen, random_gen, NULL) != 0) { - mbedtls_ecdsa_free(&ctx); +#ifdef MBEDTLS_EDDSA_C + if (ctx.grp.id == MBEDTLS_ECP_DP_ED25519 || ctx.grp.id == MBEDTLS_ECP_DP_ED448) { + r = mbedtls_eddsa_write_signature(&ctx, apdu.data, apdu.nc, buf, sizeof(buf), &olen, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL); + } + else +#endif + { + r = mbedtls_ecdsa_write_signature(&ctx, md, apdu.data, apdu.nc, buf, MBEDTLS_ECDSA_MAX_LEN, + &olen, random_gen, NULL); + } + if (r != 0) { + mbedtls_ecp_keypair_free(&ctx); return SW_EXEC_ERROR(); } memcpy(res_APDU, buf, olen); res_APDU_size = (uint16_t)olen; - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); } else if (p2 == ALGO_HD) { size_t olen = 0; uint8_t buf[MBEDTLS_ECDSA_MAX_LEN] = {0}; if (hd_context.grp.id == MBEDTLS_ECP_DP_NONE) { - mbedtls_ecdsa_free(&hd_context); + mbedtls_ecp_keypair_free(&hd_context); return SW_CONDITIONS_NOT_SATISFIED(); } if (hd_keytype != 0x1 && hd_keytype != 0x2) { - mbedtls_ecdsa_free(&hd_context); + mbedtls_ecp_keypair_free(&hd_context); return SW_INCORRECT_PARAMS(); } md = MBEDTLS_MD_SHA256; if (mbedtls_ecdsa_write_signature(&hd_context, md, apdu.data, apdu.nc, buf, MBEDTLS_ECDSA_MAX_LEN, &olen, random_gen, NULL) != 0) { - mbedtls_ecdsa_free(&hd_context); + mbedtls_ecp_keypair_free(&hd_context); return SW_EXEC_ERROR(); } memcpy(res_APDU, buf, olen); res_APDU_size = (uint16_t)olen; - mbedtls_ecdsa_free(&hd_context); + mbedtls_ecp_keypair_free(&hd_context); hd_keytype = 0; } else { diff --git a/src/hsm/cvc.c b/src/hsm/cvc.c index 8b6b22e..3ff0f42 100644 --- a/src/hsm/cvc.c +++ b/src/hsm/cvc.c @@ -26,6 +26,9 @@ #include "oid.h" #include "mbedtls/md.h" #include "files.h" +#ifdef MBEDTLS_EDDSA_C +#include "mbedtls/eddsa.h" +#endif extern const uint8_t *dev_name; extern uint16_t dev_name_len; @@ -71,7 +74,7 @@ const uint8_t *pointA[] = { "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", }; -uint16_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, uint16_t buf_len) { +uint16_t asn1_cvc_public_key_ecdsa(mbedtls_ecp_keypair *ecdsa, uint8_t *buf, uint16_t buf_len) { uint8_t Y_buf[MBEDTLS_ECP_MAX_PT_LEN], G_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 }; @@ -88,7 +91,11 @@ uint16_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, u uint16_t ctot_size = asn1_len_tag(0x87, (uint16_t)c_size); uint16_t oid_len = asn1_len_tag(0x6, sizeof(oid_ecdsa)); uint16_t tot_len = 0, tot_data_len = 0; - if (mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { + if (mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY +#ifdef MBEDTLS_EDDSA_C + || mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_EDWARDS +#endif + ) { tot_data_len = oid_len + ptot_size + otot_size + gtot_size + ytot_size; oid = oid_ri; } @@ -109,7 +116,11 @@ uint16_t asn1_cvc_public_key_ecdsa(mbedtls_ecdsa_context *ecdsa, uint8_t *buf, u //oid *p++ = 0x6; p += format_tlv_len(sizeof(oid_ecdsa), p); memcpy(p, oid, sizeof(oid_ecdsa)); p += sizeof(oid_ecdsa); - if (mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { + if (mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY +#ifdef MBEDTLS_EDDSA_C + || mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_EDWARDS +#endif + ) { //p *p++ = 0x81; p += format_tlv_len((uint16_t)p_size, p); mbedtls_mpi_write_binary(&ecdsa->grp.P, p, p_size); p += p_size; @@ -293,11 +304,18 @@ uint16_t asn1_cvc_cert(void *rsa_ecdsa, else if (key_type & PICO_KEYS_KEY_EC) { mbedtls_mpi r, s; int ret = 0; - mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) rsa_ecdsa; + mbedtls_ecp_keypair *ecdsa = (mbedtls_ecp_keypair *) rsa_ecdsa; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); - ret = - mbedtls_ecdsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, hsh, sizeof(hsh), random_gen, NULL); +#ifdef MBEDTLS_EDDSA_C + if (ecdsa->grp.id == MBEDTLS_ECP_DP_ED25519 || ecdsa->grp.id == MBEDTLS_ECP_DP_ED448) { + ret = mbedtls_eddsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, body, body_size, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL); + } + else +#endif + { + ret = mbedtls_ecdsa_sign(&ecdsa->grp, &r, &s, &ecdsa->d, hsh, sizeof(hsh), random_gen, NULL); + } if (ret == 0) { mbedtls_mpi_write_binary(&r, p, key_size / 2); p += key_size / 2; mbedtls_mpi_write_binary(&s, p, key_size / 2); p += key_size / 2; @@ -326,10 +344,10 @@ uint16_t asn1_cvc_aut(void *rsa_ecdsa, if (!fkey) { return 0; } - mbedtls_ecdsa_context ectx; - mbedtls_ecdsa_init(&ectx); - if (load_private_key_ecdsa(&ectx, fkey) != PICOKEY_OK) { - mbedtls_ecdsa_free(&ectx); + mbedtls_ecp_keypair ectx; + mbedtls_ecp_keypair_init(&ectx); + if (load_private_key_ec(&ectx, fkey) != PICOKEY_OK) { + mbedtls_ecp_keypair_free(&ectx); return 0; } int ret = 0; @@ -349,15 +367,23 @@ uint16_t asn1_cvc_aut(void *rsa_ecdsa, p += asn1_cvc_cert(rsa_ecdsa, key_type, p, cvcert_size, ext, ext_len, false); //outcar *p++ = 0x42; p += format_tlv_len(outcar_len, p); memcpy(p, outcar, outcar_len); p += outcar_len; - uint8_t hsh[32]; memcpy(p, "\x5f\x37", 2); p += 2; p += format_tlv_len(key_size, p); - hash256(body, cvcert_size + outcar_size, hsh); mbedtls_mpi r, s; mbedtls_mpi_init(&r); mbedtls_mpi_init(&s); - ret = mbedtls_ecdsa_sign(&ectx.grp, &r, &s, &ectx.d, hsh, sizeof(hsh), random_gen, NULL); - mbedtls_ecdsa_free(&ectx); +#ifdef MBEDTLS_EDDSA_C + if (ectx.grp.id == MBEDTLS_ECP_DP_ED25519 || ectx.grp.id == MBEDTLS_ECP_DP_ED448) { + ret = mbedtls_eddsa_sign(&ectx.grp, &r, &s, &ectx.d, body, cvcert_size + outcar_size, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL); + } + else +#endif + { + uint8_t hsh[32]; + hash256(body, cvcert_size + outcar_size, hsh); + ret = mbedtls_ecdsa_sign(&ectx.grp, &r, &s, &ectx.d, hsh, sizeof(hsh), random_gen, NULL); + } + mbedtls_ecp_keypair_free(&ectx); if (ret != 0) { mbedtls_mpi_free(&r); mbedtls_mpi_free(&s); diff --git a/src/hsm/kek.c b/src/hsm/kek.c index 61a80fa..f51ace4 100644 --- a/src/hsm/kek.c +++ b/src/hsm/kek.c @@ -663,7 +663,16 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le len = get_uint16_t_be(kb + ofs); ofs += len + 2; //G - len = get_uint16_t_be(kb + ofs); ofs += len + 2; + len = get_uint16_t_be(kb + ofs); +#ifdef MBEDTLS_EDDSA_C + if (ec_id == MBEDTLS_ECP_DP_CURVE25519 && kb[ofs + 2] != 0x09) { + ec_id = MBEDTLS_ECP_DP_ED25519; + } + else if (ec_id == MBEDTLS_ECP_DP_CURVE448 && (len != 56 || kb[ofs + 2] != 0x05)) { + ec_id = MBEDTLS_ECP_DP_ED448; + } +#endif + ofs += len + 2; //d len = get_uint16_t_be(kb + ofs); ofs += 2; @@ -678,7 +687,15 @@ int dkek_decode_key(uint8_t id, void *key_ctx, const uint8_t *in, uint16_t in_le len = get_uint16_t_be(kb + ofs); ofs += 2; r = mbedtls_ecp_point_read_binary(&ecdsa->grp, &ecdsa->Q, kb + ofs, len); if (r != 0) { - r = mbedtls_ecp_mul(&ecdsa->grp, &ecdsa->Q, &ecdsa->d, &ecdsa->grp.G, random_gen, NULL); +#ifdef MBEDTLS_EDDSA_C + if (mbedtls_ecp_get_type(&ecdsa->grp) == MBEDTLS_ECP_TYPE_EDWARDS) { + r = mbedtls_ecp_point_edwards(&ecdsa->grp, &ecdsa->Q, &ecdsa->d, random_gen, NULL); + } + else +#endif + { + r = mbedtls_ecp_mul(&ecdsa->grp, &ecdsa->Q, &ecdsa->d, &ecdsa->grp.G, random_gen, NULL); + } if (r != 0) { mbedtls_ecdsa_free(ecdsa); return PICOKEY_EXEC_ERROR; diff --git a/src/hsm/sc_hsm.c b/src/hsm/sc_hsm.c index 9ef933e..e5554bc 100644 --- a/src/hsm/sc_hsm.c +++ b/src/hsm/sc_hsm.c @@ -661,7 +661,7 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey) { return PICOKEY_OK; } -int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) { +int load_private_key_ec(mbedtls_ecp_keypair *ctx, file_t *fkey) { if (wait_button_pressed() == true) { // timeout return PICOKEY_VERIFICATION_FAILED; } @@ -676,17 +676,28 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey) { int r = mbedtls_ecp_read_key(gid, ctx, kdata + 1, key_size - 1); if (r != 0) { mbedtls_platform_zeroize(kdata, sizeof(kdata)); - mbedtls_ecdsa_free(ctx); + mbedtls_ecp_keypair_free(ctx); return PICOKEY_EXEC_ERROR; } mbedtls_platform_zeroize(kdata, sizeof(kdata)); - r = mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL); +#ifdef MBEDTLS_EDDSA_C + if (gid == MBEDTLS_ECP_DP_ED25519 || gid == MBEDTLS_ECP_DP_ED448) { + r = mbedtls_ecp_point_edwards(&ctx->grp, &ctx->Q, &ctx->d, random_gen, NULL); + } + else +#endif + { + r = mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL); + } if (r != 0) { - mbedtls_ecdsa_free(ctx); + mbedtls_ecp_keypair_free(ctx); return PICOKEY_EXEC_ERROR; } return PICOKEY_OK; } +int load_private_key_ecdh(mbedtls_ecp_keypair *ctx, file_t *fkey) { + return load_private_key_ec(ctx, fkey); +} #define INS_VERIFY 0x20 #define INS_MSE 0x22 diff --git a/src/hsm/sc_hsm.h b/src/hsm/sc_hsm.h index c025db5..d799353 100644 --- a/src/hsm/sc_hsm.h +++ b/src/hsm/sc_hsm.h @@ -123,7 +123,8 @@ extern int delete_file(file_t *ef); extern const uint8_t *get_meta_tag(file_t *ef, uint16_t meta_tag, uint16_t *tag_len); extern bool key_has_purpose(file_t *ef, uint8_t purpose); extern int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey); -extern int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey); +extern int load_private_key_ec(mbedtls_ecp_keypair *ctx, file_t *fkey); +extern int load_private_key_ecdh(mbedtls_ecp_keypair *ctx, file_t *fkey); extern bool wait_button_pressed(); extern int store_keys(void *key_ctx, int type, uint8_t key_id); extern int find_and_store_meta_key(uint8_t key_id); diff --git a/tests/build-in-docker.sh b/tests/build-in-docker.sh index 8a42b51..04d4785 100755 --- a/tests/build-in-docker.sh +++ b/tests/build-in-docker.sh @@ -4,7 +4,7 @@ source tests/docker_env.sh build_image #run_in_docker rm -rf CMakeFiles run_in_docker mkdir -p build_in_docker -run_in_docker -w "$PWD/build_in_docker" cmake -DENABLE_EMULATION=1 -D__FOR_CI=1 .. +run_in_docker -w "$PWD/build_in_docker" cmake -DENABLE_EMULATION=1 -D__FOR_CI=1 -DENABLE_EDDSA=1 .. run_in_docker -w "$PWD/build_in_docker" make -j ${NUM_PROC} docker create --name temp_container pico-hsm-test:bullseye docker cp $PWD/build_in_docker/pico_hsm temp_container:/pico_hsm diff --git a/tests/pico-hsm/test_020_keypair_gen.py b/tests/pico-hsm/test_020_keypair_gen.py index dcceaa8..d8edb73 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', 'curve25519', 'curve448'] + "curve", ['secp192r1', 'secp256r1', 'secp384r1', 'secp521r1', 'brainpoolP256r1', 'brainpoolP384r1', 'brainpoolP512r1', 'secp192k1', 'secp256k1', 'curve25519', 'curve448', 'ed25519', 'ed448'] ) def test_gen_ecc(device, curve): keyid = device.key_generation(KeyType.ECC, curve) diff --git a/tests/pico-hsm/test_021_key_import.py b/tests/pico-hsm/test_021_key_import.py index 6129b17..34d47f7 100644 --- a/tests/pico-hsm/test_021_key_import.py +++ b/tests/pico-hsm/test_021_key_import.py @@ -21,7 +21,7 @@ import pytest import hashlib import os from picohsm import DOPrefixes -from cryptography.hazmat.primitives.asymmetric import rsa, ec, x25519, x448 +from cryptography.hazmat.primitives.asymmetric import rsa, ec, x25519, x448, ed25519, ed448 from cryptography.hazmat.primitives.serialization import Encoding, PublicFormat from picohsm.const import DEFAULT_RETRIES, DEFAULT_DKEK_SHARES from const import DEFAULT_DKEK @@ -70,6 +70,17 @@ def test_import_montgomery(device, curve): device.delete_file(DOPrefixes.KEY_PREFIX, keyid) device.delete_file(DOPrefixes.EE_CERTIFICATE_PREFIX, keyid) +@pytest.mark.parametrize( + "curve", [ed25519.Ed25519PrivateKey, ed448.Ed448PrivateKey] +) +def test_import_edwards(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] ) diff --git a/tests/pico-hsm/test_030_signature.py b/tests/pico-hsm/test_030_signature.py index 23fb71f..4b44ade 100644 --- a/tests/pico-hsm/test_030_signature.py +++ b/tests/pico-hsm/test_030_signature.py @@ -55,3 +55,12 @@ def test_signature_rsa(device, modulus, scheme): device.delete_file(DOPrefixes.KEY_PREFIX, keyid) device.verify(pubkey, data, signature, scheme) +@pytest.mark.parametrize( + "curve", ['ed25519', 'ed448'] +) +def test_signature_edwards(device, curve): + keyid = device.key_generation(KeyType.ECC, curve) + pubkey = device.public_key(keyid=keyid) + signature = device.sign(keyid=keyid, scheme=Algorithm.ALGO_EC_RAW, data=data) + device.delete_file(DOPrefixes.KEY_PREFIX, keyid) + device.verify(pubkey, data, signature) diff --git a/tools/pico-hsm-tool.py b/tools/pico-hsm-tool.py index 97af316..b1223f5 100644 --- a/tools/pico-hsm-tool.py +++ b/tools/pico-hsm-tool.py @@ -141,6 +141,8 @@ def parse_args(): parser_keygen_aes.add_argument('--size', help='Specifies the size of AES key [128, 192 or 256]', choices=[128, 192, 256], default=128, type=int) parser_keygen_x25519 = subparser_keygen.add_parser('x25519', help='Generates a private X25519 keypair.') parser_keygen_x448 = subparser_keygen.add_parser('x448', help='Generates a private X448 keypair.') + parser_keygen_x25519 = subparser_keygen.add_parser('ed25519', help='Generates a private Ed25519 keypair.') + parser_keygen_x448 = subparser_keygen.add_parser('ed448', help='Generates a private Ed448 keypair.') parser_otp = subparser.add_parser('otp', help='Read/write OTP values.') parser_otp.add_argument('subcommand', choices=['read', 'write', 'secure_boot'], help='Read, write or enable Secure Boot', nargs='?') @@ -469,8 +471,10 @@ def cipher(picohsm, args): def keygen(picohsm, args): if (args.subcommand == 'aes'): ret = picohsm.key_generation(KeyType.AES, param=args.size) - elif (args.subcommand in ['x25519', 'x448']): - curve = 'curve' + args.subcommand[1:] + elif (args.subcommand in ['x25519', 'x448', 'ed25519', 'ed448']): + curve = args.subcommand + if (args.subcommand in ['x25519', 'x448']): + curve = 'curve' + args.subcommand[1:] ret = picohsm.key_generation(KeyType.ECC, curve) print('Key generated successfully.') print(f'Key ID: {ret}')