blob: aa955dd8f0b9904dc5e32c3801869bdd48374bf2 [file] [log] [blame]
Gaurav Shah57468452011-03-02 14:50:46 -08001#!/bin/bash
2# Copyright (c) 2011 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# Common key generation functions.
7
8SCRIPT_DIR="$(dirname "$0")"
9
10# 0 = (RSA1024 SHA1)
11# 1 = (RSA1024 SHA256)
12# 2 = (RSA1024 SHA512)
13# 3 = (RSA2048 SHA1)
14# 4 = (RSA2048 SHA256)
15# 5 = (RSA2048 SHA512)
16# 6 = (RSA4096 SHA1)
17# 7 = (RSA4096 SHA256)
18# 8 = (RSA4096 SHA512)
19# 9 = (RSA8192 SHA1)
20# 10 = (RSA8192 SHA256)
21# 11 = (RSA8192 SHA512)
22function alg_to_keylen {
23 echo $(( 1 << (10 + ($1 / 3)) ))
24}
25
Bill Richardson2448d3b2012-05-03 08:40:44 -070026# Default algorithms.
27EC_ROOT_KEY_ALGOID=7
28EC_DATAKEY_ALGOID=7
29
Gaurav Shah41f444a2011-04-12 17:05:37 -070030ROOT_KEY_ALGOID=11
31RECOVERY_KEY_ALGOID=11
32
33FIRMWARE_DATAKEY_ALGOID=7
34DEV_FIRMWARE_DATAKEY_ALGOID=7
35
36RECOVERY_KERNEL_ALGOID=11
37INSTALLER_KERNEL_ALGOID=11
38KERNEL_SUBKEY_ALGOID=7
39KERNEL_DATAKEY_ALGOID=4
40
41# Keyblock modes determine which boot modes a signing key is valid for use
42# in verification.
Bill Richardson2448d3b2012-05-03 08:40:44 -070043EC_KEYBLOCK_MODE=7 # Only allow RW EC firmware in non-recovery.
44FIRMWARE_KEYBLOCK_MODE=7 # Only allow RW firmware in non-recovery.
Gaurav Shah41f444a2011-04-12 17:05:37 -070045DEV_FIRMWARE_KEYBLOCK_MODE=6 # Only allow in dev mode.
Bill Richardson2448d3b2012-05-03 08:40:44 -070046RECOVERY_KERNEL_KEYBLOCK_MODE=11 # Only in recovery mode.
Gaurav Shah41f444a2011-04-12 17:05:37 -070047KERNEL_KEYBLOCK_MODE=7 # Only allow in non-recovery.
48INSTALLER_KERNEL_KEYBLOCK_MODE=10 # Only allow in Dev + Recovery.
49
Gaurav Shah57468452011-03-02 14:50:46 -080050# Emit .vbpubk and .vbprivk using given basename and algorithm
51# NOTE: This function also appears in ../../utility/dev_make_keypair. Making
52# the two implementations the same would require some common.sh, which is more
53# likely to cause problems than just keeping an eye out for any differences. If
54# you feel the need to change this file, check the history of that other file
55# to see what may need updating here too.
56function make_pair {
57 local base=$1
58 local alg=$2
Gaurav Shah41f444a2011-04-12 17:05:37 -070059 local key_version=${3:-1}
Gaurav Shah57468452011-03-02 14:50:46 -080060 local len=$(alg_to_keylen $alg)
61
Gaurav Shah41f444a2011-04-12 17:05:37 -070062 echo "creating $base keypair (version = $key_version)..."
Gaurav Shah57468452011-03-02 14:50:46 -080063
64 # make the RSA keypair
65 openssl genrsa -F4 -out "${base}_${len}.pem" $len
66 # create a self-signed certificate
67 openssl req -batch -new -x509 -key "${base}_${len}.pem" \
68 -out "${base}_${len}.crt"
69 # generate pre-processed RSA public key
70 dumpRSAPublicKey -cert "${base}_${len}.crt" > "${base}_${len}.keyb"
71
72 # wrap the public key
73 vbutil_key \
74 --pack "${base}.vbpubk" \
75 --key "${base}_${len}.keyb" \
Gaurav Shah41f444a2011-04-12 17:05:37 -070076 --version "${key_version}" \
Gaurav Shah57468452011-03-02 14:50:46 -080077 --algorithm $alg
78
79 # wrap the private key
80 vbutil_key \
81 --pack "${base}.vbprivk" \
82 --key "${base}_${len}.pem" \
83 --algorithm $alg
84
85 # remove intermediate files
86 rm -f "${base}_${len}.pem" "${base}_${len}.crt" "${base}_${len}.keyb"
87}
88
89
90# Emit a .keyblock containing flags and a public key, signed by a private key
91# flags are the bitwise OR of these (passed in decimal, though)
92# 0x01 Developer switch off
93# 0x02 Developer switch on
94# 0x04 Not recovery mode
95# 0x08 Recovery mode
96function make_keyblock {
97 local base=$1
98 local flags=$2
99 local pubkey=$3
100 local signkey=$4
101
102 echo "creating $base keyblock..."
103
104 # create it
105 vbutil_keyblock \
106 --pack "${base}.keyblock" \
107 --flags $flags \
108 --datapubkey "${pubkey}.vbpubk" \
109 --signprivate "${signkey}.vbprivk"
110
111 # verify it
112 vbutil_keyblock \
113 --unpack "${base}.keyblock" \
114 --signpubkey "${signkey}.vbpubk"
115}
116
Kris Rambish40d86512012-09-06 15:58:37 -0700117# File to read current versions from.
118VERSION_FILE="key.versions"
Gaurav Shah57468452011-03-02 14:50:46 -0800119
Mike Frysinger51ca0b82014-06-16 01:12:32 -0400120# ARGS: <VERSION_TYPE> [VERSION_FILE]
Kris Rambish40d86512012-09-06 15:58:37 -0700121get_version() {
Mike Frysinger51ca0b82014-06-16 01:12:32 -0400122 awk -F= '/^'$1'\>/ { print $NF }' "${2:-${VERSION_FILE}}"
Kris Rambish40d86512012-09-06 15:58:37 -0700123}
124
125# Loads the current versions prints them to stdout and sets the global version
126# variables: CURR_FIRMKEY_VER CURR_FIRM_VER CURR_KERNKEY_VER CURR_KERN_VER
127load_current_versions() {
Mike Frysinger8b42ac82012-10-17 01:05:50 -0400128 local key_dir=$1
129 local VERSION_FILE="${key_dir}/${VERSION_FILE}"
Kris Rambish40d86512012-09-06 15:58:37 -0700130 if [[ ! -f ${VERSION_FILE} ]]; then
131 return 1
132 fi
133 CURR_FIRMKEY_VER=$(get_version "firmware_key_version")
134 # Firmware version is the kernel subkey version.
135 CURR_FIRM_VER=$(get_version "firmware_version")
136 # Kernel data key version is the kernel key version.
137 CURR_KERNKEY_VER=$(get_version "kernel_key_version")
138 CURR_KERN_VER=$(get_version "kernel_version")
139
140 cat <<EOF
141Current Firmware key version: ${CURR_FIRMKEY_VER}
142Current Firmware version: ${CURR_FIRM_VER}
143Current Kernel key version: ${CURR_KERNKEY_VER}
144Current Kernel version: ${CURR_KERN_VER}
145EOF
146}
147
148# Make backups of existing kernel subkeys and keyblocks that will be revved.
149# Backup format:
150# for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
151# Args: SUBKEY_VERSION DATAKEY_VERSION
152backup_existing_kernel_keyblock() {
153 if [[ ! -e kernel.keyblock ]]; then
154 return
155 fi
156 mv --no-clobber kernel.{keyblock,"v$2.v$1.keyblock"}
157}
158
159# Make backups of existing kernel subkeys and keyblocks that will be revved.
160# Backup format:
161# for keys: <key_name>.v<version>.vb{pub|priv}k
162# for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
163# Args: SUBKEY_VERSION DATAKEY_VERSION
164backup_existing_kernel_subkeys() {
165 local subkey_ver=$1
166 local datakey_ver=$2
167 # --no-clobber to prevent accidentally overwriting existing
168 # backups.
169 mv --no-clobber kernel_subkey.{vbprivk,"v${subkey_ver}.vbprivk"}
170 mv --no-clobber kernel_subkey.{vbpubk,"v${subkey_ver}.vbpubk"}
171 backup_existing_kernel_keyblock ${subkey_ver} ${datakey_ver}
172}
173
174# Make backups of existing kernel data keys and keyblocks that will be revved.
175# Backup format:
176# for keys: <key_name>.v<version>.vb{pub|priv}k
177# for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
178# Args: SUBKEY_VERSION DATAKEY_VERSION
179backup_existing_kernel_data_keys() {
180 local subkey_ver=$1
181 local datakey_ver=$2
182 # --no-clobber to prevent accidentally overwriting existing
183 # backups.
184 mv --no-clobber kernel_data_key.{vbprivk,"v${datakey_ver}.vbprivk"}
185 mv --no-clobber kernel_data_key.{vbpubk,"v${datakey_ver}.vbpubk"}
186 backup_existing_kernel_keyblock ${subkey_ver} ${datakey_ver}
187}
188
189# Make backups of existing firmware keys and keyblocks that will be revved.
190# Backup format:
191# for keys: <key_name>.v<version>.vb{pub|priv}k
192# for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
193# Args: SUBKEY_VERSION DATAKEY_VERSION
194backup_existing_firmware_keys() {
195 local subkey_ver=$1
196 local datakey_ver=$2
197 mv --no-clobber firmware_data_key.{vbprivk,"v${subkey_ver}.vbprivk"}
198 mv --no-clobber firmware_data_key.{vbpubk,"v${subkey_ver}.vbpubk"}
199 mv --no-clobber firmware.{keyblock,"v${datakey_ver}.v${subkey_ver}.keyblock"}
200}
201
202
203# Write new key version file with the updated key versions.
204# Args: FIRMWARE_KEY_VERSION FIRMWARE_VERSION KERNEL_KEY_VERSION
205# KERNEL_VERSION
206write_updated_version_file() {
207 local firmware_key_version=$1
208 local firmware_version=$2
209 local kernel_key_version=$3
210 local kernel_version=$4
211
212 cat > ${VERSION_FILE} <<EOF
213firmware_key_version=${firmware_key_version}
214firmware_version=${firmware_version}
215kernel_key_version=${kernel_key_version}
216kernel_version=${kernel_version}
217EOF
218}
219
220# Returns the incremented version number of the passed in key from the version
221# file. The options are "firmware_key_version", "firmware_version",
222# "kernel_key_version", or "kernel_version".
223# ARGS: KEY_DIR <key_name>
224increment_version() {
225 local key_dir=$1
226 local VERSION_FILE="${key_dir}/${VERSION_FILE}"
227 local old_version=$(get_version $2)
228 local new_version=$(( ${old_version} + 1 ))
229
230 if [[ ${new_version} -gt 0xffff ]]; then
231 echo "Version overflow!" >&2
232 return 1
233 fi
234 echo ${new_version}
235}