blob: b7725add7db925b09f81f28d0b99d0a4bc8cc2d8 [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
Kris Rambish40d86512012-09-06 15:58:37 -0700120# ARGS: <VERSION_TYPE>
121get_version() {
122 awk -F= '/^'$1'\>/ { print $NF }' ${2:-${VERSION_FILE}}
123}
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() {
128 if [[ ! -f ${VERSION_FILE} ]]; then
129 return 1
130 fi
131 CURR_FIRMKEY_VER=$(get_version "firmware_key_version")
132 # Firmware version is the kernel subkey version.
133 CURR_FIRM_VER=$(get_version "firmware_version")
134 # Kernel data key version is the kernel key version.
135 CURR_KERNKEY_VER=$(get_version "kernel_key_version")
136 CURR_KERN_VER=$(get_version "kernel_version")
137
138 cat <<EOF
139Current Firmware key version: ${CURR_FIRMKEY_VER}
140Current Firmware version: ${CURR_FIRM_VER}
141Current Kernel key version: ${CURR_KERNKEY_VER}
142Current Kernel version: ${CURR_KERN_VER}
143EOF
144}
145
146# Make backups of existing kernel subkeys and keyblocks that will be revved.
147# Backup format:
148# for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
149# Args: SUBKEY_VERSION DATAKEY_VERSION
150backup_existing_kernel_keyblock() {
151 if [[ ! -e kernel.keyblock ]]; then
152 return
153 fi
154 mv --no-clobber kernel.{keyblock,"v$2.v$1.keyblock"}
155}
156
157# Make backups of existing kernel subkeys and keyblocks that will be revved.
158# Backup format:
159# for keys: <key_name>.v<version>.vb{pub|priv}k
160# for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
161# Args: SUBKEY_VERSION DATAKEY_VERSION
162backup_existing_kernel_subkeys() {
163 local subkey_ver=$1
164 local datakey_ver=$2
165 # --no-clobber to prevent accidentally overwriting existing
166 # backups.
167 mv --no-clobber kernel_subkey.{vbprivk,"v${subkey_ver}.vbprivk"}
168 mv --no-clobber kernel_subkey.{vbpubk,"v${subkey_ver}.vbpubk"}
169 backup_existing_kernel_keyblock ${subkey_ver} ${datakey_ver}
170}
171
172# Make backups of existing kernel data keys and keyblocks that will be revved.
173# Backup format:
174# for keys: <key_name>.v<version>.vb{pub|priv}k
175# for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
176# Args: SUBKEY_VERSION DATAKEY_VERSION
177backup_existing_kernel_data_keys() {
178 local subkey_ver=$1
179 local datakey_ver=$2
180 # --no-clobber to prevent accidentally overwriting existing
181 # backups.
182 mv --no-clobber kernel_data_key.{vbprivk,"v${datakey_ver}.vbprivk"}
183 mv --no-clobber kernel_data_key.{vbpubk,"v${datakey_ver}.vbpubk"}
184 backup_existing_kernel_keyblock ${subkey_ver} ${datakey_ver}
185}
186
187# Make backups of existing firmware keys and keyblocks that will be revved.
188# Backup format:
189# for keys: <key_name>.v<version>.vb{pub|priv}k
190# for keyblocks: <keyblock_name>.v<datakey version>.v<subkey version>.keyblock
191# Args: SUBKEY_VERSION DATAKEY_VERSION
192backup_existing_firmware_keys() {
193 local subkey_ver=$1
194 local datakey_ver=$2
195 mv --no-clobber firmware_data_key.{vbprivk,"v${subkey_ver}.vbprivk"}
196 mv --no-clobber firmware_data_key.{vbpubk,"v${subkey_ver}.vbpubk"}
197 mv --no-clobber firmware.{keyblock,"v${datakey_ver}.v${subkey_ver}.keyblock"}
198}
199
200
201# Write new key version file with the updated key versions.
202# Args: FIRMWARE_KEY_VERSION FIRMWARE_VERSION KERNEL_KEY_VERSION
203# KERNEL_VERSION
204write_updated_version_file() {
205 local firmware_key_version=$1
206 local firmware_version=$2
207 local kernel_key_version=$3
208 local kernel_version=$4
209
210 cat > ${VERSION_FILE} <<EOF
211firmware_key_version=${firmware_key_version}
212firmware_version=${firmware_version}
213kernel_key_version=${kernel_key_version}
214kernel_version=${kernel_version}
215EOF
216}
217
218# Returns the incremented version number of the passed in key from the version
219# file. The options are "firmware_key_version", "firmware_version",
220# "kernel_key_version", or "kernel_version".
221# ARGS: KEY_DIR <key_name>
222increment_version() {
223 local key_dir=$1
224 local VERSION_FILE="${key_dir}/${VERSION_FILE}"
225 local old_version=$(get_version $2)
226 local new_version=$(( ${old_version} + 1 ))
227
228 if [[ ${new_version} -gt 0xffff ]]; then
229 echo "Version overflow!" >&2
230 return 1
231 fi
232 echo ${new_version}
233}