diff --git a/CMakeLists.txt b/CMakeLists.txt
index 069b723..b1c7ea9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -20,6 +20,9 @@
if(ESP_PLATFORM)
set(EXTRA_COMPONENT_DIRS src)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
+ if(ESP_PLATFORM)
+ set(EXTRA_COMPONENT_DIRS src)
+ include($ENV{IDF_PATH}/tools/cmake/project.cmake)
else()
if(NOT ENABLE_EMULATION)
set(PICO_USE_FASTEST_SUPPORTED_CLOCK 1)
diff --git a/pico_keys_sdk_import.cmake b/pico_keys_sdk_import.cmake
index fc6ea6b..346febf 100644
--- a/pico_keys_sdk_import.cmake
+++ b/pico_keys_sdk_import.cmake
@@ -15,7 +15,7 @@
# along with this program. If not, see .
#
-include(pico-keys-sdk/cmake/version.cmake)
+include(pico-keys-sdk/cmake/version.cmake OPTIONAL)
option(VIDPID "Set specific VID/PID from a known platform {NitroHSM, NitroFIDO2, NitroStart, NitroPro, Nitro3, Yubikey5, YubikeyNeo, YubiHSM, Gnuk, GnuPG}" "None")
diff --git a/src/fs/files.c b/src/fs/files.c
new file mode 100644
index 0000000..7608e02
--- /dev/null
+++ b/src/fs/files.c
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
+ * Copyright (c) 2022 Pol Henarejos.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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
+ * Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "file.h"
+
+file_t file_entries[] = {
+ /* 0 */ { .fid = 0x3f00, .parent = 0xff, .name = NULL, .type = FILE_TYPE_DF, .data = NULL,
+ .ef_structure = 0, .acl = { 0 } }, // MF
+ /* 1 */ { .fid = 0x0000, .parent = 0xff, .name = NULL, .type = FILE_TYPE_NOT_KNOWN, .data = NULL,
+ .ef_structure = 0, .acl = { 0 } } //end
+};
+
+const file_t *MF = &file_entries[0];
+const file_t *file_last = &file_entries[sizeof(file_entries) / sizeof(file_t) - 1];
diff --git a/src/rescue.c b/src/rescue.c
index 48f9b2e..acba24c 100644
--- a/src/rescue.c
+++ b/src/rescue.c
@@ -23,6 +23,9 @@
#include "pico/bootrom.h"
#include "hardware/watchdog.h"
#endif
+#include "mbedtls/ecdsa.h"
+#include "mbedtls/sha256.h"
+#include "random.h"
int rescue_process_apdu();
int rescue_unload();
@@ -54,6 +57,8 @@ int rescue_select(app_t *a, uint8_t force) {
res_APDU[res_APDU_size++] = PICO_PRODUCT;
res_APDU[res_APDU_size++] = PICO_VERSION_MAJOR;
res_APDU[res_APDU_size++] = PICO_VERSION_MINOR;
+ memcpy(res_APDU + res_APDU_size, pico_serial.id, sizeof(pico_serial.id));
+ res_APDU_size += sizeof(pico_serial.id);
apdu.ne = res_APDU_size;
if (force) {
scan_flash();
@@ -69,6 +74,89 @@ int rescue_unload() {
return PICOKEY_OK;
}
+int cmd_keydev_sign() {
+ uint8_t p1 = P1(apdu);
+ if (p1 == 0x01) {
+ if (apdu.nc != 32) {
+ return SW_WRONG_LENGTH();
+ }
+ if (!otp_key_2) {
+ return SW_INS_NOT_SUPPORTED();
+ }
+ mbedtls_ecdsa_context ecdsa;
+ mbedtls_ecdsa_init(&ecdsa);
+ int ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256K1, &ecdsa, otp_key_2, 32);
+ if (ret != 0) {
+ mbedtls_ecdsa_free(&ecdsa);
+ return SW_EXEC_ERROR();
+ }
+ uint16_t key_size = 2 * (int)((mbedtls_ecp_curve_info_from_grp_id(MBEDTLS_ECP_DP_SECP256K1)->bit_size + 7) / 8);
+ mbedtls_mpi r, s;
+ mbedtls_mpi_init(&r);
+ mbedtls_mpi_init(&s);
+
+ ret = mbedtls_ecdsa_sign(&ecdsa.MBEDTLS_PRIVATE(grp), &r, &s, &ecdsa.MBEDTLS_PRIVATE(d), apdu.data, apdu.nc, random_gen, NULL);
+ if (ret != 0) {
+ mbedtls_ecdsa_free(&ecdsa);
+ mbedtls_mpi_free(&r);
+ mbedtls_mpi_free(&s);
+ return SW_EXEC_ERROR();
+ }
+
+ mbedtls_mpi_write_binary(&r, res_APDU, key_size / 2); res_APDU_size = key_size / 2;
+ mbedtls_mpi_write_binary(&s, res_APDU + res_APDU_size, key_size / 2); res_APDU_size += key_size / 2;
+ mbedtls_ecdsa_free(&ecdsa);
+ mbedtls_mpi_free(&r);
+ mbedtls_mpi_free(&s);
+ }
+ else if (p1 == 0x02) {
+ // Return public key
+ if (!otp_key_2) {
+ return SW_INS_NOT_SUPPORTED();
+ }
+ if (apdu.nc != 0) {
+ return SW_WRONG_LENGTH();
+ }
+ mbedtls_ecp_keypair ecp;
+ mbedtls_ecp_keypair_init(&ecp);
+ int ret = mbedtls_ecp_read_key(MBEDTLS_ECP_DP_SECP256K1, &ecp, otp_key_2, 32);
+ if (ret != 0) {
+ mbedtls_ecp_keypair_free(&ecp);
+ return SW_EXEC_ERROR();
+ }
+ ret = mbedtls_ecp_mul(&ecp.MBEDTLS_PRIVATE(grp), &ecp.MBEDTLS_PRIVATE(Q), &ecp.MBEDTLS_PRIVATE(d), &ecp.MBEDTLS_PRIVATE(grp).G, random_gen, NULL);
+ if (ret != 0) {
+ mbedtls_ecp_keypair_free(&ecp);
+ return SW_EXEC_ERROR();
+ }
+ size_t olen = 0;
+ ret = mbedtls_ecp_point_write_binary(&ecp.MBEDTLS_PRIVATE(grp), &ecp.MBEDTLS_PRIVATE(Q), MBEDTLS_ECP_PF_UNCOMPRESSED, &olen, res_APDU, 4096);
+ if (ret != 0) {
+ mbedtls_ecp_keypair_free(&ecp);
+ return SW_EXEC_ERROR();
+ }
+ res_APDU_size = (uint16_t)olen;
+ mbedtls_ecp_keypair_free(&ecp);
+ }
+ else if (p1 == 0x03) {
+ // Upload device attestation certificate
+ if (apdu.nc == 0) {
+ return SW_WRONG_LENGTH();
+ }
+ file_t *ef_devcert = file_new(0x2F02); // EF_DEVCERT
+ if (!ef_devcert) {
+ return SW_FILE_NOT_FOUND();
+ }
+ file_put_data(ef_devcert, apdu.data, (uint16_t)apdu.nc);
+ res_APDU_size = 0;
+ low_flash_available();
+ }
+ else {
+ return SW_INCORRECT_P1P2();
+ }
+ return SW_OK();
+}
+
int cmd_write() {
if (apdu.nc < 2) {
return SW_WRONG_LENGTH();
@@ -163,12 +251,14 @@ int cmd_reboot_bootsel() {
}
#endif
+#define INS_KEYDEV_SIGN 0x10
#define INS_WRITE 0x1C
#define INS_SECURE 0x1D
#define INS_READ 0x1E
#define INS_REBOOT_BOOTSEL 0x1F
static const cmd_t cmds[] = {
+ { INS_KEYDEV_SIGN, cmd_keydev_sign },
{ INS_WRITE, cmd_write },
#if defined(PICO_RP2350) || defined(ESP_PLATFORM)
{ INS_SECURE, cmd_secure },
diff --git a/src/version.c b/src/version.c
new file mode 100644
index 0000000..369ddb2
--- /dev/null
+++ b/src/version.c
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the Pico Keys SDK distribution (https://github.com/polhenarejos/pico-keys-sdk).
+ * Copyright (c) 2022 Pol Henarejos.
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero 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
+ * Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see .
+ */
+
+#include "pico_keys.h"
+#include "pico_keys_version.h"
+
+const uint8_t PICO_PRODUCT = 0;
+const uint8_t PICO_VERSION_MAJOR = PICO_KEYS_SDK_VERSION_MAJOR;
+const uint8_t PICO_VERSION_MINOR = PICO_KEYS_SDK_VERSION_MINOR;