Skip to content

Commit 475dce4

Browse files
karthikr-googleKangheui WonMartin Roth
committed
mb/google/utils: Add script to prepare PSP verstage for signing
This script helps to prepare the PSP verstage for signing as per guidelines from AMD BIOS Signing Key Pair and Certification Process document. BUG=None TEST=Build Skyrim BIOS image and ensure that the prepared verstage binary built as part of coreboot is ready for signing. Change-Id: I1d0997364ff4f89feed26ed1611108258845f0e9 Signed-off-by: Karthikeyan Ramasubramanian <[email protected]> Co-authored-by: Kangheui Won <[email protected]> Co-authored-by: Martin Roth <[email protected]>
1 parent 9df5910 commit 475dce4

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed
Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
#!/bin/bash
2+
# Copyright 2023 The Chromium OS Authors. All rights reserved.
3+
# Use of this source code is governed by a BSD-style license that can be
4+
# found in the LICENSE file.
5+
6+
# Abort on error.
7+
set -eu -o pipefail
8+
9+
# Extract program name for usage instructions.
10+
PROG="$(basename "$0")"
11+
12+
usage() {
13+
cat <<EOF
14+
Usage: ${PROG} <input_firmware> <token> <output_firmware>
15+
16+
For detail, reference the AMD documentation titled "OEM PSP VERSTAGE BL FW Signing
17+
Key Pair Generation and Certificate Request Process" -
18+
http://dr/corp/drive/folders/1ySJyDgbH73W1lqrhxMvM9UYl5TtJt_mw. This document
19+
is Google internal only and is under NDA. This document is loosely based on the
20+
"AMD BIOS Signing Key Pair Generation and Certificate Request Process Document
21+
(id: 56535)" from AMD devhub.
22+
23+
EOF
24+
25+
if [[ $# -ne 0 ]]; then
26+
echo "$*" >&2
27+
exit 1
28+
else
29+
exit 0
30+
fi
31+
}
32+
33+
die() {
34+
echo "$*" >&2
35+
exit 1
36+
}
37+
38+
# Check the arguments to make sure we have the correct number.
39+
if [[ $# -ne 3 ]]; then
40+
usage "Error: Incorrect number of arguments"
41+
fi
42+
43+
write_byte() {
44+
local position="$1"
45+
local value="$2"
46+
local file="$3"
47+
48+
echo -n -e "\x${value}" |
49+
dd of="${file}" bs=1 count=1 seek="${position}" conv=notrunc status=none
50+
}
51+
52+
write_dword_le() {
53+
local -i position="$1"
54+
local value
55+
value="$(printf "%08x" "$2")"
56+
local file="$3"
57+
58+
write_byte $((position)) "${value:6:2}" "${file}"
59+
write_byte $((position + 1)) "${value:4:2}" "${file}"
60+
write_byte $((position + 2)) "${value:2:2}" "${file}"
61+
write_byte $((position + 3)) "${value:0:2}" "${file}"
62+
}
63+
64+
copy_key_id() {
65+
local input_file="$1"
66+
local -i input_offset="$2"
67+
local output_file="$3"
68+
local -i output_offset="$4"
69+
local -i id_size=16
70+
71+
dd if="${input_file}" skip="${input_offset}" \
72+
of="${output_file}" seek="${output_offset}" \
73+
bs=1 count="${id_size}" conv=notrunc status=none
74+
}
75+
76+
main() {
77+
local input_firmware="$1"
78+
local amd_key="$2"
79+
local output_firmware="$3"
80+
81+
if [[ "${input_firmware}" == "${output_firmware}" ]]; then
82+
usage "Error: input and output files must not be the same"
83+
fi
84+
85+
if [[ ! -e "${input_firmware}" || ! -e "${amd_key}" ]]; then
86+
usage "Error: either input or amd_key does not exist"
87+
fi
88+
89+
local -i sig_size=256 # RSA2048 signature size
90+
local -i fw_size
91+
local -i image_size
92+
local -i header_size=256 # AMDFW header size
93+
local -i signed_fw_size
94+
local -i unsigned_fw_size
95+
local -i signed_fw_minus_header_size
96+
97+
fw_size="$(stat -c %s "${input_firmware}")"
98+
image_size="$((fw_size + sig_size))"
99+
# Search for PSP_FOOTER_DATA in psp_verstage binary. On boards with CBFS_VERIFICATION
100+
# enabled, metadata hash anchor follows PSP_FOOTER_DATA and is excluded from signing.
101+
local -a psp_footer_matches
102+
readarray -t psp_footer_matches < <(
103+
od -v --address-radix=d -t x4 --width=64 "${input_firmware}" | \
104+
awk '/[[:digit:]]+( 9{8}){16}$/ {print ($1 + 64)}'
105+
)
106+
if [[ "${#psp_footer_matches[@]}" -ne 1 ]]; then
107+
die "Multiple PSP Footer matches"
108+
fi
109+
signed_fw_size="${psp_footer_matches[0]}"
110+
if [[ "${signed_fw_size}" -le "${header_size}" ]]; then
111+
die "PSP Footer Data unexpectedly inside header!!!"
112+
fi
113+
signed_fw_minus_header_size="$((signed_fw_size - header_size))"
114+
unsigned_fw_size="$((fw_size - signed_fw_size))"
115+
116+
dd if="${input_firmware}" of="${output_firmware}" bs=1 count="${signed_fw_size}" status=none
117+
118+
# Since the header is also part of the signed binary, update the required fields before
119+
# signing. Refer to Appendix D in the AMD BIOS Signing Key Pair and Certification Process
120+
# document for what needs to be changed in the psp_verstage header.
121+
write_dword_le "0x14" "${signed_fw_minus_header_size}" "${output_firmware}"
122+
# Set the signed flag in the header
123+
write_dword_le "0x30" "1" "${output_firmware}"
124+
write_dword_le "0x6c" "${image_size}" "${output_firmware}"
125+
write_dword_le "0x70" "${unsigned_fw_size}" "${output_firmware}"
126+
copy_key_id "${amd_key}" "0x04" "${output_firmware}" "0x38"
127+
128+
echo "Finished preparing PSP Verstage for signing"
129+
}
130+
131+
main "$@"

0 commit comments

Comments
 (0)