diff options
Diffstat (limited to 'scripts')
-rwxr-xr-x | scripts/keygeneration/create_new_keys.sh | 19 | ||||
-rwxr-xr-x | scripts/keygeneration/uefi/create_new_uefi_keys.sh | 75 | ||||
-rwxr-xr-x | scripts/keygeneration/uefi/increment_db_child_key.sh | 47 | ||||
-rwxr-xr-x | scripts/keygeneration/uefi/increment_db_key.sh | 48 | ||||
-rwxr-xr-x | scripts/keygeneration/uefi/increment_kek_key.sh | 45 | ||||
-rwxr-xr-x | scripts/keygeneration/uefi/increment_pk_key.sh | 45 | ||||
-rw-r--r-- | scripts/keygeneration/uefi/uefi_common.sh | 224 |
7 files changed, 503 insertions, 0 deletions
diff --git a/scripts/keygeneration/create_new_keys.sh b/scripts/keygeneration/create_new_keys.sh index 2d7c8e31..9b2cf880 100755 --- a/scripts/keygeneration/create_new_keys.sh +++ b/scripts/keygeneration/create_new_keys.sh @@ -14,8 +14,10 @@ usage() { Usage: ${PROG} [options] Options: + --board <name> The board name (Optional. Used for UEFI keys) --devkeyblock Also generate developer firmware keyblock and data key --android Also generate android keys + --uefi Also generate UEFI keys --4k Use 4k keys instead of 8k (enables options below) --4k-root Use 4k key size for the root key --4k-recovery Use 4k key size for the recovery key @@ -35,9 +37,11 @@ EOF main() { set -e + local board="" # Flag to indicate whether we should be generating a developer keyblock flag. local dev_keyblock="false" local android_keys="false" + local uefi_keys="false" local root_key_algoid=${ROOT_KEY_ALGOID} local recovery_key_algoid=${RECOVERY_KEY_ALGOID} local recovery_kernel_algoid=${RECOVERY_KERNEL_ALGOID} @@ -47,6 +51,11 @@ main() { while [[ $# -gt 0 ]]; do case $1 in + --board) + board="$2" + shift + ;; + --devkeyblock) echo "Will also generate developer firmware keyblock and data key." dev_keyblock="true" @@ -57,6 +66,11 @@ main() { android_keys="true" ;; + --uefi) + echo "Will also generate UEFI keys." + uefi_keys="true" + ;; + --4k) root_key_algoid=${RSA4096_SHA512_ALGOID} recovery_key_algoid=${RSA4096_SHA512_ALGOID} @@ -168,6 +182,11 @@ main() { "${SCRIPT_DIR}"/create_new_android_keys.sh android fi + if [[ "${uefi_keys}" == "true" ]]; then + mkdir -p uefi + "${SCRIPT_DIR}"/uefi/create_new_uefi_keys.sh uefi "${board}" + fi + if [[ "${setperms}" == "true" ]]; then find -type f -exec chmod 400 {} + find -type d -exec chmod 500 {} + diff --git a/scripts/keygeneration/uefi/create_new_uefi_keys.sh b/scripts/keygeneration/uefi/create_new_uefi_keys.sh new file mode 100755 index 00000000..10be420e --- /dev/null +++ b/scripts/keygeneration/uefi/create_new_uefi_keys.sh @@ -0,0 +1,75 @@ +#!/bin/bash + +# Copyright 2018 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. + +# Load common constants and functions. +. "$(dirname "$0")/uefi_common.sh" + +usage() { + cat <<EOF +Usage: ${PROG} OUTPUT_DIR BOARD_NAME(optional) + +Generate key pairs for UEFI secure boot. +EOF + + if [[ $# -ne 0 ]]; then + die "$*" + else + exit 0 + fi +} + +main() { + set -e + + while [[ $# -gt 0 ]]; do + case $1 in + -h|--help) + usage + ;; + -*) + usage "Unknown option: $1" + ;; + *) + break + ;; + esac + done + + if [[ $# -lt 1 ]]; then + usage "Missing output directory" + fi + + local dir="$1" + local board_name="$2" + + check_uefi_key_dir_name "${dir}" + pushd "${dir}" > /dev/null + + if [[ ! -e "${UEFI_VERSION_FILE}" ]]; then + echo "No version file found. Creating default ${UEFI_VERSION_FILE}." + ( + printf '%s_key_version=1\n' {pk,kek,db,db_child} + ) > "${UEFI_VERSION_FILE}" + fi + + local pk_key_version kek_key_version db_key_version db_child_key_version + + # Get the key versions for normal keypairs + pk_key_version=$(get_uefi_version "pk_key_version") + kek_key_version=$(get_uefi_version "kek_key_version") + db_key_version=$(get_uefi_version "db_key_version") + db_child_key_version=$(get_uefi_version "db_child_key_version") + + make_pk_keypair "${pk_key_version}" "${board_name}" + make_kek_keypair "${kek_key_version}" "${board_name}" + make_db_keypair "${db_key_version}" "${board_name}" + make_db_child_keypair "${db_key_version}" "${db_child_key_version}" \ + "${board_name}" + + popd > /dev/null +} + +main "$@" diff --git a/scripts/keygeneration/uefi/increment_db_child_key.sh b/scripts/keygeneration/uefi/increment_db_child_key.sh new file mode 100755 index 00000000..216aacde --- /dev/null +++ b/scripts/keygeneration/uefi/increment_db_child_key.sh @@ -0,0 +1,47 @@ +#!/bin/bash +# Copyright 2018 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. + +# Script to increment UEFI DB child key. + +# Load common constants and variables. +. "$(dirname "$0")/uefi_common.sh" + +# Abort on errors. +set -e + +if [ $# -lt 1 ]; then + cat <<EOF + Usage: $0 <keyset directory> [board name] + + Increments the UEFI DB child key in the specified keyset. +EOF + exit 1 +fi + +KEY_DIR="$1" +BOARD_NAME="$2" # Optional. + +main() { + check_uefi_key_dir_name "${KEY_DIR}" + + load_current_uefi_key_versions "${KEY_DIR}" + new_db_child_key_ver=$(increment_uefi_version "${KEY_DIR}" \ + "db_child_key_version") + + cd "${KEY_DIR}" + backup_existing_db_child_keypair "${CURR_DB_CHILD_KEY_VER}" + + cat <<EOF +Generating new UEFI DB child key version. + +New DB child key version: ${new_db_child_key_ver}. +EOF + make_db_child_keypair "${CURR_DB_KEY_VER}" "${new_db_child_key_ver}" \ + "${BOARD_NAME}" + write_updated_uefi_version_file "${CURR_PK_KEY_VER}" "${CURR_KEK_KEY_VER}" \ + "${CURR_DB_KEY_VER}" "${new_db_child_key_ver}" +} + +main "$@" diff --git a/scripts/keygeneration/uefi/increment_db_key.sh b/scripts/keygeneration/uefi/increment_db_key.sh new file mode 100755 index 00000000..1e48f4f4 --- /dev/null +++ b/scripts/keygeneration/uefi/increment_db_key.sh @@ -0,0 +1,48 @@ +#!/bin/bash +# Copyright 2018 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. + +# Script to increment UEFI DB key. + +# Load common constants and variables. +. "$(dirname "$0")/uefi_common.sh" + +# Abort on errors. +set -e + +if [ $# -lt 1 ]; then + cat <<EOF + Usage: $0 <keyset directory> [board name] + + Increments the UEFI DB key in the specified keyset. +EOF + exit 1 +fi + +KEY_DIR="$1" +BOARD_NAME="$2" # Optional. + +main() { + check_uefi_key_dir_name "${KEY_DIR}" + + load_current_uefi_key_versions "${KEY_DIR}" + new_db_key_ver=$(increment_uefi_version "${KEY_DIR}" "db_key_version") + new_db_child_key_ver=1 + + cd "${KEY_DIR}" + backup_existing_db_keypair_and_children "${CURR_DB_KEY_VER}" + + cat <<EOF +Generating new UEFI DB key version. + +New DB key version: ${new_db_key_ver}. +EOF + make_db_keypair "${new_db_key_ver}" "${BOARD_NAME}" + make_db_child_keypair "${new_db_key_ver}" "${new_db_child_key_ver}" \ + "${BOARD_NAME}" + write_updated_uefi_version_file "${CURR_PK_KEY_VER}" "${CURR_KEK_KEY_VER}" \ + "${new_db_key_ver}" "${new_db_child_key_ver}" +} + +main "$@" diff --git a/scripts/keygeneration/uefi/increment_kek_key.sh b/scripts/keygeneration/uefi/increment_kek_key.sh new file mode 100755 index 00000000..3b9879ad --- /dev/null +++ b/scripts/keygeneration/uefi/increment_kek_key.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Copyright 2018 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. + +# Script to increment UEFI Key Exchange Key (KEK). + +# Load common constants and variables. +. "$(dirname "$0")/uefi_common.sh" + +# Abort on errors. +set -e + +if [ $# -lt 1 ]; then + cat <<EOF + Usage: $0 <keyset directory> [board name] + + Increments the UEFI Key Exchange Key (KEK) in the specified keyset. +EOF + exit 1 +fi + +KEY_DIR="$1" +BOARD_NAME="$2" # Optional. + +main() { + check_uefi_key_dir_name "${KEY_DIR}" + + load_current_uefi_key_versions "${KEY_DIR}" + new_kek_key_ver=$(increment_uefi_version "${KEY_DIR}" "kek_key_version") + + cd "${KEY_DIR}" + backup_existing_kek_keypair "${CURR_KEK_KEY_VER}" + + cat <<EOF +Generating new UEFI Key Exchange Key (KEK) version. + +New Key Exchange Key version: ${new_kek_key_ver}. +EOF + make_kek_keypair "${new_kek_key_ver}" "${BOARD_NAME}" + write_updated_uefi_version_file "${CURR_PK_KEY_VER}" "${new_kek_key_ver}" \ + "${CURR_DB_KEY_VER}" "${CURR_DB_CHILD_KEY_VER}" +} + +main "$@" diff --git a/scripts/keygeneration/uefi/increment_pk_key.sh b/scripts/keygeneration/uefi/increment_pk_key.sh new file mode 100755 index 00000000..a2940ef0 --- /dev/null +++ b/scripts/keygeneration/uefi/increment_pk_key.sh @@ -0,0 +1,45 @@ +#!/bin/bash +# Copyright 2018 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. + +# Script to increment UEFI Platform Key (PK). + +# Load common constants and variables. +. "$(dirname "$0")/uefi_common.sh" + +# Abort on errors. +set -e + +if [ $# -lt 1 ]; then + cat <<EOF + Usage: $0 <keyset directory> [board name] + + Increments the UEFI Platform Key (PK) in the specified keyset. +EOF + exit 1 +fi + +KEY_DIR="$1" +BOARD_NAME="$2" # Optional. + +main() { + check_uefi_key_dir_name "${KEY_DIR}" + + load_current_uefi_key_versions "${KEY_DIR}" + new_pk_key_ver=$(increment_uefi_version "${KEY_DIR}" "pk_key_version") + + cd "${KEY_DIR}" + backup_existing_pk_keypair "${CURR_PK_KEY_VER}" + + cat <<EOF +Generating new UEFI Platform Key (PK) version. + +New Platform Key version: ${new_pk_key_ver}. +EOF + make_pk_keypair "${new_pk_key_ver}" "${BOARD_NAME}" + write_updated_uefi_version_file "${new_pk_key_ver}" "${CURR_KEK_KEY_VER}" \ + "${CURR_DB_KEY_VER}" "${CURR_DB_CHILD_KEY_VER}" +} + +main "$@" diff --git a/scripts/keygeneration/uefi/uefi_common.sh b/scripts/keygeneration/uefi/uefi_common.sh new file mode 100644 index 00000000..5920a14a --- /dev/null +++ b/scripts/keygeneration/uefi/uefi_common.sh @@ -0,0 +1,224 @@ +#!/bin/bash +# Copyright 2018 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. + +# Common UEFI key generation functions. + +. "$(dirname "$0")/../common.sh" + +check_uefi_key_dir_name() { + local key_dir="$1" + local key_dir_fullpath="$(readlink -f "${key_dir}")" + local key_dir_basename="$(basename "${key_dir_fullpath}")" + if [[ "${key_dir_basename}" != "uefi" ]]; then + die "Key directory base name is not \"uefi\"" + fi +} + +# File to read current versions from. +UEFI_VERSION_FILE="uefi_key.versions" + +# ARGS: <VERSION_TYPE> [UEFI_VERSION_FILE] +get_uefi_version() { + local key="$1" + local file="${2:-${UEFI_VERSION_FILE}}" + awk -F= -vkey="${key}" '$1 == key { print $NF }' "${file}" +} + +# Loads the current versions, prints them to stdout, and sets the global version +# variables: CURR_PK_KEY_VER CURR_KEK_KEY_VER CURR_DB_KEY_VER +# CURR_DB_CHILD_KEY_VER +load_current_uefi_key_versions() { + local key_dir="$1" + local UEFI_VERSION_FILE="${key_dir}/${UEFI_VERSION_FILE}" + if [[ ! -f "${UEFI_VERSION_FILE}" ]]; then + return 1 + fi + CURR_PK_KEY_VER=$(get_uefi_version "pk_key_version") + CURR_KEK_KEY_VER=$(get_uefi_version "kek_key_version") + CURR_DB_KEY_VER=$(get_uefi_version "db_key_version") + CURR_DB_CHILD_KEY_VER=$(get_uefi_version "db_child_key_version") + + cat <<EOF +Current UEFI Platform Key (PK) version: ${CURR_PK_KEY_VER} +Current UEFI Key Exchange Key (KEK) version: ${CURR_KEK_KEY_VER} +Current UEFI DB key version: ${CURR_DB_KEY_VER} +Current UEFI DB child key version: ${CURR_DB_CHILD_KEY_VER} +EOF +} + +_CHROMIUM_OS_SUBJECT=\ +'/C=US/ST=California/L=Mountain View/O=Google LLC./OU=Chromium OS' + +_get_subj() { + local title="$1" + local version="$2" + local board_name="$3" # Optional. + + if [[ ! -z "${board_name}" ]]; then + board_name="${board_name} " + fi + echo "${_CHROMIUM_OS_SUBJECT}/CN=${board_name}${title} v${version}" +} + +# Generate a pair of a private key and a self-signed cert at the current +# directory. Generated files are +# $1/$1.rsa: The private key +# $1/$1.pem: The self-signed cert in PEM format +_make_self_signed_pair() { + local key_name="$1" + local subj="$2" + + mkdir -p "${key_name}" + pushd "${key_name}" > /dev/null + openssl req -new -x509 -nodes -newkey rsa:2048 -sha256 \ + -keyout "${key_name}.rsa" -out "${key_name}.pem" \ + -subj "${subj}" -days 73000 + popd > /dev/null +} + +# Generate a pair of a private key and a cert signed by the given CA. +# "$1" (the first argument) is the CA file name without extension. +# The results are signed by "$1/$1.{rsa,pem}", and are generated in +# "$1/$1.children" directory under the current directory. Generated files are +# $1/$1.children/$2.rsa: The private key +# $1/$1.children/$2.csr: The Certificate Signing Request +# $1/$1.children/$2.pem: The certificate signed by "$1.{rsa,pem}" +_make_child_pair() { + local ca_name="$1" # Base filename without extension. + local child_key_name="$2" + local subj="$3" + + mkdir -p "${ca_name}/${ca_name}.children" + pushd "${ca_name}/${ca_name}.children" > /dev/null + openssl req -new -nodes -newkey rsa:2048 -sha256 \ + -keyout "${child_key_name}.rsa" -out "${child_key_name}.csr" \ + -subj "${subj}" -days 73000 + openssl x509 -req -sha256 -CA "../${ca_name}.pem" -CAkey "../${ca_name}.rsa" \ + -CAcreateserial -in "${child_key_name}.csr" \ + -out "${child_key_name}.pem" -days 73000 + popd > /dev/null +} + +make_pk_keypair() { + local version="$1" + local board_name="$2" # Optional. + _make_self_signed_pair pk \ + "$(_get_subj "UEFI Platform Key" "${version}" "${board_name}")" +} + +make_kek_keypair() { + local version="$1" + local board_name="$2" # Optional. + _make_self_signed_pair kek \ + "$(_get_subj "UEFI Key Exchange Key" "${version}" "${board_name}")" +} + +make_db_keypair() { + local version="$1" + local board_name="$2" # Optional. + _make_self_signed_pair db \ + "$(_get_subj "UEFI DB Key" "${version}" "${board_name}")" +} + +make_db_child_keypair() { + local db_key_version="$1" + local child_key_version="$2" + local board_name="$3" # Optional. + _make_child_pair db db_child \ + "$(_get_subj "UEFI DB Child Key" \ + "${db_key_version}.${child_key_version}" "${board_name}")" +} + +_backup_existing_self_signed_pair() { + local key_name="$1" + local version="$2" + pushd "${key_name}" > /dev/null + mv --no-clobber "${key_name}".{rsa,"v${version}.rsa"} + mv --no-clobber "${key_name}".{pem,"v${version}.pem"} + popd > /dev/null +} + +_backup_existing_self_signed_pair_and_children() { + local key_name="$1" + local version="$2" + _backup_existing_self_signed_pair "${key_name}" "${version}" + pushd "${key_name}" > /dev/null + mv --no-clobber "${key_name}".{children,"v${version}.children"} + popd > /dev/null +} + +_backup_existing_child_pair() { + local ca_name="$1" + local child_key_name="$2" + local child_key_version="$3" + pushd "${ca_name}/${ca_name}.children" > /dev/null + mv --no-clobber "${child_key_name}".{rsa,"v${child_key_version}.rsa"} + mv --no-clobber "${child_key_name}".{csr,"v${child_key_version}.csr"} + mv --no-clobber "${child_key_name}".{pem,"v${child_key_version}.pem"} + popd +} + +# Make backup of existing pk keypair. +# Backup format: pk.v<pk key version>.{rsa,pem} +backup_existing_pk_keypair() { + local pk_key_version="$1" + _backup_existing_self_signed_pair pk "${pk_key_version}" +} + +# Make backup of existing kek keypair. +# Backup format: kek.v<kek key version>.{rsa,pem} +backup_existing_kek_keypair() { + local kek_key_version="$1" + _backup_existing_self_signed_pair kek "${kek_key_version}" +} + +# Make backup of existing db keypair and children. +# Backup format: +# for db keypair: db.v<db key version>.{rsa,pem} +# for child keypair: db.v<db key version>.childern/child*.{rsa,csr,pem} +backup_existing_db_keypair_and_children() { + local db_key_version="$1" + _backup_existing_self_signed_pair_and_children db "${db_key_version}" +} + +# Make backup of existing db child keypair. +# Backup format: db.children/child.v<db child key version>.{rsa,csr,pem} +backup_existing_db_child_keypair() { + local db_child_key_version="$1" + _backup_existing_child_pair db db_child "${db_child_key_version}" +} + +# Write new key version file with the updated key versions. +# Args: PK_KEY_VERSION KEK_KEY_VERSION DB_KEY_VERSION DB_CHILD_KEY_VERSION +write_updated_uefi_version_file() { + local pk_key_version="$1" + local kek_key_version="$2" + local db_key_version="$3" + local db_child_key_version="$4" + + cat > "${UEFI_VERSION_FILE}" <<EOF +pk_key_version=${pk_key_version} +kek_key_version=${kek_key_version} +db_key_version=${db_key_version} +db_child_key_version=${db_child_key_version} +EOF +} + +# Returns the incremented version number of the passed in key from the version +# file. The options are "pk_key_version", "kek_key_version", "db_key_version", +# or "db_child_key_version". +# ARGS: KEY_DIR <key_name> +increment_uefi_version() { + local key_dir="$1" + local UEFI_VERSION_FILE="${key_dir}/${UEFI_VERSION_FILE}" + local old_version=$(get_uefi_version "$2") + local new_version=$(( old_version + 1 )) + + if [[ ${new_version} -gt 0xffff ]]; then + echo "Version overflow!" >&2 + return 1 + fi + echo ${new_version} +} |