summaryrefslogtreecommitdiff
path: root/scripts/image_signing/sign_psp_verstagebl_fw.sh
blob: 9d7fd87fdb68ad22956e6e7dcf9fe7fadb4452ed (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#!/bin/bash
# Copyright 2020 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# Abort on error.
set -e -o pipefail

# Determine script directory.
SCRIPT_DIR=$(dirname "$0")

# Load common constants and variables.
. "${SCRIPT_DIR}/common.sh"

usage() {
  cat <<EOF
Usage: ${PROG} <input_firmware> <key_dir> <output_firmware>

Signs <input_firmware> with keys in <key_dir>. Outputs signed firmware to
<output_firmware>.  The <input_firmware> and <output_firmware> paths should not
be the same.

For detail, reference the AMD documentation titled "OEM PSP VERSTAGE
BL FW Signing Key Pair Generation and Certificate Request Process"
http://dr/corp/drive/folders/1ySJyDgbH73W1lqrhxMvM9UYl5TtJt_mw

EOF

  if [[ $# -ne 0 ]]; then
    echo "$*" >&2
    exit 1
  else
    exit 0
  fi
}

# Check the arguments to make sure we have the correct number.
if [[ $# -lt 3 ]]; then
  usage "Error: Too few arguments"
fi
if [[ $# -gt 3 ]]; then
  usage "Error: Too many arguments"
fi

read_byte() {
  local position="$1"
  local file="$2"

  dd if="${file}" bs=1 count=1 skip="$((16#${position}))" status=none |
    hexdump -e '/1 "%X"'
}

write_byte() {
  local position="$1"
  local value="$2"
  local file="$3"

  printf "\x${value}" |
    dd of="${file}" bs=1 count=1 seek="${position}" conv=notrunc status=none
}

read_dword_le() {
  local position
  position=$(printf -- "%d" "$1")
  local file="$2"
  read_byte "${position}" "${file}"
  read_byte $((position + 1)) "${file}"
  read_byte $((position + 2)) "${file}"
  read_byte $((position + 3))
}

write_dword_le() {
  local position
  position=$(printf -- "%d" "$1")
  local value
  value=$(printf -- "%08x" "$2")
  local file="$3"

  write_byte "${position}" "${value:6:2}" "$file"
  write_byte $((position + 1)) "${value:4:2}" "$file"
  write_byte $((position + 2)) "${value:2:2}" "$file"
  write_byte $((position + 3)) "${value:0:2}" "$file"
}

filesize() {
  local file="$1"
  stat -c %s -- "${file}"
}

copy_key_id() {
  local input_file="$1"
  local input_offset
  input_offset=$(printf -- "%d" "$2")
  local output_file="$3"
  local output_offset
  output_offset=$(printf -- "%d" "$4")

  local id_size=16

  dd if="${input_file}" skip="${input_offset}" \
    of="${output_file}" seek="${output_offset}" \
    bs=1 count="${id_size}" conv=notrunc status=none
}

KEYNAME=psp_verstagebl_fw_signing

main() {
  local input_firmware="$1"
  local key_dir="$2"
  local output_firmware="$3"

  if [[ "${input_firmware}" == "${output_firmware}" ]]; then
    usage "Error: input and output files must not be the same"
  fi

  local amd_key="${key_dir}/${KEYNAME}.stkn"
  local hashtype
  local sig_size
  local temp_sig
  local temp_fw
  local fw_size
  local image_size

  temp_sig=$(make_temp_file)
  temp_fw=$(make_temp_file)

  # TODO: Differentiate sizes for Picasso vs later chips
  hashtype="-sha256"
  sig_size=256

  fw_size="$(($(filesize "${input_firmware}")))"
  fw_minus_header_size="$((fw_size - 256))"
  image_size="$((fw_size + sig_size))"

  cp "${input_firmware}" "${temp_fw}"

  # Refer to Appendix D in the AMD BIOS Signing Key Pair and Certification
  # Process document for what needs to be changed in the psp_verstage header.
  write_dword_le "0x14" "${fw_minus_header_size}" "${temp_fw}"
  write_dword_le "0x30" "1" "${temp_fw}"
  write_dword_le "0x6c" "${image_size}" "${temp_fw}"

  # TODO: Need the PSP verstage signing token from AMD to verify.
  copy_key_id "${amd_key}" "0x04" "${temp_fw}" "0x38"

  local cmd=(
    openssl dgst
    "${hashtype}"
    -sign "${key_dir}/${KEYNAME}.pem"
    -sigopt rsa_padding_mode:pss
    -sigopt rsa_pss_saltlen:-1
    -out "${temp_sig}"
  )

  "${cmd[@]}" "${temp_fw}"

  cat "${temp_fw}" "${temp_sig}" >"${output_firmware}"

  echo "Complete"
}

main "$@"