From e9f0b1b58c9adf5775762902af33c44f74a074d1 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 1 Oct 2024 09:33:22 +0200 Subject: [PATCH 01/10] Update autobuild for local and esp32. Signed-off-by: Pol Henarejos --- .github/workflows/codeql.yml | 3 ++- workflows/autobuild.sh | 26 ++++++++++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index ff6288b..5558edc 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -35,6 +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' ] steps: - name: Checkout repository @@ -66,7 +67,7 @@ jobs: - run: | echo "Run, Build Application using script" - ./workflows/autobuild.sh + ./workflows/autobuild.sh ${{ matrix.mode }} - name: Perform CodeQL Analysis uses: github/codeql-action/analyze@v2 diff --git a/workflows/autobuild.sh b/workflows/autobuild.sh index 09ef1c7..8f830c3 100755 --- a/workflows/autobuild.sh +++ b/workflows/autobuild.sh @@ -2,12 +2,38 @@ git submodule update --init --recursive sudo apt update + +if [[ $1 == "pico" ]]; then sudo apt install -y cmake gcc-arm-none-eabi libnewlib-arm-none-eabi libstdc++-arm-none-eabi-newlib git clone https://github.com/raspberrypi/pico-sdk cd pico-sdk git submodule update --init cd .. +git clone https://github.com/raspberrypi/picotool +cd picotool +git submodule update --init mkdir build cd build +cmake -DPICO_SDK_PATH=../../pico-sdk .. +make -j`nproc` +sudo make install +cd ../.. +mkdir build_pico +cd build_pico cmake -DPICO_SDK_PATH=../pico-sdk .. make +elif [[ $1 == "esp32" ]]; then +sudo apt install -y git wget flex bison gperf python3 python3-pip python3-venv cmake ninja-build ccache libffi-dev libssl-dev dfu-util libusb-1.0-0 +git clone --recursive https://github.com/espressif/esp-idf.git +cd esp-idf +./install.sh esp32s3 +. ./export.sh +cd .. +idf.py set-target esp32s3 +idf.py all +else +mkdir build +cd build +cmake -DENABLE_EMULATION=1 .. +make +fi \ No newline at end of file From 442caa271628fdd56b905d3e1222d40ba09a6fef Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Tue, 1 Oct 2024 13:29:25 +0200 Subject: [PATCH 02/10] Fix macos alignment. Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index e2b3eac..84c3efd 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit e2b3eacd89a0e857ef5c6b56ff4661fa0fba7242 +Subproject commit 84c3efd78292ebbb8473df667ab80310488d30a7 From 27470836725d8597c349016461e2f8755cc49aa3 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sat, 9 Nov 2024 00:36:21 +0100 Subject: [PATCH 03/10] Upgrade pico keys sdk. Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- src/openpgp/management.c | 4 +- src/openpgp/openpgp.c | 144 +++++++++++++++++++-------------------- src/openpgp/piv.c | 20 +++--- 4 files changed, 85 insertions(+), 85 deletions(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 84c3efd..5bce3e4 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 84c3efd78292ebbb8473df667ab80310488d30a7 +Subproject commit 5bce3e4c838f424c8d17728814284352f1b53bff diff --git a/src/openpgp/management.c b/src/openpgp/management.c index c6568b9..1c1d1ba 100644 --- a/src/openpgp/management.c +++ b/src/openpgp/management.c @@ -39,7 +39,7 @@ int man_select(app_t *a, uint8_t force) { res_APDU_size = strlen((char *) res_APDU); apdu.ne = res_APDU_size; init_piv(); - return CCID_OK; + return PICOKEY_OK; } INITIALIZER( man_ctor ) { @@ -47,7 +47,7 @@ INITIALIZER( man_ctor ) { } int man_unload() { - return CCID_OK; + return PICOKEY_OK; } bool cap_supported(uint16_t cap) { diff --git a/src/openpgp/openpgp.c b/src/openpgp/openpgp.c index 01efe4d..d21645d 100644 --- a/src/openpgp/openpgp.c +++ b/src/openpgp/openpgp.c @@ -291,13 +291,13 @@ extern bool has_pwpiv; extern uint8_t session_pwpiv[32]; int load_dek() { if (!has_pw1 && !has_pw2 && !has_pw3 && !has_pwpiv) { - return CCID_NO_LOGIN; + return PICOKEY_NO_LOGIN; } file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF); if (!tf) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } - int r = CCID_OK; + int r = PICOKEY_OK; if (has_pw1 || has_pw2) { memcpy(dek, file_get_data(tf), IV_SIZE + 32); r = aes_decrypt_cfb_256(session_pw1, dek, dek + IV_SIZE, 32); @@ -313,9 +313,9 @@ int load_dek() { r = aes_decrypt_cfb_256(session_pwpiv, dek, dek + IV_SIZE, 32); } if (r != 0) { - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } - return CCID_OK; + return PICOKEY_OK; } void release_dek() { @@ -324,7 +324,7 @@ void release_dek() { int dek_encrypt(uint8_t *data, size_t len) { int r; - if ((r = load_dek()) != CCID_OK) { + if ((r = load_dek()) != PICOKEY_OK) { return r; } r = aes_encrypt_cfb_256(dek + IV_SIZE, dek, data, len); @@ -334,7 +334,7 @@ int dek_encrypt(uint8_t *data, size_t len) { int dek_decrypt(uint8_t *data, size_t len) { int r; - if ((r = load_dek()) != CCID_OK) { + if ((r = load_dek()) != PICOKEY_OK) { return r; } r = aes_decrypt_cfb_256(dek + IV_SIZE, dek, data, len); @@ -360,7 +360,7 @@ int openpgp_unload() { algo_aut = EF_ALGO_PRIV3; pk_dec = EF_PK_DEC; pk_aut = EF_PK_AUT; - return CCID_OK; + return PICOKEY_OK; } extern char __StackLimit; @@ -390,7 +390,7 @@ int openpgp_select_aid(app_t *a, uint8_t force) { res_APDU[res_APDU_size++] = ((heap_left >> 0) & 0xff); res_APDU[1] += 8; apdu.ne = res_APDU_size; - return CCID_OK; + return PICOKEY_OK; } INITIALIZER( openpgp_ctor ) { @@ -479,32 +479,32 @@ int inc_sig_count() { } file_t *ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY); if (!ef || !ef->data) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } uint8_t *p = file_get_data(ef); uint32_t counter = (p[0] << 16) | (p[1] << 8) | p[2]; counter++; uint8_t q[3] = { (counter >> 16) & 0xff, (counter >> 8) & 0xff, counter & 0xff }; int r = file_put_data(ef, q, sizeof(q)); - if (r != CCID_OK) { - return CCID_EXEC_ERROR; + if (r != PICOKEY_OK) { + return PICOKEY_EXEC_ERROR; } low_flash_available(); - return CCID_OK; + return PICOKEY_OK; } int reset_sig_count() { file_t *ef = search_by_fid(EF_SIG_COUNT, NULL, SPECIFY_ANY); if (!ef || !ef->data) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } uint8_t q[3] = { 0 }; int r = file_put_data(ef, q, sizeof(q)); - if (r != CCID_OK) { - return CCID_EXEC_ERROR; + if (r != PICOKEY_OK) { + return PICOKEY_EXEC_ERROR; } low_flash_available(); - return CCID_OK; + return PICOKEY_OK; } int parse_sec_tpl(const file_t *f, int mode) { @@ -851,21 +851,21 @@ static int cmd_get_data() { int pin_reset_retries(const file_t *pin, bool force) { if (!pin) { - return CCID_ERR_NULL_PARAM; + return PICOKEY_ERR_NULL_PARAM; } file_t *pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF); file_t *pw_retries = search_by_fid(EF_PW_RETRIES, NULL, SPECIFY_EF); if (!pw_status || !pw_retries) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } if (3 + (pin->fid & 0xf) >= file_get_size(pw_status) || (pin->fid & 0xf) >= file_get_size(pw_retries)) { - return CCID_ERR_MEMORY_FATAL; + return PICOKEY_ERR_MEMORY_FATAL; } uint8_t p[64]; memcpy(p, file_get_data(pw_status), file_get_size(pw_status)); uint8_t retries = p[3 + (pin->fid & 0xf)]; if (retries == 0 && force == false) { //blocked - return CCID_ERR_BLOCKED; + return PICOKEY_ERR_BLOCKED; } uint8_t max_retries = file_get_data(pw_retries)[(pin->fid & 0xf)]; p[3 + (pin->fid & 0xf)] = max_retries; @@ -876,27 +876,27 @@ int pin_reset_retries(const file_t *pin, bool force) { int pin_wrong_retry(const file_t *pin) { if (!pin) { - return CCID_ERR_NULL_PARAM; + return PICOKEY_ERR_NULL_PARAM; } file_t *pw_status = search_by_fid(EF_PW_PRIV, NULL, SPECIFY_EF); if (!pw_status) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } uint8_t p[64]; memcpy(p, file_get_data(pw_status), file_get_size(pw_status)); if (p[3 + (pin->fid & 0xf)] > 0) { p[3 + (pin->fid & 0xf)] -= 1; int r = file_put_data(pw_status, p, file_get_size(pw_status)); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } low_flash_available(); if (p[3 + (pin->fid & 0xf)] == 0) { - return CCID_ERR_BLOCKED; + return PICOKEY_ERR_BLOCKED; } return p[3 + (pin->fid & 0xf)]; } - return CCID_ERR_BLOCKED; + return PICOKEY_ERR_BLOCKED; } int check_pin(const file_t *pin, const uint8_t *data, size_t len) { @@ -916,17 +916,17 @@ int check_pin(const file_t *pin, const uint8_t *data, size_t len) { } if (memcmp(file_get_data(pin) + 1, dhash, sizeof(dhash)) != 0) { int retries; - if ((retries = pin_wrong_retry(pin)) < CCID_OK) { + if ((retries = pin_wrong_retry(pin)) < PICOKEY_OK) { return SW_PIN_BLOCKED(); } return set_res_sw(0x63, 0xc0 | retries); } int r = pin_reset_retries(pin, false); - if (r == CCID_ERR_BLOCKED) { + if (r == PICOKEY_ERR_BLOCKED) { return SW_PIN_BLOCKED(); } - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_MEMORY_FAILURE(); } isUserAuthenticated = true; @@ -1021,7 +1021,7 @@ static int cmd_put_data() { int r = 0; if (fid == EF_RC) { has_rc = false; - if ((r = load_dek()) != CCID_OK) { + if ((r = load_dek()) != PICOKEY_OK) { return SW_EXEC_ERROR(); } uint8_t dhash[33]; @@ -1043,7 +1043,7 @@ static int cmd_put_data() { else { r = file_put_data(ef, apdu.data, apdu.nc); } - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_MEMORY_FAILURE(); } low_flash_available(); @@ -1062,7 +1062,7 @@ static int cmd_change_pin() { } uint8_t pin_len = file_get_data(pw)[0]; uint16_t r = 0; - if ((r = load_dek()) != CCID_OK) { + if ((r = load_dek()) != PICOKEY_OK) { return SW_EXEC_ERROR(); } r = check_pin(pw, apdu.data, pin_len); @@ -1130,7 +1130,7 @@ static int cmd_reset_retry() { newpin_len = apdu.nc; } int r = 0; - if ((r = load_dek()) != CCID_OK) { + if ((r = load_dek()) != PICOKEY_OK) { return SW_EXEC_ERROR(); } file_t *tf = search_by_fid(EF_DEK, NULL, SPECIFY_EF); @@ -1148,7 +1148,7 @@ static int cmd_reset_retry() { dhash[0] = newpin_len; double_hash_pin(apdu.data + (apdu.nc - newpin_len), newpin_len, dhash + 1); file_put_data(pw, dhash, sizeof(dhash)); - if (pin_reset_retries(pw, true) != CCID_OK) { + if (pin_reset_retries(pw, true) != PICOKEY_OK) { return SW_MEMORY_FAILURE(); } low_flash_available(); @@ -1162,13 +1162,13 @@ int store_keys(void *key_ctx, int type, uint16_t key_id, bool use_kek) { uint8_t kdata[4096 / 8]; //worst //if (!has_pw3) - // return CCID_NO_LOGIN; + // return PICOKEY_NO_LOGIN; //file_t *pw3 = search_by_fid(EF_PW3, NULL, SPECIFY_EF); //if (!pw3) - // return CCID_ERR_FILE_NOT_FOUND; + // return PICOKEY_ERR_FILE_NOT_FOUND; file_t *ef = search_by_fid(key_id, NULL, SPECIFY_EF); if (!ef) { - return CCID_ERR_FILE_NOT_FOUND; + return PICOKEY_ERR_FILE_NOT_FOUND; } if (type == ALGO_RSA) { mbedtls_rsa_context *rsa = (mbedtls_rsa_context *) key_ctx; @@ -1197,19 +1197,19 @@ int store_keys(void *key_ctx, int type, uint16_t key_id, bool use_kek) { } if (use_kek) { r = dek_encrypt(kdata, key_size); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } } //r = aes_encrypt_cfb_256(file_read(pw3->data+2), session_pw3, kdata, key_size); - //if (r != CCID_OK) + //if (r != PICOKEY_OK) // return r; r = file_put_data(ef, kdata, key_size); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return r; } low_flash_available(); - return CCID_OK; + return PICOKEY_OK; } int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey, bool use_dek) { @@ -1217,33 +1217,33 @@ int load_private_key_rsa(mbedtls_rsa_context *ctx, file_t *fkey, bool use_dek) { uint8_t kdata[4096 / 8]; memcpy(kdata, file_get_data(fkey), key_size); if (use_dek && dek_decrypt(kdata, key_size) != 0) { - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } if (mbedtls_mpi_read_binary(&ctx->P, kdata, key_size / 2) != 0) { mbedtls_rsa_free(ctx); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (mbedtls_mpi_read_binary(&ctx->Q, kdata + key_size / 2, key_size / 2) != 0) { mbedtls_rsa_free(ctx); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (mbedtls_mpi_lset(&ctx->E, 0x10001) != 0) { mbedtls_rsa_free(ctx); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } if (mbedtls_rsa_import(ctx, NULL, &ctx->P, &ctx->Q, NULL, &ctx->E) != 0) { mbedtls_rsa_free(ctx); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (mbedtls_rsa_complete(ctx) != 0) { mbedtls_rsa_free(ctx); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } if (mbedtls_rsa_check_privkey(ctx) != 0) { mbedtls_rsa_free(ctx); - return CCID_WRONG_DATA; + return PICOKEY_WRONG_DATA; } - return CCID_OK; + return PICOKEY_OK; } int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey, bool use_dek) { @@ -1251,30 +1251,30 @@ int load_private_key_ecdsa(mbedtls_ecdsa_context *ctx, file_t *fkey, bool use_de uint8_t kdata[67]; //Worst case, 521 bit + 1byte memcpy(kdata, file_get_data(fkey), key_size); if (use_dek && dek_decrypt(kdata, key_size) != 0) { - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } 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); - return CCID_EXEC_ERROR; + 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 (r != 0) { mbedtls_ecdsa_free(ctx); - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } - return CCID_OK; + return PICOKEY_OK; } int load_aes_key(uint8_t *aes_key, file_t *fkey) { int key_size = file_get_size(fkey); memcpy(aes_key, file_get_data(fkey), key_size); if (dek_decrypt(aes_key, key_size) != 0) { - return CCID_EXEC_ERROR; + return PICOKEY_EXEC_ERROR; } - return CCID_OK; + return PICOKEY_OK; } mbedtls_ecp_group_id get_ec_group_id_from_attr(const uint8_t *algo, size_t algo_len) { @@ -1359,7 +1359,7 @@ static int cmd_keypair_gen() { } uint16_t fid = 0x0; - int r = CCID_OK; + int r = PICOKEY_OK; if (apdu.data[0] == 0xB6) { fid = EF_PK_SIG; } @@ -1400,7 +1400,7 @@ static int cmd_keypair_gen() { r = store_keys(&rsa, ALGO_RSA, fid, true); make_rsa_response(&rsa); mbedtls_rsa_free(&rsa); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } } @@ -1421,7 +1421,7 @@ static int cmd_keypair_gen() { r = store_keys(&ecdsa, algo[0], fid, true); make_ecdsa_response(&ecdsa); mbedtls_ecdsa_free(&ecdsa); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } } @@ -1433,7 +1433,7 @@ static int cmd_keypair_gen() { return SW_REFERENCE_NOT_FOUND(); } r = file_put_data(pbef, res_APDU, res_APDU_size); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } if (fid == EF_PK_SIG) { @@ -1447,7 +1447,7 @@ static int cmd_keypair_gen() { memcpy(aes_key, random_bytes_get(key_size), key_size); r = store_keys(aes_key, ALGO_AES_256, EF_AES_KEY, true); /* if storing the key fails, we silently continue */ - //if (r != CCID_OK) + //if (r != PICOKEY_OK) // return SW_EXEC_ERROR(); } low_flash_available(); @@ -1596,19 +1596,19 @@ static int cmd_pso() { if (wait_button_pressed(pk_fid == EF_PK_SIG ? EF_UIF_SIG : EF_UIF_DEC) == true) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } - int r = CCID_OK; + int r = PICOKEY_OK; int key_size = file_get_size(ef); if (is_aes) { uint8_t aes_key[32]; r = load_aes_key(aes_key, ef); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { memset(aes_key, 0, sizeof(aes_key)); return SW_EXEC_ERROR(); } if (P1(apdu) == 0x80 && P2(apdu) == 0x86) { //decipher r = aes_decrypt(aes_key, NULL, key_size, PICO_KEYS_AES_MODE_CBC, apdu.data + 1, apdu.nc - 1); memset(aes_key, 0, sizeof(aes_key)); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } memcpy(res_APDU, apdu.data + 1, apdu.nc - 1); @@ -1617,7 +1617,7 @@ static int cmd_pso() { else if (P1(apdu) == 0x86 && P2(apdu) == 0x80) { //encipher r = aes_encrypt(aes_key, NULL, key_size, PICO_KEYS_AES_MODE_CBC, apdu.data, apdu.nc); memset(aes_key, 0, sizeof(aes_key)); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } res_APDU[0] = 0x2; @@ -1630,7 +1630,7 @@ static int cmd_pso() { mbedtls_rsa_context ctx; mbedtls_rsa_init(&ctx); r = load_private_key_rsa(&ctx, ef, true); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_rsa_free(&ctx); return SW_EXEC_ERROR(); } @@ -1669,7 +1669,7 @@ static int cmd_pso() { mbedtls_ecdsa_context ctx; mbedtls_ecdsa_init(&ctx); r = load_private_key_ecdsa(&ctx, ef, true); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecdsa_free(&ctx); return SW_EXEC_ERROR(); } @@ -1794,12 +1794,12 @@ static int cmd_internal_aut() { if (wait_button_pressed(EF_UIF_AUT) == true) { return SW_SECURE_MESSAGE_EXEC_ERROR(); } - int r = CCID_OK; + int r = PICOKEY_OK; if (algo[0] == ALGO_RSA) { mbedtls_rsa_context ctx; mbedtls_rsa_init(&ctx); r = load_private_key_rsa(&ctx, ef, true); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_rsa_free(&ctx); return SW_EXEC_ERROR(); } @@ -1815,7 +1815,7 @@ static int cmd_internal_aut() { mbedtls_ecdsa_context ctx; mbedtls_ecdsa_init(&ctx); r = load_private_key_ecdsa(&ctx, ef, true); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecdsa_free(&ctx); return SW_EXEC_ERROR(); } @@ -1988,7 +1988,7 @@ static int cmd_import_data() { r = store_keys(&rsa, ALGO_RSA, fid, true); make_rsa_response(&rsa); mbedtls_rsa_free(&rsa); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } } @@ -2021,7 +2021,7 @@ static int cmd_import_data() { r = store_keys(&ecdsa, ALGO_ECDSA, fid, true); make_ecdsa_response(&ecdsa); mbedtls_ecdsa_free(&ecdsa); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } } @@ -2036,7 +2036,7 @@ static int cmd_import_data() { return SW_REFERENCE_NOT_FOUND(); } r = file_put_data(pbef, res_APDU, res_APDU_size); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } res_APDU_size = 0; //make_*_response sets a response. we need to overwrite diff --git a/src/openpgp/piv.c b/src/openpgp/piv.c index 6eae778..6b37772 100644 --- a/src/openpgp/piv.c +++ b/src/openpgp/piv.c @@ -270,7 +270,7 @@ void init_piv() { } int piv_unload() { - return CCID_OK; + return PICOKEY_OK; } void select_piv_aid() { @@ -306,7 +306,7 @@ int piv_select_aid(app_t *a, uint8_t force) { a->unload = piv_unload; init_piv(); select_piv_aid(); - return CCID_OK; + return PICOKEY_OK; } INITIALIZER( piv_ctor ) { @@ -469,7 +469,7 @@ static int cmd_get_metadata() { mbedtls_rsa_context ctx; mbedtls_rsa_init(&ctx); int r = load_private_key_rsa(&ctx, ef_key, false); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_rsa_free(&ctx); return SW_EXEC_ERROR(); } @@ -488,7 +488,7 @@ static int cmd_get_metadata() { mbedtls_ecdsa_context ctx; mbedtls_ecdsa_init(&ctx); int r = load_private_key_ecdsa(&ctx, ef_key, false); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecdsa_free(&ctx); return SW_EXEC_ERROR(); } @@ -690,7 +690,7 @@ static int cmd_authenticate() { mbedtls_rsa_context ctx; mbedtls_rsa_init(&ctx); int r = load_private_key_rsa(&ctx, ef_key, false); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_rsa_free(&ctx); return SW_EXEC_ERROR(); } @@ -724,7 +724,7 @@ static int cmd_authenticate() { mbedtls_ecdsa_context ctx; mbedtls_ecdsa_init(&ctx); int r = load_private_key_ecdsa(&ctx, ef_key, false); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecdsa_free(&ctx); return SW_EXEC_ERROR(); } @@ -905,7 +905,7 @@ static int cmd_asym_keygen() { file_put_data(ef, cert + sizeof(cert) - r, r); r = store_keys(&rsa, ALGO_RSA, key_ref == 0x93 ? EF_PIV_KEY_RETIRED18 : key_ref, false); mbedtls_rsa_free(&rsa); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } } @@ -926,7 +926,7 @@ static int cmd_asym_keygen() { file_put_data(ef, cert + sizeof(cert) - r, r); r = store_keys(&ecdsa, ALGO_ECDSA, key_ref == 0x93 ? EF_PIV_KEY_RETIRED18 : key_ref, false); mbedtls_ecdsa_free(&ecdsa); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { return SW_EXEC_ERROR(); } } @@ -1155,7 +1155,7 @@ static int cmd_attestation() { mbedtls_rsa_context ctx; mbedtls_rsa_init(&ctx); r = load_private_key_rsa(&ctx, ef_key, false); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_rsa_free(&ctx); return SW_EXEC_ERROR(); } @@ -1166,7 +1166,7 @@ static int cmd_attestation() { mbedtls_ecdsa_context ctx; mbedtls_ecdsa_init(&ctx); r = load_private_key_ecdsa(&ctx, ef_key, false); - if (r != CCID_OK) { + if (r != PICOKEY_OK) { mbedtls_ecdsa_free(&ctx); return SW_EXEC_ERROR(); } From 4ba5e04080618f62fab15377ab6b2a1f1e97179f Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sat, 9 Nov 2024 00:37:19 +0100 Subject: [PATCH 04/10] Add PICO_PRODUCT. Signed-off-by: Pol Henarejos --- src/openpgp/openpgp.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/openpgp/openpgp.c b/src/openpgp/openpgp.c index d21645d..2b1c03e 100644 --- a/src/openpgp/openpgp.c +++ b/src/openpgp/openpgp.c @@ -33,6 +33,8 @@ #include "usb.h" #include "ccid/ccid.h" +uint8_t PICO_PRODUCT = 3; + bool has_pw1 = false; bool has_pw2 = false; bool has_pw3 = false; From 9b2b2e822abb17e007b28ceb315f366e733558d0 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sat, 9 Nov 2024 00:38:39 +0100 Subject: [PATCH 05/10] Add compiler options for optimized build.s Signed-off-by: Pol Henarejos --- sdkconfig.defaults | 1 + 1 file changed, 1 insertion(+) diff --git a/sdkconfig.defaults b/sdkconfig.defaults index a7833a5..d917312 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -11,6 +11,7 @@ CONFIG_PARTITION_TABLE_FILENAME="pico-keys-sdk/config/esp32/partitions.csv" CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y CONFIG_WL_SECTOR_SIZE_512=y CONFIG_WL_SECTOR_MODE_PERF=y +COMPILER_OPTIMIZATION="Performance" CONFIG_MBEDTLS_CMAC_C=y CONFIG_MBEDTLS_CHACHA20_C=y From 21a9a731aaf5b8217c9ce1c834e49bc59bbc8ef9 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 10 Nov 2024 18:14:24 +0100 Subject: [PATCH 06/10] Upgrade Pico Keys SDK Signed-off-by: Pol Henarejos --- pico-keys-sdk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pico-keys-sdk b/pico-keys-sdk index 5bce3e4..8c25e9b 160000 --- a/pico-keys-sdk +++ b/pico-keys-sdk @@ -1 +1 @@ -Subproject commit 5bce3e4c838f424c8d17728814284352f1b53bff +Subproject commit 8c25e9be87f5556738550d309358198163111420 From 79c69a66170128a4c98750cd0bdd8e2ef9d1ae0d Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 10 Nov 2024 18:56:46 +0100 Subject: [PATCH 07/10] OTP key is used to mask the DEK. Signed-off-by: Pol Henarejos --- src/openpgp/openpgp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/openpgp/openpgp.c b/src/openpgp/openpgp.c index 2b1c03e..926fbb1 100644 --- a/src/openpgp/openpgp.c +++ b/src/openpgp/openpgp.c @@ -32,6 +32,7 @@ #include "asn1.h" #include "usb.h" #include "ccid/ccid.h" +#include "otp.h" uint8_t PICO_PRODUCT = 3; @@ -317,6 +318,11 @@ int load_dek() { if (r != 0) { return PICOKEY_EXEC_ERROR; } + if (otp_key_1) { + for (int i = 0; i < 32; i++) { + dek[IV_SIZE + i] ^= otp_key_1[i]; + } + } return PICOKEY_OK; } From 4e6a9eaa4c732da9f6945b6d9796115c4075bd51 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 10 Nov 2024 18:56:55 +0100 Subject: [PATCH 08/10] Update README Signed-off-by: Pol Henarejos --- README.md | 77 +++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 2423218..652d7e9 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Pico OpenPGP -This project aims at transforming your Raspberry Pico into a Smart Card with an OpenPGP applet integrated. The Pico works as a reader with an embedded OpenPGP card, like a USB card. +This project aims at transforming your Raspberry Pico or ESP32 microcontroller into a Smart Card with an OpenPGP applet integrated. The Pico works as a reader with an embedded OpenPGP card, like a USB card. OpenPGP cards are used to manage PGP keys and do cryptographic operations, such as keypair generation, signing and asymmetric deciphering. Pico OpenPGP follows the [**OpenPGP 3.4.1** specifications](https://gnupg.org/ftp/specs/OpenPGP-smart-card-application-3.4.pdf "**OpenPGP 3.4.1** specifications"), available at [GnuPG](http://gnupg.org "GnuPG"). @@ -29,6 +29,10 @@ Pico OpenPGP has implemented the following features: - AES key generation. - AES ciphering and deciphering. - Cardholder certificates support. +- Secure Boot and Secure Lock in RP2350 and ESP32-S3 MCUs. +- One Time Programming to store the master key that encrypts all resident keys and seeds. +- Rescue interface to allow recovery of the device if it becomes unresponsive or undetectable. +- LED customization with Pico Commissioner. All these features are compliant with the specification. Therefore, if you detect some behaviour that is not expected or it does not follow the rules of specs, please open an issue. @@ -47,44 +51,71 @@ As a consequence, Pico OpenPGP is designed from zero. Well, not strictly from ze Whilst Gnuk is OpenPGP 2.0 with small set of enhancements, Pico OpenPGP aims at being OpenPGP 3.4 compliant, with new features (not present in Gnuk), such as Manage Security Environment (MSE) or UIF. ## Security considerations -All secret keys (asymmetric and symmetric) are stored encrypted in the flash memory of the Raspberry Pico. DEK is used as a 256 bit AES key to protect private and secret keys. Keys are never stored in RAM except for signature and decryption operations and only during the process. All keys (including DEK) are loaded and cleared every time to avoid potential security flaws. +All secret keys (asymmetric and symmetric) are stored encrypted in the flash memory of the Raspberry Pico using a Device Encyrption Key (DEK). DEK is a 256 bit AES key used to protect private and secret keys. Keys are never stored in RAM except for signature and decryption operations and only during the process. All keys (including DEK) are loaded and cleared every time to avoid potential security flaws. -At the same time, DEK is encrypted with doubled salted and hashed PIN. Also, the PIN is hashed in memory during the session. Hence, PIN is never stored in plain text neither in flash nor in memory. Note that PIN is conveyed from the host to the Pico in plain text if no secure channel is provided. +At the same time, DEK is encrypted with doubled salted and hashed PIN. For RP2350 and ESP32-S3 microcontrollers it is masked by a secure device 32 bytes key. Also, the PIN is hashed in memory during the session. Hence, PIN is never stored in plain text neither in flash nor in memory. Note that PIN is conveyed from the host to the Pico in plain text if no secure channel is provided. If the Pico is stolen the contents of private and secret keys cannot be read without the PIN, even if the flash memory is dumped. +### RP2350 and ESP32-S3 +RP2350 and ESP32-S3 microcontrollers are equipped with advanced security features, including Secure Boot and Secure Lock, ensuring that firmware integrity and authenticity are tightly controlled. Both devices support the storage of the Device Encryption Key (DEK) in an OTP (One-Time Programmable) memory region, making it permanently inaccessible for external access or tampering. This secure, non-volatile region guarantees that critical security keys are embedded into the hardware, preventing unauthorized access and supporting robust defenses against code injection or firmware modification. Together, Secure Boot and Secure Lock enforce firmware authentication, while the DEK in OTP memory solidifies the foundation for secure operations. + +### Secure Boot +Secure Boot is a security feature that ensures that only trusted firmware, verified through digital signatures, can be loaded onto the device during the boot process. Once enabled, Secure Boot checks every piece of firmware against a cryptographic signature before execution, rejecting any unauthorized or modified code. This prevents malicious firmware from compromising the device’s operation and integrity. With Secure Boot activated, only firmware versions signed by a trusted authority, such as the device manufacturer, will be accepted, ensuring the device remains protected from unauthorized software modifications. **This is irreversible. Once enabled, it CANNOT be disabled.** + +**IMPORTANT:** For users wishing to develop and compile custom firmware, a private-public key pair is essential. Activating Secure Boot requires users to generate and manage their own unique private-public key pair. The public key from this pair must be embedded into the device to validate all firmware. Firmware will not boot without a proper digital signature from this key pair. This means that users must sign all future firmware versions with their private key and embed the public key in the device to ensure compatibility. + +### Secure Lock +Secure Lock builds on Secure Boot by imposing an even stricter security model. Once activated, Secure Lock prevents any further installation of new boot keys, effectively locking the device to only run firmware that is authorized by the device's primary vendor—in this case, Pico Keys. In addition to preventing additional keys, Secure Lock disables debugging interfaces and puts additional safeguards in place to resist tampering and intrusion attempts. This ensures that the device operates exclusively with the original vendor’s firmware and resists unauthorized access, making it highly secure against external threats. **This is irreversible. Once enabled, it CANNOT be disabled.** + +**IMPORTANT:** Activating Secure Lock not only enables Secure Boot but also invalidates all keys except the official Pico Key. This means that only firmware signed by Pico Key will be recognized, and custom code will no longer be allowed. Once enabled, the Pico Key device will run solely on the official firmware available on the website, with no option for generating or compiling new code for the device. + ## Download -Please, go to the [Release page](https://github.com/polhenarejos/pico-openpgp/releases "Release page")) and download the UF2 file for your board. +**If you own an ESP32-S3 board, go to [ESP32 Flasher](https://www.picokeys.com/esp32-flasher/) for flashing your Pico OpenPGP.** -Please, go to the Release page and download the UF2 file for your board. +If you own a Raspberry Pico (RP2040 or RP2350), go to [Download page](https://www.picokeys.com/getting-started/), select your vendor and model and download the proper firmware; or go to [Release page](https://www.github.com/polhenarejos/pico-openpgp/releases/) and download the UF2 file for your board. -Note that UF2 files are shiped with a dummy VID/PID to avoid license issues (FEFF:FCFD). If you are planning to use it with OpenSC or similar, you should modify Info.plist of CCID driver to add these VID/PID or use the [Pico Patcher tool](https://www.picokeys.com/pico-patcher/). - -Alternatively you can use the legacy VID/PID patcher as follows: -`./patch_vidpid.sh VID:PID input_hsm_file.uf2 output_hsm_file.uf2` +Note that UF2 files are shiped with a dummy VID/PID to avoid license issues (FEFF:FCFD). If you plan to use it with OpenSC or similar tools, you should modify Info.plist of CCID driver to add these VID/PID or use the [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner"). You can use whatever VID/PID (i.e., 234b:0000 from FISJ), but remember that you are not authorized to distribute the binary with a VID/PID that you do not own. -Note that the pure-browser option [Pico Patcher tool](https://www.picokeys.com/pico-patcher/) is the most recommended. +Note that the pure-browser option [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner") is the most recommended. -## Build +## Build for Raspberry Pico Before building, ensure you have installed the toolchain for the Pico and the Pico SDK is properly located in your drive. +``` +git clone https://github.com/polhenarejos/pico-openpgp +git submodule update --init --recursive +cd pico-openpgp +mkdir build +cd build +PICO_SDK_PATH=/path/to/pico-sdk cmake .. -DPICO_BOARD=board_type -DUSB_VID=0x1234 -DUSB_PID=0x5678 +make +``` +Note that `PICO_BOARD`, `USB_VID` and `USB_PID` are optional. If not provided, `pico` board and VID/PID `FEFF:FCFD` will be used. - git clone https://github.com/polhenarejos/pico-openpgp - cd pico-openpgp - mkdir build - cd build - PICO_SDK_PATH=/path/to/pico-sdk cmake .. -DPICO_BOARD=board_type -DUSB_VID=0x1234 -DUSB_PID=0x5678 - make +Additionally, you can pass the `VIDPID=value` parameter to build the firmware with a known VID/PID. The supported values are: -Note that PICO_BOARD, USB_VID and USB_PID are optional. If not provided, pico board and VID/PID FEFF:FCFD will be used. +- `NitroHSM` +- `NitroFIDO2` +- `NitroStart` +- `NitroPro` +- `Nitro3` +- `Yubikey5` +- `YubikeyNeo` +- `YubiHSM` +- `Gnuk` +- `GnuPG` -After make ends, the binary file pico_openpgp.uf2 will be generated. Put your pico board into loading mode, by pushing BOOTSEL button while pluging on, and copy the UF2 to the new fresh usb mass storage Pico device. Once copied, the pico mass storage will be disconnected automatically and the pico board will reset with the new firmware. A blinking led will indicate the device is ready to work. +After running `make`, the binary file `pico_openpgp.uf2` will be generated. To load this onto your Pico board: + +1. Put the Pico board into loading mode by holding the `BOOTSEL` button while plugging it in. +2. Copy the `pico_openpgp.uf2` file to the new USB mass storage device that appears. +3. Once the file is copied, the Pico mass storage device will automatically disconnect, and the Pico board will reset with the new firmware. +4. A blinking LED will indicate that the device is ready to work. ## Operation time ### Keypair generation -Generating EC keys is almost instant. RSA keypair generation takes some time, specially for 3072 and 4096 bits. -### Keypair generation Generating EC keys is almost instant. RSA keypair generation takes some time, specially for `3072` and `4096` bits. | RSA key length (bits) | Average time (seconds) | @@ -135,7 +166,9 @@ Pico OpenPGP relies on PKCS#15 structure to store and manipulate the internal fi The way to communicate is exactly the same as with other cards, such as OpenPGP or similar. ### Important -OpenSC relies on PCSC driver, which reads a list (`Info.plist`) that contains a pair of VID/PID of supported readers. In order to be detectable, you must patch the UF2 binary (if you just downloaded from the [Release section](https://github.com/polhenarejos/pico-openpgp/releases "Release section")) or configure the project with the proper VID/PID with `USB_VID` and `USB_PID` parameters in `CMake` (see [Build section](#build "Build section")). Note that you cannot distribute the patched/compiled binary if you do not own the VID/PID or have an explicit authorization. +OpenSC relies on PCSC driver, which reads a list (`Info.plist`) that contains a pair of VID/PID of supported readers. In order to be detectable, you have several options: +- Use the pure-browser online [Pico Commissioner](https://www.picokeys.com/pico-commissioner/ "Pico Commissioner") that commissions the Pico Key on-the-fly without external tools. +- Build and configure the project with the proper VID/PID with `USB_VID` and `USB_PID` parameters in `CMake` (see [Build section](#build "Build section")). Note that you cannot distribute the patched/compiled binary if you do not own the VID/PID or have an explicit authorization. ## Credits Pico OpenPGP uses the following libraries or portion of code: From 3ed463cc97192a2938e72bbe0e061522551d5b45 Mon Sep 17 00:00:00 2001 From: Pol Henarejos Date: Sun, 10 Nov 2024 18:57:19 +0100 Subject: [PATCH 09/10] Upgrade to version 3.0 Signed-off-by: Pol Henarejos --- build_pico_openpgp.sh | 65 ++++++++++++++++++++++++++++++++++++++----- src/openpgp/version.h | 2 +- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/build_pico_openpgp.sh b/build_pico_openpgp.sh index c6ea85f..5f4de6f 100755 --- a/build_pico_openpgp.sh +++ b/build_pico_openpgp.sh @@ -1,45 +1,93 @@ #!/bin/bash -VERSION_MAJOR="2" -VERSION_MINOR="2" +VERSION_MAJOR="3" +VERSION_MINOR="0" +SUFFIX="${VERSION_MAJOR}.${VERSION_MINOR}" +#if ! [[ -z "${GITHUB_SHA}" ]]; then +# SUFFIX="${SUFFIX}.${GITHUB_SHA}" +#fi rm -rf release/* +mkdir -p build_release +mkdir -p release cd build_release -for board in adafruit_feather_rp2040 \ +for board in 0xcb_helios \ + adafruit_feather_rp2040_usb_host \ + adafruit_feather_rp2040 \ adafruit_itsybitsy_rp2040 \ adafruit_kb2040 \ adafruit_macropad_rp2040 \ adafruit_qtpy_rp2040 \ adafruit_trinkey_qt2040 \ + amethyst_fpga \ + archi \ arduino_nano_rp2040_connect \ + cytron_maker_pi_rp2040 \ datanoisetv_rp2040_dsp \ eetree_gamekit_rp2040 \ garatronic_pybstick26_rp2040 \ + gen4_rp2350_24 \ + gen4_rp2350_24ct \ + gen4_rp2350_24t \ + gen4_rp2350_28 \ + gen4_rp2350_28ct \ + gen4_rp2350_28t \ + gen4_rp2350_32 \ + gen4_rp2350_32ct \ + gen4_rp2350_32t \ + gen4_rp2350_35 \ + gen4_rp2350_35ct \ + gen4_rp2350_35t \ + hellbender_2350A_devboard \ + ilabs_challenger_rp2350_bconnect \ + ilabs_challenger_rp2350_wifi_ble \ + ilabs_opendec02 \ + melopero_perpetuo_rp2350_lora \ melopero_shake_rp2040 \ + metrotech_xerxes_rp2040 \ + net8086_usb_interposer \ nullbits_bit_c_pro \ + phyx_rick_tny_rp2350 \ + pi-plates_micropi \ pico \ pico_w \ + pico2 \ pimoroni_badger2040 \ pimoroni_interstate75 \ pimoroni_keybow2040 \ pimoroni_motor2040 \ pimoroni_pga2040 \ + pimoroni_pga2350 \ + pimoroni_pico_plus2_rp2350 \ pimoroni_picolipo_4mb \ pimoroni_picolipo_16mb \ pimoroni_picosystem \ pimoroni_plasma2040 \ + pimoroni_plasma2350 \ pimoroni_servo2040 \ pimoroni_tiny2040 \ pimoroni_tiny2040_2mb \ + pimoroni_tiny2350 \ pololu_3pi_2040_robot \ + pololu_zumo_2040_robot \ seeed_xiao_rp2040 \ + seeed_xiao_rp2350 \ solderparty_rp2040_stamp \ solderparty_rp2040_stamp_carrier \ solderparty_rp2040_stamp_round_carrier \ + solderparty_rp2350_stamp_xl \ + solderparty_rp2350_stamp \ sparkfun_micromod \ sparkfun_promicro \ + sparkfun_promicro_rp2350 \ sparkfun_thingplus \ + switchscience_picossci2_conta_base \ + switchscience_picossci2_dev_board \ + switchscience_picossci2_micro \ + switchscience_picossci2_rp2350_breakout \ + switchscience_picossci2_tiny \ + tinycircuits_thumby_color_rp2350 \ vgaboard \ waveshare_rp2040_lcd_0.96 \ waveshare_rp2040_lcd_1.28 \ @@ -47,11 +95,14 @@ for board in adafruit_feather_rp2040 \ waveshare_rp2040_plus_4mb \ waveshare_rp2040_plus_16mb \ waveshare_rp2040_zero \ + weact_studio_rp2040_2mb \ + weact_studio_rp2040_4mb \ + weact_studio_rp2040_8mb \ + weact_studio_rp2040_16mb \ wiznet_w5100s_evb_pico do rm -rf * - PICO_SDK_PATH=../../pico-sdk cmake .. -DPICO_BOARD=$board - make -kj20 - mv pico_openpgp.uf2 ../release/pico_openpgp_$board-$VERSION_MAJOR.$VERSION_MINOR.uf2 - + PICO_SDK_PATH="${PICO_SDK_PATH:-../../pico-sdk}" cmake .. -DPICO_BOARD=$board + make -j`nproc` + mv pico_openpgp.uf2 ../release/pico_openpgp_$board-$SUFFIX.uf2 done diff --git a/src/openpgp/version.h b/src/openpgp/version.h index 818e948..2d4ae1b 100644 --- a/src/openpgp/version.h +++ b/src/openpgp/version.h @@ -24,7 +24,7 @@ #define OPGP_VERSION_MINOR (OPGP_VERSION & 0xff) -#define PIPGP_VERSION 0x0202 +#define PIPGP_VERSION 0x0300 #define PIPGP_VERSION_MAJOR ((PIPGP_VERSION >> 8) & 0xff) #define PIPGP_VERSION_MINOR (PIPGP_VERSION & 0xff) From 4971a22a32354a673a28016ef991f9f80aa19e46 Mon Sep 17 00:00:00 2001 From: Pol Henarejos <55573252+polhenarejos@users.noreply.github.com> Date: Sun, 10 Nov 2024 19:01:10 +0100 Subject: [PATCH 10/10] Update README.md Fix headings --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 652d7e9..92a82da 100644 --- a/README.md +++ b/README.md @@ -57,15 +57,15 @@ At the same time, DEK is encrypted with doubled salted and hashed PIN. For RP235 If the Pico is stolen the contents of private and secret keys cannot be read without the PIN, even if the flash memory is dumped. -### RP2350 and ESP32-S3 +### RP2350 and ESP32-S3 RP2350 and ESP32-S3 microcontrollers are equipped with advanced security features, including Secure Boot and Secure Lock, ensuring that firmware integrity and authenticity are tightly controlled. Both devices support the storage of the Device Encryption Key (DEK) in an OTP (One-Time Programmable) memory region, making it permanently inaccessible for external access or tampering. This secure, non-volatile region guarantees that critical security keys are embedded into the hardware, preventing unauthorized access and supporting robust defenses against code injection or firmware modification. Together, Secure Boot and Secure Lock enforce firmware authentication, while the DEK in OTP memory solidifies the foundation for secure operations. -### Secure Boot +### Secure Boot Secure Boot is a security feature that ensures that only trusted firmware, verified through digital signatures, can be loaded onto the device during the boot process. Once enabled, Secure Boot checks every piece of firmware against a cryptographic signature before execution, rejecting any unauthorized or modified code. This prevents malicious firmware from compromising the device’s operation and integrity. With Secure Boot activated, only firmware versions signed by a trusted authority, such as the device manufacturer, will be accepted, ensuring the device remains protected from unauthorized software modifications. **This is irreversible. Once enabled, it CANNOT be disabled.** **IMPORTANT:** For users wishing to develop and compile custom firmware, a private-public key pair is essential. Activating Secure Boot requires users to generate and manage their own unique private-public key pair. The public key from this pair must be embedded into the device to validate all firmware. Firmware will not boot without a proper digital signature from this key pair. This means that users must sign all future firmware versions with their private key and embed the public key in the device to ensure compatibility. -### Secure Lock +### Secure Lock Secure Lock builds on Secure Boot by imposing an even stricter security model. Once activated, Secure Lock prevents any further installation of new boot keys, effectively locking the device to only run firmware that is authorized by the device's primary vendor—in this case, Pico Keys. In addition to preventing additional keys, Secure Lock disables debugging interfaces and puts additional safeguards in place to resist tampering and intrusion attempts. This ensures that the device operates exclusively with the original vendor’s firmware and resists unauthorized access, making it highly secure against external threats. **This is irreversible. Once enabled, it CANNOT be disabled.** **IMPORTANT:** Activating Secure Lock not only enables Secure Boot but also invalidates all keys except the official Pico Key. This means that only firmware signed by Pico Key will be recognized, and custom code will no longer be allowed. Once enabled, the Pico Key device will run solely on the official firmware available on the website, with no option for generating or compiling new code for the device.