Commit 5f8c23365006d689e49d99029ddb3d9713c2c90a

Authored by tim
1 parent 879641fc

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