diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index 5558edc..9b4c44e 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -35,7 +35,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 9f0b4ba..213100b 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -14,10 +14,10 @@ name: "Emulation and test" on: workflow_dispatch: push: - branches: [ "main", "piv" ] + branches: [ "main", "piv", "eddsa" ] pull_request: # The branches below must be a subset of the branches above - branches: [ "main", "piv" ] + branches: [ "main", "piv", "eddsa" ] schedule: - cron: '23 5 * * 4' diff --git a/build_pico_openpgp.sh b/build_pico_openpgp.sh index 9f150f3..1d52c87 100755 --- a/build_pico_openpgp.sh +++ b/build_pico_openpgp.sh @@ -1,7 +1,7 @@ #!/bin/bash VERSION_MAJOR="3" -VERSION_MINOR="4" +VERSION_MINOR="4-eddsa1" SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}" #if ! [[ -z "${GITHUB_SHA}" ]]; then # SUFFIX="${SUFFIX}.${GITHUB_SHA}" diff --git a/pico-keys-sdk b/pico-keys-sdk index 07415e6..6ec374a 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 07415e6e8be36255fbcd3e5c3aeec394c7b76bac +Subproject commit 6ec374a6ac53a4de34ed26ae19be126fe7c704e7 diff --git a/src/openpgp/CMakeLists.txt b/src/openpgp/CMakeLists.txt index 31d66c9..a0fff70 100644 --- a/src/openpgp/CMakeLists.txt +++ b/src/openpgp/CMakeLists.txt @@ -1,6 +1,6 @@ idf_component_register( SRCS ${SOURCES} - INCLUDE_DIRS . ../../pico-keys-sdk/src ../../pico-keys-sdk/src/fs ../../pico-keys-sdk/src/rng ../../pico-keys-sdk/src/usb + INCLUDE_DIRS . ../../pico-keys-sdk/src ../../pico-keys-sdk/src/fs ../../pico-keys-sdk/src/rng ../../pico-keys-sdk/src/usb ../../pico-keys-sdk/tinycbor/src REQUIRES bootloader_support esp_partition esp_tinyusb zorxx__neopixel mbedtls efuse ) idf_component_set_property(${COMPONENT_NAME} WHOLE_ARCHIVE ON) diff --git a/src/openpgp/cmd_import_data.c b/src/openpgp/cmd_import_data.c index 74df4ec..e17df7d 100644 --- a/src/openpgp/cmd_import_data.c +++ b/src/openpgp/cmd_import_data.c @@ -156,8 +156,8 @@ int cmd_import_data() { return SW_EXEC_ERROR(); } } - else if (algo[0] == ALGO_ECDSA || algo[0] == ALGO_ECDH) { - mbedtls_ecdsa_context ecdsa; + else if (algo[0] == ALGO_ECDSA || algo[0] == ALGO_ECDH || algo[0] == ALGO_EDDSA) { + mbedtls_ecp_keypair ecdsa; if (p[1] == NULL || len[1] == 0) { return SW_WRONG_DATA(); } @@ -165,7 +165,7 @@ int cmd_import_data() { if (gid == MBEDTLS_ECP_DP_NONE) { return SW_FUNC_NOT_SUPPORTED(); } - mbedtls_ecdsa_init(&ecdsa); + mbedtls_ecp_keypair_init(&ecdsa); if (gid == MBEDTLS_ECP_DP_CURVE25519) { mbedtls_ecp_group_load(&ecdsa.grp, gid); r = mbedtls_mpi_read_binary(&ecdsa.d, p[1], len[1]); @@ -174,17 +174,22 @@ int cmd_import_data() { r = mbedtls_ecp_read_key(gid, &ecdsa, p[1], len[1]); } if (r != 0) { - mbedtls_ecdsa_free(&ecdsa); + mbedtls_ecp_keypair_free(&ecdsa); return SW_EXEC_ERROR(); } - r = mbedtls_ecp_mul(&ecdsa.grp, &ecdsa.Q, &ecdsa.d, &ecdsa.grp.G, random_gen, NULL); + if (ecdsa.grp.id == MBEDTLS_ECP_DP_ED25519) { + r = mbedtls_ecp_point_edwards(&ecdsa.grp, &ecdsa.Q, &ecdsa.d, random_gen, NULL); + } + else { + r = mbedtls_ecp_mul(&ecdsa.grp, &ecdsa.Q, &ecdsa.d, &ecdsa.grp.G, random_gen, NULL); + } if (r != 0) { - mbedtls_ecdsa_free(&ecdsa); + mbedtls_ecp_keypair_free(&ecdsa); return SW_EXEC_ERROR(); } r = store_keys(&ecdsa, ALGO_ECDSA, fid, true); make_ecdsa_response(&ecdsa); - mbedtls_ecdsa_free(&ecdsa); + mbedtls_ecp_keypair_free(&ecdsa); if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } diff --git a/src/openpgp/cmd_internal_aut.c b/src/openpgp/cmd_internal_aut.c index 92d4c07..869bb22 100644 --- a/src/openpgp/cmd_internal_aut.c +++ b/src/openpgp/cmd_internal_aut.c @@ -57,17 +57,17 @@ int cmd_internal_aut() { } res_APDU_size = olen; } - else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA) { - mbedtls_ecdsa_context ctx; - mbedtls_ecdsa_init(&ctx); + else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA || algo[0] == ALGO_EDDSA) { + mbedtls_ecp_keypair ctx; + mbedtls_ecp_keypair_init(&ctx); r = load_private_key_ecdsa(&ctx, ef, true); if (r != PICOKEY_OK) { - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); return SW_EXEC_ERROR(); } size_t olen = 0; r = ecdsa_sign(&ctx, apdu.data, apdu.nc, res_APDU, &olen); - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); if (r != 0) { return SW_EXEC_ERROR(); } diff --git a/src/openpgp/cmd_keypair_gen.c b/src/openpgp/cmd_keypair_gen.c index 9329350..23a91a4 100644 --- a/src/openpgp/cmd_keypair_gen.c +++ b/src/openpgp/cmd_keypair_gen.c @@ -76,23 +76,23 @@ int cmd_keypair_gen() { return SW_EXEC_ERROR(); } } - else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA) { + else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA || algo[0] == ALGO_EDDSA) { printf("KEYPAIR ECDSA\r\n"); mbedtls_ecp_group_id gid = get_ec_group_id_from_attr(algo + 1, algo_len - 1); if (gid == MBEDTLS_ECP_DP_NONE) { return SW_FUNC_NOT_SUPPORTED(); } - mbedtls_ecdsa_context ecdsa; - mbedtls_ecdsa_init(&ecdsa); + mbedtls_ecp_keypair ecdsa; + mbedtls_ecp_keypair_init(&ecdsa); uint8_t index = 0; r = mbedtls_ecdsa_genkey(&ecdsa, gid, random_gen, &index); if (r != 0) { - mbedtls_ecdsa_free(&ecdsa); + mbedtls_ecp_keypair_free(&ecdsa); return SW_EXEC_ERROR(); } r = store_keys(&ecdsa, algo[0], fid, true); make_ecdsa_response(&ecdsa); - mbedtls_ecdsa_free(&ecdsa); + mbedtls_ecp_keypair_free(&ecdsa); if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } diff --git a/src/openpgp/cmd_pso.c b/src/openpgp/cmd_pso.c index fd5a891..e2e9ba0 100644 --- a/src/openpgp/cmd_pso.c +++ b/src/openpgp/cmd_pso.c @@ -137,18 +137,18 @@ int cmd_pso() { res_APDU_size = olen; } } - else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA) { + else if (algo[0] == ALGO_ECDH || algo[0] == ALGO_ECDSA || algo[0] == ALGO_EDDSA) { if (P1(apdu) == 0x9E && P2(apdu) == 0x9A) { - mbedtls_ecdsa_context ctx; - mbedtls_ecdsa_init(&ctx); + mbedtls_ecp_keypair ctx; + mbedtls_ecp_keypair_init(&ctx); r = load_private_key_ecdsa(&ctx, ef, true); if (r != PICOKEY_OK) { - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); return SW_EXEC_ERROR(); } size_t olen = 0; r = ecdsa_sign(&ctx, apdu.data, apdu.nc, res_APDU, &olen); - mbedtls_ecdsa_free(&ctx); + mbedtls_ecp_keypair_free(&ctx); if (r != 0) { return SW_EXEC_ERROR(); } diff --git a/src/openpgp/do.c b/src/openpgp/do.c index 28b0a72..0f76bc0 100644 --- a/src/openpgp/do.c +++ b/src/openpgp/do.c @@ -275,6 +275,12 @@ const uint8_t algorithm_attr_cv25519[] = { 0x2b, 0x06, 0x01, 0x04, 0x01, 0x97, 0x55, 0x01, 0x05, 0x01 }; +const uint8_t algorithm_attr_ed25519[] = { + 10, + ALGO_EDDSA, + 0x2b, 0x06, 0x01, 0x04, 0x01, 0xda, 0x47, 0x0f, 0x01 +}; + int parse_algo(const uint8_t *algo, uint16_t tag) { res_APDU[res_APDU_size++] = tag & 0xff; memcpy(res_APDU + res_APDU_size, algo, algo[0] + 1); @@ -300,6 +306,7 @@ int parse_algoinfo(const file_t *f, int mode) { datalen += parse_algo(algorithm_attr_bp256r1, EF_ALGO_SIG); datalen += parse_algo(algorithm_attr_bp384r1, EF_ALGO_SIG); datalen += parse_algo(algorithm_attr_bp512r1, EF_ALGO_SIG); + datalen += parse_algo(algorithm_attr_ed25519, EF_ALGO_SIG); datalen += parse_algo(algorithm_attr_rsa1k, EF_ALGO_DEC); datalen += parse_algo(algorithm_attr_rsa2k, EF_ALGO_DEC); @@ -326,6 +333,7 @@ int parse_algoinfo(const file_t *f, int mode) { datalen += parse_algo(algorithm_attr_bp256r1, EF_ALGO_AUT); datalen += parse_algo(algorithm_attr_bp384r1, EF_ALGO_AUT); datalen += parse_algo(algorithm_attr_bp512r1, EF_ALGO_AUT); + datalen += parse_algo(algorithm_attr_ed25519, EF_ALGO_AUT); uint16_t lpdif = res_APDU + res_APDU_size - lp - 2; *lp++ = lpdif >> 8; *lp++ = lpdif & 0xff; diff --git a/src/openpgp/do.h b/src/openpgp/do.h index 1a34242..d340fdb 100644 --- a/src/openpgp/do.h +++ b/src/openpgp/do.h @@ -26,3 +26,4 @@ extern const uint8_t algorithm_attr_cv25519[]; extern const uint8_t algorithm_attr_x448[]; extern const uint8_t algorithm_attr_rsa2k[]; extern const uint8_t algorithm_attr_rsa4096[]; +extern const uint8_t algorithm_attr_ed25519[]; diff --git a/src/openpgp/openpgp.c b/src/openpgp/openpgp.c index 6a55d00..0b30b7a 100644 --- a/src/openpgp/openpgp.c +++ b/src/openpgp/openpgp.c @@ -30,6 +30,7 @@ #include "ccid/ccid.h" #include "otp.h" #include "do.h" +#include "mbedtls/eddsa.h" uint8_t PICO_PRODUCT = 3; @@ -488,8 +489,8 @@ int store_keys(void *key_ctx, int type, uint16_t key_id, bool use_kek) { mbedtls_mpi_write_binary(&rsa->P, kdata, key_size / 2); mbedtls_mpi_write_binary(&rsa->Q, kdata + key_size / 2, key_size / 2); } - else if (type == ALGO_ECDSA || type == ALGO_ECDH) { - mbedtls_ecdsa_context *ecdsa = (mbedtls_ecdsa_context *) key_ctx; + else if (type == ALGO_ECDSA || type == ALGO_ECDH || type == ALGO_EDDSA) { + mbedtls_ecp_keypair *ecdsa = (mbedtls_ecp_keypair *) key_ctx; size_t olen = 0; kdata[0] = ecdsa->grp.id & 0xff; mbedtls_ecp_write_key_ext(ecdsa, &olen, kdata + 1, sizeof(kdata) - 1); @@ -558,7 +559,7 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey, bool use_dek) { return PICOKEY_OK; } -int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey, bool use_dek) { +int load_private_key_ecdsa(mbedtls_ecp_keypair *ctx, file_t *fkey, bool use_dek) { int key_size = file_get_size(fkey); uint8_t kdata[67]; //Worst case, 521 bit + 1byte memcpy(kdata, file_get_data(fkey), key_size); @@ -568,11 +569,16 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey, bool use_de mbedtls_ecp_group_id gid = kdata[0]; int r = mbedtls_ecp_read_key(gid, ctx, kdata + 1, key_size - 1); if (r != 0) { - 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); + if (ctx->grp.id == MBEDTLS_ECP_DP_ED25519) { + r = mbedtls_ecp_point_edwards(&ctx->grp, &ctx->Q, &ctx->d, random_gen, NULL); + } + else { + r = mbedtls_ecp_mul(&ctx->grp, &ctx->Q, &ctx->d, &ctx->grp.G, random_gen, NULL); + } if (r != 0) { mbedtls_ecdsa_free(ctx); return PICOKEY_EXEC_ERROR; @@ -617,6 +623,9 @@ mbedtls_ecp_group_id get_ec_group_id_from_attr(const uint8_t *algo, size_t algo_ else if (memcmp(algorithm_attr_x448 + 2, algo, algo_len) == 0) { return MBEDTLS_ECP_DP_CURVE448; } + else if (memcmp(algorithm_attr_ed25519 + 2, algo, algo_len) == 0) { + return MBEDTLS_ECP_DP_ED25519; + } return MBEDTLS_ECP_DP_NONE; } @@ -635,7 +644,7 @@ void make_rsa_response(mbedtls_rsa_context *rsa) { put_uint16_t_be(res_APDU_size - 5, res_APDU + 3); } -void make_ecdsa_response(mbedtls_ecdsa_context *ecdsa) { +void make_ecdsa_response(mbedtls_ecp_keypair *ecdsa) { uint8_t pt[MBEDTLS_ECP_MAX_PT_LEN]; size_t plen = 0; mbedtls_ecp_point_write_binary(&ecdsa->grp, @@ -728,23 +737,30 @@ int rsa_sign(mbedtls_rsa_context *ctx, return r; } -int ecdsa_sign(mbedtls_ecdsa_context *ctx, +int ecdsa_sign(mbedtls_ecp_keypair *ctx, const uint8_t *data, size_t data_len, uint8_t *out, size_t *out_len) { - mbedtls_mpi ri, si; - mbedtls_mpi_init(&ri); - mbedtls_mpi_init(&si); - int r = mbedtls_ecdsa_sign(&ctx->grp, &ri, &si, &ctx->d, data, data_len, random_gen, NULL); - if (r == 0) { - size_t plen = (ctx->grp.nbits + 7) / 8; - mbedtls_mpi_write_binary(&ri, out, plen); - mbedtls_mpi_write_binary(&si, out + plen, plen); - *out_len = 2 * plen; + + int r = 0; + if (ctx->grp.id == MBEDTLS_ECP_DP_ED25519) { + r = mbedtls_eddsa_write_signature(ctx, data, data_len, out, 64, out_len, MBEDTLS_EDDSA_PURE, NULL, 0, random_gen, NULL); + } + else { + mbedtls_mpi ri, si; + mbedtls_mpi_init(&ri); + mbedtls_mpi_init(&si); + r = mbedtls_ecdsa_sign(&ctx->grp, &ri, &si, &ctx->d, data, data_len, random_gen, NULL); + if (r == 0) { + size_t plen = (ctx->grp.nbits + 7) / 8; + mbedtls_mpi_write_binary(&ri, out, plen); + mbedtls_mpi_write_binary(&si, out + plen, plen); + *out_len = 2 * plen; + } + mbedtls_mpi_free(&ri); + mbedtls_mpi_free(&si); } - mbedtls_mpi_free(&ri); - mbedtls_mpi_free(&si); return r; } diff --git a/src/openpgp/openpgp.h b/src/openpgp/openpgp.h index 2072262..c08ff75 100644 --- a/src/openpgp/openpgp.h +++ b/src/openpgp/openpgp.h @@ -59,6 +59,7 @@ extern int pin_reset_retries(const file_t *pin, bool force); #define ALGO_RSA 0x01 #define ALGO_ECDH 0x12 #define ALGO_ECDSA 0x13 +#define ALGO_EDDSA 0x16 #define ALGO_AES 0x70 #define ALGO_AES_128 0x71 #define ALGO_AES_192 0x72