mirror of
https://github.com/flatcar/scripts.git
synced 2025-08-06 04:26:59 +02:00
163 lines
4.9 KiB
Bash
Executable File
163 lines
4.9 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
|
|
# Copyright (c) 2014 CoreOS, Inc. All rights reserved.
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
|
|
# usage: ./core_generate_update_payload --image coreos_production_update.bin \
|
|
# --output update.gz \
|
|
# --private_keys update.key.pem:update2.key.pem
|
|
# --public_keys update.pub.pem:update2.pub.pem
|
|
|
|
SCRIPT_ROOT=$(dirname $(readlink -f "$0"))
|
|
# We have to simple-mindedly set GCLIENT_ROOT in case we're running from
|
|
# au-generator.zip because common.sh will fail while auto-detect it.
|
|
export GCLIENT_ROOT=$(readlink -f "${SCRIPT_ROOT}/../../")
|
|
. "${SCRIPT_ROOT}/common.sh" || exit 1
|
|
|
|
DEFINE_string image "" "The filesystem image of /usr"
|
|
DEFINE_string kernel "" "The kernel image"
|
|
DEFINE_string output "" "Output file"
|
|
DEFINE_string private_keys "" "Path or pkcs11 URI for private keys."
|
|
DEFINE_string public_keys "" "Path to public keys in .pem format."
|
|
DEFINE_string keys_separator ":" "Separator for the above keys"
|
|
|
|
# Parse command line
|
|
FLAGS "$@" || exit 1
|
|
eval set -- "${FLAGS_ARGV}"
|
|
|
|
set -e
|
|
|
|
cleanup() {
|
|
rm -f padding
|
|
rm -f padding-pkcs11
|
|
rm -f update
|
|
rm -f update.hash
|
|
rm -f update.padhash
|
|
rm -f update.pkcs11-padhash
|
|
rm -f update.signed
|
|
rm -f update.sig.*
|
|
}
|
|
|
|
trap cleanup INT TERM EXIT
|
|
|
|
echo "=== Creating signable update payload... ==="
|
|
delta_generator \
|
|
-new_image "$FLAGS_image" \
|
|
-new_kernel "$FLAGS_kernel" \
|
|
-out_file update
|
|
|
|
# The separator is configurable for backwards compatibility with old `sign.sh` scripts.
|
|
IFS="${FLAGS_keys_separator}" read -a private_keys <<< "$FLAGS_private_keys"
|
|
IFS="${FLAGS_keys_separator}" read -a public_keys <<< "$FLAGS_public_keys"
|
|
|
|
if [ ${#private_keys[@]} -ne ${#public_keys[@]} ]; then
|
|
echo "mismatch in count of private keys and public keys"
|
|
exit 1
|
|
fi
|
|
|
|
i=0
|
|
signature_sizes=""
|
|
for key in "${private_keys[@]}"; do
|
|
signature_sizes=${signature_sizes}:256
|
|
let "i += 1"
|
|
done
|
|
signature_sizes="${signature_sizes:1:${#signature_sizes}}"
|
|
|
|
delta_generator \
|
|
--signature_size ${signature_sizes} \
|
|
--in_file update \
|
|
--out_hash_file update.hash
|
|
|
|
# padding for openssl rsautl -pkcs (smartcard keys)
|
|
#
|
|
# The following is an ASN.1 header. It is prepended to the actual signature
|
|
# (32 bytes) to form a sequence of 51 bytes. OpenSSL will add additional
|
|
# PKCS#1 1.5 padding during the signing operation. The padded hash will look
|
|
# as follows:
|
|
#
|
|
# ASN1HEADER SHA256HASH
|
|
# |----19----||----32----|
|
|
#
|
|
# where ASN1HEADER is the ASN.1 description of the signed data. The complete 51
|
|
# bytes of actual data (i.e. the ASN.1 header complete with the hash) are
|
|
# packed as follows:
|
|
#
|
|
# SEQUENCE(2+49) {
|
|
# SEQUENCE(2+13) {
|
|
# OBJECT(2+9) id-sha256
|
|
# NULL(2+0)
|
|
# }
|
|
# OCTET STRING(2+32) <actual signature bytes...>
|
|
# }
|
|
echo "MDEwDQYJYIZIAWUDBAIBBQAEIA==" | base64 -d > padding-pkcs11
|
|
cat padding-pkcs11 update.hash > update.pkcs11-padhash
|
|
|
|
# Legacy padding for openssl -raw (non smartcard keys)
|
|
#
|
|
# The following is a standard PKCS1-v1_5 padding for SHA256 signatures, as
|
|
# defined in RFC3447. It is prepended to the actual signature (32 bytes) to
|
|
# form a sequence of 256 bytes (2048 bits) that is amenable to RSA signing. The
|
|
# padded hash will look as follows:
|
|
#
|
|
# 0x00 0x01 0xff ... 0xff 0x00 ASN1HEADER SHA256HASH
|
|
# |--------------205-----------||----19----||----32----|
|
|
#
|
|
# where ASN1HEADER is the ASN.1 description of the signed data. The complete 51
|
|
# bytes of actual data (i.e. the ASN.1 header complete with the hash) are
|
|
# packed as follows:
|
|
#
|
|
# SEQUENCE(2+49) {
|
|
# SEQUENCE(2+13) {
|
|
# OBJECT(2+9) id-sha256
|
|
# NULL(2+0)
|
|
# }
|
|
# OCTET STRING(2+32) <actual signature bytes...>
|
|
# }
|
|
echo "AAH/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////ADAxMA0GCWCGSAFlAwQCAQUABCA=" | base64 -d > padding
|
|
cat padding update.hash > update.padhash
|
|
|
|
echo "=== Signing update payload... ==="
|
|
i=1
|
|
signature_sizes=""
|
|
for key in "${private_keys[@]}"; do
|
|
if [[ "${key}" == pkcs11* ]]; then
|
|
sudo OPENSSL_CONF=/etc/ssl/pkcs11.cnf openssl pkeyutl -engine pkcs11 -sign -keyform engine -inkey "${key}" -in update.pkcs11-padhash -out "update.sig.${i}"
|
|
else
|
|
openssl rsautl -raw -sign -inkey ${key} -in update.padhash -out update.sig.${i}
|
|
fi
|
|
let "i += 1"
|
|
done
|
|
|
|
files=""
|
|
for i in update.sig.*; do
|
|
files=${files}:${i}
|
|
done
|
|
files="${files:1:${#files}}"
|
|
echo ${files}
|
|
|
|
delta_generator --signature_file ${files} --in_file update --out_file update.signed
|
|
|
|
i=1
|
|
for key in "${public_keys[@]}"; do
|
|
version="${i}"
|
|
if [ ${#public_keys[@]} == 1 ]; then
|
|
version=2
|
|
fi
|
|
|
|
delta_generator \
|
|
--public_key_version "${version}" \
|
|
--public_key "${key}" \
|
|
--in_file update.signed
|
|
|
|
let "i += 1"
|
|
done
|
|
|
|
mv update.signed ${FLAGS_output}
|
|
echo "=== Update payload signed successfully. ==="
|
|
|
|
trap - INT TERM EXIT
|
|
cleanup noexit
|
|
|
|
echo "Done generating full update."
|