Skip to content

Commit 5f8c233

Browse files
author
tim
committed
secure-boot: Add more documentation about the RSA signatures and add optional public key argument
Add some more detail about the RSA signatures. Tweak update-pieeprom.sh so add a separate argument for the public key in order to make it easier to customize the script for hardware security modules.
1 parent 879641f commit 5f8c233

File tree

5 files changed

+65
-8
lines changed

5 files changed

+65
-8
lines changed

Readme.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,28 @@ rmdir boot-mount
140140
```
141141

142142
#### Sign the boot image
143+
For secure-boot, `rpi-eeprom-digest` extends the current `.sig` format of
144+
sha256 + timestamp to include an hex format RSA bit PKCS#1 v1.5 signature. The key length
145+
must be 2048 bits.
146+
143147
```bash
144148
../tools/rpi-eeprom-digest -i boot.img -o boot.sig -k "${KEY_FILE}"
145149
```
150+
#### Hardware security modules
151+
`rpi-eeprom-digest` is a shell script that wraps a call to `openssl dgst -sign`.
152+
If the private key is stored withing a hardware security module instead of
153+
a .PEM file the `openssl` command will need to be replaced with the appropriate call to the HSM.
154+
155+
`rpi-eeprom-digest` called by `update-pieeprom.sh` to sign the EEPROM config file.
156+
157+
The RSA public key must be stored within the EEPROM so that it can be used by the bootloader.
158+
By default, the RSA public key is automatically extracted from the private key PEM file. Alternatively,
159+
the public key may be specified separately via the `-p` argument to `update-pieeprom.sh` and `rpi-eeprom-config`.
160+
161+
To extract the public key in PEM format from a private key PEM file run.
162+
```bash
163+
openssl rsa -in private.pem -pubout -out public.pem`
164+
```
146165

147166
#### Copy the secure boot image to the boot partition on the Raspberry Pi.
148167
Copy `boot.img` and `boot.sig` to the chosen boot filesystem. Secure boot images can be loaded from any of the normal boot devices (e.g. SD, USB, Network).

secure-boot-example/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
This directory contains an example secure boot image signed with the example private key in this directory.
2+
3+
Clearly, product releases should never be signed with `example-private.pem`.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
-----BEGIN PUBLIC KEY-----
2+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+l3E+h/QNjrIR1cG6Npz
3+
P0fBwp2UDpuQAafXDS5yryrfCPDYTO9DvzAfOk9Dz/putDfHV0RTOFXv1tmc4nqO
4+
gU6nKx7tTdsjTiY4CgG3vXRMuAmDGX5ssJFCVmljGuILt1INlCmtun7Ow35VTxOc
5+
RDDfrBDKnSitzOTf6KTR7xJhqFFhdMpIg8hW4bDBKMavyt38pRvDaO1o01qaQT/G
6+
gAPmJm27y5RKNAe6iVTqsm4TMAhKC6P4XyRAbe6OMdFZyEWEk7Asexuc7uZlVHsU
7+
I6pebSW/07O+5l/U7/3k6r//hO/HDFOBUUW55EjzzC1BhTlWHWfZNI+5+NdN8o32
8+
3QIDAQAB
9+
-----END PUBLIC KEY-----

secure-boot-msd/README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
11
# USB MSD device mode drivers for signed-boot
22

3-
If secure-boot has been enabled then this image must be signed with
4-
the customer's RSA private key. Otherwise, the SPI EEPROM bootloader
5-
will refused to load this image.
3+
If secure-boot mode has been locked (via OTP) then both the
4+
bootloader and rpiboot `bootcode4.bin` will only load `boot.img`
5+
files signed with the customer's private key. Therefore, access
6+
to rpiboot mass storage mode is disabled.
67

7-
To do this run:
8+
Mass storage mode can be re-enabled by signing a boot image
9+
containing the firmware mass storage drivers.
810

11+
N.B. The signed image should normally be kept secure because can
12+
be used on any device signed with the same customer key.
13+
14+
To sign the mass storage mode boot image run:-
915
```bash
1016
KEY_FILE=$HOME/private.pem
1117
../tools/rpi-eeprom-digest -i boot.img -o boot.sig -k "${KEY_FILE}"

tools/update-pieeprom.sh

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ SRC_IMAGE="pieeprom.original.bin"
1616
CONFIG="boot.conf"
1717
DST_IMAGE="pieeprom.bin"
1818
PEM_FILE=""
19+
PUBLIC_PEM_FILE=""
1920
TMP_CONFIG_SIG=""
2021

2122
die() {
@@ -43,12 +44,19 @@ cat <<EOF
4344
-c Bootloader config file - default: "${SRC_IMAGE}"
4445
-i Source EEPROM image - default: "${CONFIG}"
4546
-o Output EEPROM image - default: "${DST_IMAGE}"
46-
-k Optional RSA private PEM file - default: "${PEM_FILE}"
47+
-k Optional RSA private key PEM file.
48+
-p Optional RSA public key PEM file.
4749
4850
The -k argument signs the EEPROM configuration using the specified RSA 2048
4951
bit private key in PEM format. It also embeds the public portion of the RSA
5052
key pair in the EEPROM image so that the bootloader can verify the signed OS
5153
image.
54+
55+
If the public key is not specified then rpi-eeprom-config will extract this
56+
automatically from the private key. Typically, the [-p] public key argument
57+
would only be used if rpi-eeprom-digest has been modified to use a hardware
58+
security module instead of a private key file.
59+
5260
EOF
5361
}
5462

@@ -57,6 +65,7 @@ update_eeprom() {
5765
config="$2"
5866
dst_image="$3"
5967
pem_file="$4"
68+
public_pem_file="$5"
6069
sign_args=""
6170

6271
if [ -n "${pem_file}" ]; then
@@ -83,14 +92,16 @@ update_eeprom() {
8392
# PEM file. It will also accept just the public key so it's possible
8493
# to tweak this script so that rpi-eeprom-config never sees the private
8594
# key.
86-
sign_args="-d ${TMP_CONFIG_SIG} -p ${pem_file}"
95+
sign_args="-d ${TMP_CONFIG_SIG} -p ${public_pem_file}"
8796
fi
8897

8998
rm -f "${dst_image}"
99+
set -x
90100
${script_dir}/rpi-eeprom-config \
91101
--config "${config}" \
92102
--out "${dst_image}" ${sign_args} \
93103
"${src_image}" || die "Failed to update EEPROM image"
104+
set +x
94105

95106
cat <<EOF
96107
new-image: ${dst_image}
@@ -106,7 +117,7 @@ image_digest() {
106117

107118
trap cleanup EXIT
108119

109-
while getopts "c:hi:o:k:" option; do
120+
while getopts "c:hi:o:k:p:" option; do
110121
case "${option}" in
111122
c) CONFIG="${OPTARG}"
112123
;;
@@ -116,6 +127,8 @@ while getopts "c:hi:o:k:" option; do
116127
;;
117128
k) PEM_FILE="${OPTARG}"
118129
;;
130+
p) PUBLIC_PEM_FILE="${OPTARG}"
131+
;;
119132
h) usage
120133
;;
121134
*) echo "Unknown argument \"${option}\""
@@ -130,8 +143,15 @@ if [ -n "${PEM_FILE}" ]; then
130143
[ -f "${PEM_FILE}" ] || die "RSA key file \"${PEM_FILE}\" not found"
131144
fi
132145

146+
# If a public key is specified then use it. Otherwise, if just the private
147+
# key is specified then let rpi-eeprom-config automatically extract the
148+
# public key from the private key PEM file.
149+
if [ -z "${PUBLIC_PEM_FILE}" ]; then
150+
PUBLIC_PEM_FILE="${PEM_FILE}"
151+
fi
152+
133153
DST_IMAGE_SIG="$(echo "${DST_IMAGE}" | sed 's/\..*//').sig"
134154

135-
update_eeprom "${SRC_IMAGE}" "${CONFIG}" "${DST_IMAGE}" "${PEM_FILE}"
155+
update_eeprom "${SRC_IMAGE}" "${CONFIG}" "${DST_IMAGE}" "${PEM_FILE}" "${PUBLIC_PEM_FILE}"
136156
image_digest "${DST_IMAGE}" "${DST_IMAGE_SIG}"
137157

0 commit comments

Comments
 (0)