Commit d1ad057996de94fa28611e1d3f415488befecdbf

Authored by Tim Gover
Committed by GitHub
2 parents 879641fc 5f8c2336

Merge pull request #98 from timg236/secure-boot-hsm

secure-boot: Add more documentation about the RSA signatures and add an optional public key argument
Readme.md
@@ -140,9 +140,28 @@ rmdir boot-mount @@ -140,9 +140,28 @@ rmdir boot-mount
140 ``` 140 ```
141 141
142 #### Sign the boot image 142 #### 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 +
143 ```bash 147 ```bash
144 ../tools/rpi-eeprom-digest -i boot.img -o boot.sig -k "${KEY_FILE}" 148 ../tools/rpi-eeprom-digest -i boot.img -o boot.sig -k "${KEY_FILE}"
145 ``` 149 ```
  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 +```
146 165
147 #### Copy the secure boot image to the boot partition on the Raspberry Pi. 166 #### Copy the secure boot image to the boot partition on the Raspberry Pi.
148 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). 167 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 0 → 100644
  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`.
secure-boot-example/example-public.pem 0 → 100644
  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
1 # USB MSD device mode drivers for signed-boot 1 # USB MSD device mode drivers for signed-boot
2 2
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.
6 7
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.
8 10
  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:-
9 ```bash 15 ```bash
10 KEY_FILE=$HOME/private.pem 16 KEY_FILE=$HOME/private.pem
11 ../tools/rpi-eeprom-digest -i boot.img -o boot.sig -k "${KEY_FILE}" 17 ../tools/rpi-eeprom-digest -i boot.img -o boot.sig -k "${KEY_FILE}"
tools/update-pieeprom.sh
@@ -16,6 +16,7 @@ SRC_IMAGE="pieeprom.original.bin" @@ -16,6 +16,7 @@ SRC_IMAGE="pieeprom.original.bin"
16 CONFIG="boot.conf" 16 CONFIG="boot.conf"
17 DST_IMAGE="pieeprom.bin" 17 DST_IMAGE="pieeprom.bin"
18 PEM_FILE="" 18 PEM_FILE=""
  19 +PUBLIC_PEM_FILE=""
19 TMP_CONFIG_SIG="" 20 TMP_CONFIG_SIG=""
20 21
21 die() { 22 die() {
@@ -43,12 +44,19 @@ cat <<EOF @@ -43,12 +44,19 @@ cat <<EOF
43 -c Bootloader config file - default: "${SRC_IMAGE}" 44 -c Bootloader config file - default: "${SRC_IMAGE}"
44 -i Source EEPROM image - default: "${CONFIG}" 45 -i Source EEPROM image - default: "${CONFIG}"
45 -o Output EEPROM image - default: "${DST_IMAGE}" 46 -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.
47 49
48 The -k argument signs the EEPROM configuration using the specified RSA 2048 50 The -k argument signs the EEPROM configuration using the specified RSA 2048
49 bit private key in PEM format. It also embeds the public portion of the RSA 51 bit private key in PEM format. It also embeds the public portion of the RSA
50 key pair in the EEPROM image so that the bootloader can verify the signed OS 52 key pair in the EEPROM image so that the bootloader can verify the signed OS
51 image. 53 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 +
52 EOF 60 EOF
53 } 61 }
54 62
@@ -57,6 +65,7 @@ update_eeprom() { @@ -57,6 +65,7 @@ update_eeprom() {
57 config="$2" 65 config="$2"
58 dst_image="$3" 66 dst_image="$3"
59 pem_file="$4" 67 pem_file="$4"
  68 + public_pem_file="$5"
60 sign_args="" 69 sign_args=""
61 70
62 if [ -n "${pem_file}" ]; then 71 if [ -n "${pem_file}" ]; then
@@ -83,14 +92,16 @@ update_eeprom() { @@ -83,14 +92,16 @@ update_eeprom() {
83 # PEM file. It will also accept just the public key so it's possible 92 # PEM file. It will also accept just the public key so it's possible
84 # to tweak this script so that rpi-eeprom-config never sees the private 93 # to tweak this script so that rpi-eeprom-config never sees the private
85 # key. 94 # key.
86 - sign_args="-d ${TMP_CONFIG_SIG} -p ${pem_file}" 95 + sign_args="-d ${TMP_CONFIG_SIG} -p ${public_pem_file}"
87 fi 96 fi
88 97
89 rm -f "${dst_image}" 98 rm -f "${dst_image}"
  99 + set -x
90 ${script_dir}/rpi-eeprom-config \ 100 ${script_dir}/rpi-eeprom-config \
91 --config "${config}" \ 101 --config "${config}" \
92 --out "${dst_image}" ${sign_args} \ 102 --out "${dst_image}" ${sign_args} \
93 "${src_image}" || die "Failed to update EEPROM image" 103 "${src_image}" || die "Failed to update EEPROM image"
  104 + set +x
94 105
95 cat <<EOF 106 cat <<EOF
96 new-image: ${dst_image} 107 new-image: ${dst_image}
@@ -106,7 +117,7 @@ image_digest() { @@ -106,7 +117,7 @@ image_digest() {
106 117
107 trap cleanup EXIT 118 trap cleanup EXIT
108 119
109 -while getopts "c:hi:o:k:" option; do 120 +while getopts "c:hi:o:k:p:" option; do
110 case "${option}" in 121 case "${option}" in
111 c) CONFIG="${OPTARG}" 122 c) CONFIG="${OPTARG}"
112 ;; 123 ;;
@@ -116,6 +127,8 @@ while getopts &quot;c:hi:o:k:&quot; option; do @@ -116,6 +127,8 @@ while getopts &quot;c:hi:o:k:&quot; option; do
116 ;; 127 ;;
117 k) PEM_FILE="${OPTARG}" 128 k) PEM_FILE="${OPTARG}"
118 ;; 129 ;;
  130 + p) PUBLIC_PEM_FILE="${OPTARG}"
  131 + ;;
119 h) usage 132 h) usage
120 ;; 133 ;;
121 *) echo "Unknown argument \"${option}\"" 134 *) echo "Unknown argument \"${option}\""
@@ -130,8 +143,15 @@ if [ -n &quot;${PEM_FILE}&quot; ]; then @@ -130,8 +143,15 @@ if [ -n &quot;${PEM_FILE}&quot; ]; then
130 [ -f "${PEM_FILE}" ] || die "RSA key file \"${PEM_FILE}\" not found" 143 [ -f "${PEM_FILE}" ] || die "RSA key file \"${PEM_FILE}\" not found"
131 fi 144 fi
132 145
  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 +
133 DST_IMAGE_SIG="$(echo "${DST_IMAGE}" | sed 's/\..*//').sig" 153 DST_IMAGE_SIG="$(echo "${DST_IMAGE}" | sed 's/\..*//').sig"
134 154
135 -update_eeprom "${SRC_IMAGE}" "${CONFIG}" "${DST_IMAGE}" "${PEM_FILE}" 155 +update_eeprom "${SRC_IMAGE}" "${CONFIG}" "${DST_IMAGE}" "${PEM_FILE}" "${PUBLIC_PEM_FILE}"
136 image_digest "${DST_IMAGE}" "${DST_IMAGE_SIG}" 156 image_digest "${DST_IMAGE}" "${DST_IMAGE_SIG}"
137 157