Skip to content

Commit e8ff9bd

Browse files
committed
Add enc_bootloader binary
You can now use `picotool encrypt --embed ...` to create a self-decrypting binary, using enc_bootloader
1 parent c2a1145 commit e8ff9bd

File tree

13 files changed

+2307
-103
lines changed

13 files changed

+2307
-103
lines changed

BUILD.bazel

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@ picotool_binary_data_header(
1717
out = "xip_ram_perms_elf.h",
1818
)
1919

20+
# TODO: Make it possible to build the prebuilt from source.
21+
picotool_binary_data_header(
22+
name = "enc_bootloader_elf",
23+
src = "//enc_bootloader:enc_bootloader_prebuilt",
24+
out = "enc_bootloader_elf.h",
25+
)
26+
2027
# TODO: Make it possible to build the prebuilt from source.
2128
picotool_binary_data_header(
2229
name = "flash_id_bin",
@@ -37,6 +44,19 @@ cc_library(
3744
],
3845
)
3946

47+
cc_library(
48+
name = "enc_bootloader",
49+
srcs = ["enc_bootloader.cpp"],
50+
hdrs = [
51+
"enc_bootloader.h",
52+
"enc_bootloader_elf.h",
53+
],
54+
deps = [
55+
"//bazel:data_locs",
56+
"//lib/whereami",
57+
],
58+
)
59+
4060
filegroup(
4161
name = "data_locs_header",
4262
srcs = ["data_locs.h"],
@@ -62,6 +82,7 @@ cc_binary(
6282
"otp.h",
6383
"rp2350.rom.h",
6484
"xip_ram_perms.cpp",
85+
"enc_bootloader.cpp",
6586
] + select({
6687
# MSVC can't handle long strings, so use this manually generated
6788
# header instead.
@@ -97,6 +118,7 @@ cc_binary(
97118
}),
98119
deps = [
99120
":xip_ram_perms",
121+
":enc_bootloader",
100122
"//bazel:data_locs",
101123
"//bintool",
102124
"//elf",

CMakeLists.txt

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,33 @@ if (NOT PICOTOOL_NO_LIBUSB)
8585
DEPENDS xip_ram_perms
8686
)
8787

88+
# compile enc_bootloader.elf
89+
if (NOT DEFINED USE_PRECOMPILED)
90+
set(USE_PRECOMPILED true)
91+
endif()
92+
ExternalProject_Add(enc_bootloader
93+
PREFIX enc_bootloader
94+
SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/enc_bootloader
95+
BINARY_DIR ${CMAKE_BINARY_DIR}/enc_bootloader
96+
CMAKE_ARGS
97+
"-DCMAKE_MAKE_PROGRAM:FILEPATH=${CMAKE_MAKE_PROGRAM}"
98+
"-DPICO_SDK_PATH:FILEPATH=${PICO_SDK_PATH}"
99+
"-DUSE_PRECOMPILED:BOOL=${USE_PRECOMPILED}"
100+
"-DPICO_DEBUG_INFO_IN_RELEASE=OFF"
101+
BUILD_ALWAYS 1 # todo remove this
102+
INSTALL_COMMAND ""
103+
)
104+
105+
set(ENC_BOOTLOADER_ELF ${CMAKE_BINARY_DIR}/enc_bootloader/enc_bootloader.elf)
106+
add_executable(enc_bootloader_elf IMPORTED)
107+
add_dependencies(enc_bootloader_elf enc_bootloader)
108+
set_property(TARGET enc_bootloader_elf PROPERTY IMPORTED_LOCATION ${ENC_BOOTLOADER_ELF})
109+
# copy enc_bootloader.elf into build directory
110+
add_custom_command(TARGET enc_bootloader
111+
COMMAND ${CMAKE_COMMAND} -E copy ${ENC_BOOTLOADER_ELF} ${CMAKE_BINARY_DIR}/enc_bootloader.elf
112+
DEPENDS enc_bootloader
113+
)
114+
88115
# compile flash_id
89116
ExternalProject_Add(flash_id
90117
PREFIX picoboot_flash_id
@@ -172,6 +199,7 @@ endif()
172199
add_custom_target(binary_data DEPENDS
173200
${CMAKE_CURRENT_BINARY_DIR}/rp2350.rom.h
174201
${CMAKE_CURRENT_BINARY_DIR}/xip_ram_perms_elf.h
202+
${CMAKE_CURRENT_BINARY_DIR}/enc_bootloader_elf.h
175203
${CMAKE_CURRENT_BINARY_DIR}/flash_id_bin.h)
176204
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/rp2350.rom.h
177205
COMMAND ${CMAKE_COMMAND}
@@ -188,6 +216,14 @@ add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/xip_ram_perms_elf.h
188216
DEPENDS xip_ram_perms
189217
COMMENT "Configuring xip_ram_perms_elf.h"
190218
VERBATIM)
219+
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/enc_bootloader_elf.h
220+
COMMAND ${CMAKE_COMMAND}
221+
-D BINARY_FILE=${ENC_BOOTLOADER_ELF}
222+
-D OUTPUT_NAME=enc_bootloader_elf
223+
-P ${CMAKE_CURRENT_LIST_DIR}/cmake/binh.cmake
224+
DEPENDS enc_bootloader
225+
COMMENT "Configuring enc_bootloader_elf.h"
226+
VERBATIM)
191227
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/flash_id_bin.h
192228
COMMAND ${CMAKE_COMMAND}
193229
-D BINARY_FILE=${FLASH_ID_BIN}
@@ -233,8 +269,10 @@ target_include_directories(regs_headers INTERFACE ${PICO_SDK_PATH}/src/rp2350/ha
233269
# Main picotool executable
234270
add_executable(picotool
235271
data_locs.cpp
272+
enc_bootloader.cpp
236273
${OTP_EXE}
237274
main.cpp)
275+
add_dependencies(picotool enc_bootloader_elf)
238276
if (NOT PICOTOOL_NO_LIBUSB)
239277
target_sources(picotool PRIVATE xip_ram_perms.cpp)
240278
add_dependencies(picotool generate_otp_header xip_ram_perms_elf binary_data)
@@ -328,6 +366,12 @@ install(FILES
328366
DESTINATION ${INSTALL_CONFIGDIR}
329367
)
330368

369+
#Install enc_bootloader.elf
370+
install(FILES
371+
${ENC_BOOTLOADER_ELF}
372+
DESTINATION ${INSTALL_DATADIR}
373+
)
374+
331375
if (NOT PICOTOOL_NO_LIBUSB)
332376
if (NOT PICOTOOL_CODE_OTP)
333377
#Install the otp json

bintool/bintool.cpp

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -869,8 +869,7 @@ void verify_block(std::vector<uint8_t> bin, uint32_t storage_addr, uint32_t runt
869869
}
870870

871871

872-
int encrypt(elf_file *elf, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign) {
873-
872+
void encrypt_guts(elf_file *elf, block *new_block, const aes_key_t aes_key, std::vector<uint8_t> &iv_data, std::vector<uint8_t> &enc_data) {
874873
std::vector<uint8_t> to_enc = get_lm_hash_data(elf, new_block);
875874

876875
std::random_device rand{};
@@ -886,13 +885,21 @@ int encrypt(elf_file *elf, block *new_block, const aes_key_t aes_key, const publ
886885
e = rand();
887886
}
888887

889-
std::vector<uint8_t> iv_data(iv.bytes, iv.bytes + sizeof(iv.bytes));
888+
iv_data.resize(sizeof(iv.bytes));
889+
memcpy(iv_data.data(), iv.bytes, sizeof(iv.bytes));
890890

891-
std::vector<uint8_t> enc_data;
892891
enc_data.resize(to_enc.size());
893892

894893
aes256_buffer(to_enc.data(), to_enc.size(), enc_data.data(), &aes_key, &iv);
894+
}
895895

896+
897+
int encrypt(elf_file *elf, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign) {
898+
899+
std::vector<uint8_t> iv_data;
900+
std::vector<uint8_t> enc_data;
901+
encrypt_guts(elf, new_block, aes_key, iv_data, enc_data);
902+
896903
unsigned int i=0;
897904
for(const auto &seg : sorted_segs(elf)) {
898905
if (!seg->is_load()) continue;

bintool/bintool.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ std::unique_ptr<block> find_first_block(elf_file *elf);
2525
block place_new_block(elf_file *elf, std::unique_ptr<block> &first_block);
2626
#if HAS_MBEDTLS
2727
int hash_andor_sign(elf_file *elf, block *new_block, const public_t public_key, const private_t private_key, bool hash_value, bool sign, bool clear_sram = false);
28+
void encrypt_guts(elf_file *elf, block *new_block, const aes_key_t aes_key, std::vector<uint8_t> &iv_data, std::vector<uint8_t> &enc_data);
2829
int encrypt(elf_file *elf, block *new_block, const aes_key_t aes_key, const public_t public_key, const private_t private_key, bool hash_value, bool sign);
2930
#endif
3031

enc_bootloader.cpp

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
2+
#include <algorithm>
3+
#include <memory>
4+
#include <iostream>
5+
#include <sstream>
6+
#include <fstream>
7+
8+
#include "enc_bootloader.h"
9+
#include "enc_bootloader_elf.h"
10+
11+
#include "data_locs.h"
12+
13+
#include "whereami++.h"
14+
15+
16+
std::shared_ptr<std::iostream> get_enc_bootloader() {
17+
// search same directory as executable
18+
whereami::whereami_path_t executablePath = whereami::getExecutablePath();
19+
std::string local_loc = executablePath.dirname() + "/";
20+
if (std::find(data_locs.begin(), data_locs.end(), local_loc) == data_locs.end()) {
21+
data_locs.insert(data_locs.begin(), local_loc);
22+
}
23+
24+
for (auto loc : data_locs) {
25+
std::string filename = loc + "enc_bootloader.elf";
26+
std::ifstream i(filename);
27+
if (i.good()) {
28+
printf("Picking file %s\n", filename.c_str());
29+
auto file = std::make_shared<std::fstream>(filename, std::ios::in|std::ios::binary);
30+
return file;
31+
}
32+
}
33+
34+
// fall back to embedded enc_bootloader.elf file
35+
printf("Could not find enc_bootloader.elf file - using embedded binary\n");
36+
auto tmp = std::make_shared<std::stringstream>();
37+
tmp->write(reinterpret_cast<const char*>(enc_bootloader_elf), enc_bootloader_elf_SIZE);
38+
return tmp;
39+
}

enc_bootloader.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
/*
2+
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#pragma once
8+
9+
#include <memory>
10+
#include <fstream>
11+
12+
std::shared_ptr<std::iostream> get_enc_bootloader();

enc_bootloader/BUILD.bazel

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package(default_visibility = ["//visibility:public"])
2+
3+
filegroup(
4+
name = "enc_bootloader_prebuilt",
5+
srcs = ["enc_bootloader.elf"],
6+
)
7+
8+
# TODO: Make this work.
9+
cc_library(
10+
name = "enc_bootloader",
11+
srcs = ["enc_bootloader.c"],
12+
tags = ["manual"],
13+
deps = [
14+
"//:enc_bootloader",
15+
"@pico-sdk//src/rp2_common/pico_stdlib",
16+
"@pico-sdk//src/rp2_common/pico_rand",
17+
],
18+
)

enc_bootloader/CMakeLists.txt

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
cmake_minimum_required(VERSION 3.12)
2+
3+
if (NOT USE_PRECOMPILED)
4+
set(PICO_PLATFORM rp2350-arm-s)
5+
6+
set(PICO_NO_PICOTOOL 1)
7+
8+
# If the user set these environment variables to influence the picotool
9+
# build, unset them here so that they do not influence the pico-sdk
10+
# build. This is especially required for flags that are not supported
11+
# by arm-none-eabi compilers.
12+
unset(ENV{CFLAGS})
13+
unset(ENV{CXXFLAGS})
14+
unset(ENV{LDFLAGS})
15+
16+
# Pull in SDK (must be before project)
17+
include(${PICO_SDK_PATH}/external/pico_sdk_import.cmake)
18+
19+
project(enc_bootloader C CXX ASM)
20+
set(CMAKE_C_STANDARD 11)
21+
set(CMAKE_CXX_STANDARD 17)
22+
23+
if (PICO_SDK_VERSION_STRING VERSION_LESS "2.0.0")
24+
message(FATAL_ERROR "Raspberry Pi Pico SDK version 2.0.0 (or later) required. Your version is ${PICO_SDK_VERSION_STRING}")
25+
endif()
26+
27+
# Initialize the SDK
28+
pico_sdk_init()
29+
30+
# Encrypted Bootloader
31+
add_executable(enc_bootloader
32+
enc_bootloader.c
33+
aes.S
34+
)
35+
36+
target_link_libraries(enc_bootloader
37+
pico_stdlib
38+
pico_rand
39+
)
40+
41+
pico_set_binary_type(enc_bootloader no_flash)
42+
# create linker script to run from 0x20070000
43+
file(READ ${PICO_LINKER_SCRIPT_PATH}/memmap_no_flash.ld LINKER_SCRIPT)
44+
string(REPLACE "RAM(rwx) : ORIGIN = 0x20000000, LENGTH = 512k" "RAM(rwx) : ORIGIN = 0x20078000, LENGTH = 32k" LINKER_SCRIPT "${LINKER_SCRIPT}")
45+
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/memmap_enc_bootloader.ld "${LINKER_SCRIPT}")
46+
pico_set_linker_script(enc_bootloader ${CMAKE_CURRENT_BINARY_DIR}/memmap_enc_bootloader.ld)
47+
else()
48+
project(enc_bootloader C CXX ASM)
49+
message("Using precompiled enc_bootloader.elf")
50+
configure_file(${CMAKE_CURRENT_LIST_DIR}/enc_bootloader.elf ${CMAKE_CURRENT_BINARY_DIR}/enc_bootloader.elf COPYONLY)
51+
# Use manually specified variables
52+
set(NULL ${CMAKE_MAKE_PROGRAM})
53+
set(NULL ${PICO_SDK_PATH})
54+
set(NULL ${PICO_DEBUG_INFO_IN_RELEASE})
55+
endif()

0 commit comments

Comments
 (0)