From 33c5559e31d843385d496966d7655274af018d11 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 22 Jan 2025 17:51:47 +0000 Subject: [PATCH 1/7] Add pico_create_decrypting_binary function For now, this function embeds the decrypting bootloader, but probably better to integrate (or replace) existing pico_encrypt_binary function --- tools/CMakeLists.txt | 52 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 7d68c9107..c8cb0065b 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -41,6 +41,12 @@ define_property(TARGET BRIEF_DOCS "AES key for encrypting" FULL_DOCS "AES key for encrypting" ) +define_property(TARGET + PROPERTY PICOTOOL_EMBED_DECRYPTION + INHERITED + BRIEF_DOCS "Embed decryption stage into encrypted binary" + FULL_DOCS "Embed decryption stage into encrypted binary" +) define_property(TARGET PROPERTY PICOTOOL_ENC_SIGFILE INHERITED @@ -382,7 +388,7 @@ endfunction() # pico_encrypt_binary(TARGET AESFILE [SIGFILE]) # Encrypt the target binary with the given AES key (should be a binary -# file containing 32 bytes of a random key), and sign the encrypted binary. +# file containing 128 bytes of a random key), and sign the encrypted binary. # This sets PICOTOOL_AESFILE to AESFILE, and PICOTOOL_ENC_SIGFILE to SIGFILE # if present, else PICOTOOL_SIGFILE. function(pico_encrypt_binary TARGET AESFILE) @@ -409,6 +415,37 @@ function(pico_encrypt_binary TARGET AESFILE) endif() endfunction() +# pico_create_decrypting_binary(TARGET AESFILE [SIGFILE]) +# Encrypt the target binary with the given AES key (should be a binary +# file containing 128 bytes of a random key), add a decryption stage to +# decrypt the binary at runtime, and then sign the encrypted binary. +# This sets PICOTOOL_AESFILE to AESFILE, PICOTOOL_EMBED_DECRYPTION to TRUE, +# and PICOTOOL_ENC_SIGFILE to SIGFILE if present, else PICOTOOL_SIGFILE. +function(pico_create_decrypting_binary TARGET AESFILE) + picotool_check_configurable(${TARGET}) + set_target_properties(${TARGET} PROPERTIES + PICOTOOL_AESFILE ${AESFILE} + PICOTOOL_EMBED_DECRYPTION TRUE + ) + if (ARGC EQUAL 3) + set_target_properties(${TARGET} PROPERTIES + PICOTOOL_ENC_SIGFILE ${ARGV2} + ) + else() + get_target_property(enc_sig_file ${TARGET} PICOTOOL_ENC_SIGFILE) + if (NOT enc_sig_file) + get_target_property(sig_file ${TARGET} PICOTOOL_SIGFILE) + if (NOT sig_file) + message(FATAL_ERROR "Signature file not set for ${TARGET}") + else() + set_target_properties(${TARGET} PROPERTIES + PICOTOOL_ENC_SIGFILE ${sig_file} + ) + endif() + endif() + endif() +endfunction() + # pico_add_uf2_output(TARGET) # Add a UF2 output using picotool - must be called after # all required properties have been set @@ -547,9 +584,20 @@ function(picotool_postprocess_binary TARGET) endif() # Encryption if (picotool_aesfile) + get_target_property(picotool_embed_decryption ${TARGET} PICOTOOL_EMBED_DECRYPTION) + if (picotool_embed_decryption) + list(APPEND picotool_encrypt_args "--embed") + endif() + add_custom_command(TARGET ${TARGET} POST_BUILD DEPENDS ${picotool_enc_sigfile} ${picotool_aesfile} - COMMAND picotool encrypt --quiet --hash --sign $ $ ${picotool_aesfile} ${picotool_enc_sigfile} + COMMAND picotool + ARGS encrypt + --quiet --hash --sign + ${picotool_encrypt_args} + $ $ + ${picotool_aesfile} ${picotool_enc_sigfile} + COMMAND_EXPAND_LISTS VERBATIM) if (ARGC EQUAL 2) set(${ARGV1} TRUE PARENT_SCOPE) From 9856a080e29957b49f65233bcb47ce30e3e7a8bd Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Thu, 23 Jan 2025 11:58:30 +0000 Subject: [PATCH 2/7] Add EMBED and OTP_KEY_PAGE arguments to pico_encrypt_binary function --- tools/CMakeLists.txt | 61 ++++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 30 deletions(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index c8cb0065b..7de94d306 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -47,6 +47,12 @@ define_property(TARGET BRIEF_DOCS "Embed decryption stage into encrypted binary" FULL_DOCS "Embed decryption stage into encrypted binary" ) +define_property(TARGET + PROPERTY PICOTOOL_OTP_KEY_PAGE + INHERITED + BRIEF_DOCS "OTP page storing the AES key" + FULL_DOCS "OTP page storing the AES key" +) define_property(TARGET PROPERTY PICOTOOL_ENC_SIGFILE INHERITED @@ -386,50 +392,40 @@ function(pico_embed_pt_in_binary TARGET PTFILE) ) endfunction() -# pico_encrypt_binary(TARGET AESFILE [SIGFILE]) +# pico_encrypt_binary(TARGET AESFILE [SIGFILE ] [EMBED] [OTP_KEY_PAGE ]) # Encrypt the target binary with the given AES key (should be a binary # file containing 128 bytes of a random key), and sign the encrypted binary. # This sets PICOTOOL_AESFILE to AESFILE, and PICOTOOL_ENC_SIGFILE to SIGFILE # if present, else PICOTOOL_SIGFILE. +# Optionally, use EMBED to embed a decryption stage into the encrypted binary. +# This sets PICOTOOL_EMBED_DECRYPTION to TRUE. +# Optionally, use OTP_KEY_PAGE to specify the OTP page storing the AES key. +# This sets PICOTOOL_OTP_KEY_PAGE to OTP_KEY_PAGE. function(pico_encrypt_binary TARGET AESFILE) + set(options EMBED) + set(oneValueArgs OTP_KEY_PAGE SIGFILE) + # set(multiValueArgs ) + cmake_parse_arguments(PARSE_ARGV 2 ENC "${options}" "${oneValueArgs}" "${multiValueArgs}") picotool_check_configurable(${TARGET}) set_target_properties(${TARGET} PROPERTIES PICOTOOL_AESFILE ${AESFILE} ) - if (ARGC EQUAL 3) + + if (ENC_EMBED) set_target_properties(${TARGET} PROPERTIES - PICOTOOL_ENC_SIGFILE ${ARGV2} + PICOTOOL_EMBED_DECRYPTION TRUE ) - else() - get_target_property(enc_sig_file ${TARGET} PICOTOOL_ENC_SIGFILE) - if (NOT enc_sig_file) - get_target_property(sig_file ${TARGET} PICOTOOL_SIGFILE) - if (NOT sig_file) - message(FATAL_ERROR "Signature file not set for ${TARGET}") - else() - set_target_properties(${TARGET} PROPERTIES - PICOTOOL_ENC_SIGFILE ${sig_file} - ) - endif() - endif() endif() -endfunction() -# pico_create_decrypting_binary(TARGET AESFILE [SIGFILE]) -# Encrypt the target binary with the given AES key (should be a binary -# file containing 128 bytes of a random key), add a decryption stage to -# decrypt the binary at runtime, and then sign the encrypted binary. -# This sets PICOTOOL_AESFILE to AESFILE, PICOTOOL_EMBED_DECRYPTION to TRUE, -# and PICOTOOL_ENC_SIGFILE to SIGFILE if present, else PICOTOOL_SIGFILE. -function(pico_create_decrypting_binary TARGET AESFILE) - picotool_check_configurable(${TARGET}) - set_target_properties(${TARGET} PROPERTIES - PICOTOOL_AESFILE ${AESFILE} - PICOTOOL_EMBED_DECRYPTION TRUE - ) - if (ARGC EQUAL 3) + if (ENC_OTP_KEY_PAGE) set_target_properties(${TARGET} PROPERTIES - PICOTOOL_ENC_SIGFILE ${ARGV2} + PICOTOOL_OTP_KEY_PAGE ${ENC_OTP_KEY_PAGE} + ) + endif() + + if (ENC_SIGFILE) + set_target_properties(${TARGET} PROPERTIES + PICOTOOL_ENC_SIGFILE ${ENC_SIGFILE} ) else() get_target_property(enc_sig_file ${TARGET} PICOTOOL_ENC_SIGFILE) @@ -589,6 +585,11 @@ function(picotool_postprocess_binary TARGET) list(APPEND picotool_encrypt_args "--embed") endif() + get_target_property(otp_key_page ${TARGET} PICOTOOL_OTP_KEY_PAGE) + if (otp_key_page) + list(APPEND picotool_encrypt_args "--otp-key-page" ${otp_key_page}) + endif() + add_custom_command(TARGET ${TARGET} POST_BUILD DEPENDS ${picotool_enc_sigfile} ${picotool_aesfile} COMMAND picotool From c7cb10c803c4e0f39cc569283c09ecd7df299a25 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 5 Feb 2025 16:00:17 +0000 Subject: [PATCH 3/7] Support passing otp_file to picotool encrypt --- tools/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 7de94d306..0a2afe4ca 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -597,7 +597,7 @@ function(picotool_postprocess_binary TARGET) --quiet --hash --sign ${picotool_encrypt_args} $ $ - ${picotool_aesfile} ${picotool_enc_sigfile} + ${picotool_aesfile} ${picotool_enc_sigfile} ${otp_file} COMMAND_EXPAND_LISTS VERBATIM) if (ARGC EQUAL 2) From ea9dcb053a4b8633ed28a625cae909352cf81fd1 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 26 Feb 2025 12:36:08 +0000 Subject: [PATCH 4/7] Add IV salt to pico_encrypt_binary --- tools/CMakeLists.txt | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 0a2afe4ca..8d2139f09 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -41,6 +41,12 @@ define_property(TARGET BRIEF_DOCS "AES key for encrypting" FULL_DOCS "AES key for encrypting" ) +define_property(TARGET + PROPERTY PICOTOOL_IVFILE + INHERITED + BRIEF_DOCS "IV OTP salt for encrypting" + FULL_DOCS "IV OTP salt for encrypting" +) define_property(TARGET PROPERTY PICOTOOL_EMBED_DECRYPTION INHERITED @@ -392,24 +398,29 @@ function(pico_embed_pt_in_binary TARGET PTFILE) ) endfunction() -# pico_encrypt_binary(TARGET AESFILE [SIGFILE ] [EMBED] [OTP_KEY_PAGE ]) +# pico_encrypt_binary(TARGET AESFILE IVFILE [SIGFILE ] [EMBED] [OTP_KEY_PAGE ]) # Encrypt the target binary with the given AES key (should be a binary # file containing 128 bytes of a random key), and sign the encrypted binary. -# This sets PICOTOOL_AESFILE to AESFILE, and PICOTOOL_ENC_SIGFILE to SIGFILE -# if present, else PICOTOOL_SIGFILE. +# Salts the public IV with the provided IVFILE (should be a binary file +# containing 16 bytes of a random IV), to give the IV used by the encryption. +# This sets PICOTOOL_AESFILE to AESFILE, PICOTOOL_IVFILE to IVFILE, and +# PICOTOOL_ENC_SIGFILE to SIGFILE if specified, else PICOTOOL_SIGFILE. # Optionally, use EMBED to embed a decryption stage into the encrypted binary. # This sets PICOTOOL_EMBED_DECRYPTION to TRUE. # Optionally, use OTP_KEY_PAGE to specify the OTP page storing the AES key. # This sets PICOTOOL_OTP_KEY_PAGE to OTP_KEY_PAGE. -function(pico_encrypt_binary TARGET AESFILE) +function(pico_encrypt_binary TARGET AESFILE IVFILE) set(options EMBED) set(oneValueArgs OTP_KEY_PAGE SIGFILE) # set(multiValueArgs ) - cmake_parse_arguments(PARSE_ARGV 2 ENC "${options}" "${oneValueArgs}" "${multiValueArgs}") + cmake_parse_arguments(PARSE_ARGV 3 ENC "${options}" "${oneValueArgs}" "${multiValueArgs}") picotool_check_configurable(${TARGET}) set_target_properties(${TARGET} PROPERTIES PICOTOOL_AESFILE ${AESFILE} ) + set_target_properties(${TARGET} PROPERTIES + PICOTOOL_IVFILE ${IVFILE} + ) if (ENC_EMBED) set_target_properties(${TARGET} PROPERTIES @@ -540,6 +551,10 @@ function(picotool_postprocess_binary TARGET) if (picotool_aesfile) pico_add_link_depend(${TARGET} ${picotool_aesfile}) endif() + get_target_property(picotool_ivfile ${TARGET} PICOTOOL_IVFILE) + if (picotool_ivfile) + pico_add_link_depend(${TARGET} ${picotool_ivfile}) + endif() get_target_property(picotool_enc_sigfile ${TARGET} PICOTOOL_ENC_SIGFILE) if (picotool_enc_sigfile) pico_add_link_depend(${TARGET} ${picotool_enc_sigfile}) @@ -579,7 +594,7 @@ function(picotool_postprocess_binary TARGET) VERBATIM) endif() # Encryption - if (picotool_aesfile) + if (picotool_aesfile AND picotool_ivfile) get_target_property(picotool_embed_decryption ${TARGET} PICOTOOL_EMBED_DECRYPTION) if (picotool_embed_decryption) list(APPEND picotool_encrypt_args "--embed") @@ -591,13 +606,13 @@ function(picotool_postprocess_binary TARGET) endif() add_custom_command(TARGET ${TARGET} POST_BUILD - DEPENDS ${picotool_enc_sigfile} ${picotool_aesfile} + DEPENDS ${picotool_enc_sigfile} ${picotool_aesfile} ${picotool_ivfile} COMMAND picotool ARGS encrypt --quiet --hash --sign ${picotool_encrypt_args} $ $ - ${picotool_aesfile} ${picotool_enc_sigfile} ${otp_file} + ${picotool_aesfile} ${picotool_ivfile} ${picotool_enc_sigfile} ${otp_file} COMMAND_EXPAND_LISTS VERBATIM) if (ARGC EQUAL 2) From 9b16b83c45ad40356d5ac75875a7a8d8e940c75e Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Tue, 4 Mar 2025 15:51:35 +0000 Subject: [PATCH 5/7] Add MBEDTLS option to use mbedtls decryption stage --- tools/CMakeLists.txt | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 8d2139f09..292c5ffef 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -53,6 +53,12 @@ define_property(TARGET BRIEF_DOCS "Embed decryption stage into encrypted binary" FULL_DOCS "Embed decryption stage into encrypted binary" ) +define_property(TARGET + PROPERTY PICOTOOL_USE_MBEDTLS_DECRYPTION + INHERITED + BRIEF_DOCS "Use MbedTLS based decryption stage - this is faster, but not secure against power snooping" + FULL_DOCS "Use MbedTLS based decryption stage - this is faster, but not secure against power snooping" +) define_property(TARGET PROPERTY PICOTOOL_OTP_KEY_PAGE INHERITED @@ -398,7 +404,7 @@ function(pico_embed_pt_in_binary TARGET PTFILE) ) endfunction() -# pico_encrypt_binary(TARGET AESFILE IVFILE [SIGFILE ] [EMBED] [OTP_KEY_PAGE ]) +# pico_encrypt_binary(TARGET AESFILE IVFILE [SIGFILE ] [EMBED] [MBEDTLS] [OTP_KEY_PAGE ]) # Encrypt the target binary with the given AES key (should be a binary # file containing 128 bytes of a random key), and sign the encrypted binary. # Salts the public IV with the provided IVFILE (should be a binary file @@ -407,10 +413,13 @@ endfunction() # PICOTOOL_ENC_SIGFILE to SIGFILE if specified, else PICOTOOL_SIGFILE. # Optionally, use EMBED to embed a decryption stage into the encrypted binary. # This sets PICOTOOL_EMBED_DECRYPTION to TRUE. +# Optionally, use MBEDTLS to to use the MbedTLS based decryption stage - this +# is faster, but less secure. +# This sets PICOTOOL_USE_MBEDTLS_DECRYPTION to TRUE. # Optionally, use OTP_KEY_PAGE to specify the OTP page storing the AES key. # This sets PICOTOOL_OTP_KEY_PAGE to OTP_KEY_PAGE. function(pico_encrypt_binary TARGET AESFILE IVFILE) - set(options EMBED) + set(options EMBED MBEDTLS) set(oneValueArgs OTP_KEY_PAGE SIGFILE) # set(multiValueArgs ) cmake_parse_arguments(PARSE_ARGV 3 ENC "${options}" "${oneValueArgs}" "${multiValueArgs}") @@ -428,6 +437,12 @@ function(pico_encrypt_binary TARGET AESFILE IVFILE) ) endif() + if (ENC_MBEDTLS) + set_target_properties(${TARGET} PROPERTIES + PICOTOOL_USE_MBEDTLS_DECRYPTION TRUE + ) + endif() + if (ENC_OTP_KEY_PAGE) set_target_properties(${TARGET} PROPERTIES PICOTOOL_OTP_KEY_PAGE ${ENC_OTP_KEY_PAGE} @@ -600,6 +615,11 @@ function(picotool_postprocess_binary TARGET) list(APPEND picotool_encrypt_args "--embed") endif() + get_target_property(picotool_mbedtls_decryption ${TARGET} PICOTOOL_USE_MBEDTLS_DECRYPTION) + if (picotool_mbedtls_decryption) + list(APPEND picotool_encrypt_args "--use-mbedtls") + endif() + get_target_property(otp_key_page ${TARGET} PICOTOOL_OTP_KEY_PAGE) if (otp_key_page) list(APPEND picotool_encrypt_args "--otp-key-page" ${otp_key_page}) From fd83496776f7a309f9cbe0f9bca85ddd763cab39 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Wed, 26 Mar 2025 16:16:43 +0000 Subject: [PATCH 6/7] Improve docs for pico_encrypt_binary Add newlines for readability, and explain why MbedTLS version is insecure --- tools/CMakeLists.txt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 292c5ffef..eb81256d5 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -411,11 +411,15 @@ endfunction() # containing 16 bytes of a random IV), to give the IV used by the encryption. # This sets PICOTOOL_AESFILE to AESFILE, PICOTOOL_IVFILE to IVFILE, and # PICOTOOL_ENC_SIGFILE to SIGFILE if specified, else PICOTOOL_SIGFILE. +# # Optionally, use EMBED to embed a decryption stage into the encrypted binary. # This sets PICOTOOL_EMBED_DECRYPTION to TRUE. +# # Optionally, use MBEDTLS to to use the MbedTLS based decryption stage - this -# is faster, but less secure. +# is faster, but offers no security against power or timing sniffing attacks, +# and takes up more code size. # This sets PICOTOOL_USE_MBEDTLS_DECRYPTION to TRUE. +# # Optionally, use OTP_KEY_PAGE to specify the OTP page storing the AES key. # This sets PICOTOOL_OTP_KEY_PAGE to OTP_KEY_PAGE. function(pico_encrypt_binary TARGET AESFILE IVFILE) From c0f179f816868d4aa940c1891e7a10f8bd7d69c6 Mon Sep 17 00:00:00 2001 From: William Vinnicombe Date: Mon, 28 Apr 2025 16:47:21 +0100 Subject: [PATCH 7/7] Key can be 128 byte key share or 32 byte key --- tools/CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index eb81256d5..f13b49b31 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -406,7 +406,8 @@ endfunction() # pico_encrypt_binary(TARGET AESFILE IVFILE [SIGFILE ] [EMBED] [MBEDTLS] [OTP_KEY_PAGE ]) # Encrypt the target binary with the given AES key (should be a binary -# file containing 128 bytes of a random key), and sign the encrypted binary. +# file containing 128 bytes of a random key share, or 32 bytes of a random key), +# and sign the encrypted binary. # Salts the public IV with the provided IVFILE (should be a binary file # containing 16 bytes of a random IV), to give the IV used by the encryption. # This sets PICOTOOL_AESFILE to AESFILE, PICOTOOL_IVFILE to IVFILE, and