summaryrefslogblamecommitdiffstats
blob: 88e6bbaffd0dba6b7b802a6709015014c6dfd981 (plain) (tree)















































































































































































































































































                                                                                                                                                                                                   





                                                        






























































                                                                                                
#!/bin/bash
#
# Script to add x509 certificate to binary/ELF
#
# Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/
#
#  Redistribution and use in source and binary forms, with or without
#  modification, are permitted provided that the following conditions
#  are met:
#
#    Redistributions of source code must retain the above copyright
#    notice, this list of conditions and the following disclaimer.
#
#    Redistributions in binary form must reproduce the above copyright
#    notice, this list of conditions and the following disclaimer in the
#    documentation and/or other materials provided with the
#    distribution.
#
#    Neither the name of Texas Instruments Incorporated nor the names of
#    its contributors may be used to endorse or promote products derived
#    from this software without specific prior written permission.
#
#  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
#  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
#  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
#  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
#  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
#  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
#  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
#  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
#  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
#  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
#  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#

# Variables
VALID_SHAS="sha256 sha384 sha512 sha224"
OUTPUT=x509-firmware.bin
TEMP_X509=x509-temp.cert
CERT=certificate.bin
RAND_KEY=eckey.pem
VALID_ROM_CORES="r5 m3"
VALID_DMSC_CORES="r5-00 r5-01 a53-00 a53-01 a53-10 a53-11"
SHA=sha512
CORE=m3
LOADADDR=0x00040000
VALID_MASTERS="rom dmsc"

declare -A sha_oids
sha_oids["sha256"]=2.16.840.1.101.3.4.2.1
sha_oids["sha384"]=2.16.840.1.101.3.4.2.2
sha_oids["sha512"]=2.16.840.1.101.3.4.2.3
sha_oids["sha224"]=2.16.840.1.101.3.4.2.4

declare -A core_ids
core_ids["a53-00"]=0x20
core_ids["a53-01"]=0x21
core_ids["a53-10"]=0x22
core_ids["a53-11"]=0x23
core_ids["r5-00"]=0x01
core_ids["r5-01"]=0x02

gen_key() {
	openssl ecparam -out $RAND_KEY -name prime256v1 -genkey
	KEY=$RAND_KEY
}

declare -A options_help
usage() {
	if [ -n "$*" ]; then
		echo "ERROR: $*"
	fi
	echo -n "Usage: $0 "
	for option in "${!options_help[@]}"
	do
		arg=`echo ${options_help[$option]}|cut -d ':' -f1`
		if [ -n "$arg" ]; then
			arg=" $arg"
		fi
		echo -n "[-$option$arg] "
	done
	echo
	echo -e "\nWhere:"
	for option in "${!options_help[@]}"
	do
		arg=`echo ${options_help[$option]}|cut -d ':' -f1`
		txt=`echo ${options_help[$option]}|cut -d ':' -f2`
		tb="\t\t\t"
		if [ -n "$arg" ]; then
			arg=" $arg"
			tb="\t"
		fi
		echo -e "   -$option$arg:$tb$txt"
	done
	echo
	echo "Examples of usage:-"
	echo "# Generate x509 certificate with random key from elf"
	echo "    CROSS_COMPILE=arm-linux-gnueabihf- $0 -b ti-sci-firmware-am6x.elf -o dmsc.bin -l 0x40000"
	echo "# Generate x509 certificate with random key from bin"
	echo "    $0 -b ti-sci-firmware-am6x.bin -o dmsc.bin -l 0x40000"
	echo "# Example of signing the DMSC binary"
	echo "    $0 -m rom -c m3 -b ti-sci-firmware-am6x.bin -o dmsc.bin -l 0x40000"
	echo "# Example of signing the SPL binary"
	echo "    $0 -m rom -c r5 -b spl/u-boot-spl.bin -o tiboot3.bin -l 0x41c00000"
	echo "# Example of signing the ATF binary to run on A53"
	echo "    $0 -m dmsc -c a53-00 -b bl31.bin -o atf.bin -l 0x70000000"
}

options_help[e]="elf_file:ELF file that needs to be signed"
options_help[b]="bin_file:Bin file that needs to be signed"
options_help[k]="key_file:file with key inside it. If not provided script generates a random key."
options_help[o]="output_file:Name of the final output file. default x509-firmware.bin"
options_help[c]="core:target core on which the image would be running. Default is m3. Valid option for rom are $VALID_ROM_CORES. Valid options for DMSC are $VALID_DMSC_CORES"
options_help[d]=":Countersign DMSC firmware image. This signs a previously signed image for a second time."
options_help[s]="sha_type:sha type to be used for certificate generation. Default is sha512. Valid option are $VALID_SHAS"
options_help[l]="loadaddr: Target load address of the binary in hex. Default to $LOADADDR"
options_help[m]="master: Master name for which the image is created. This master software parses the certificate and load the images accordingly. Default to rom. valid options are $VALID_MASTERS"

while getopts "e:b:k:o:c:ds:l:m:h" opt
do
	case $opt in
	e)
		ELF=$OPTARG
	;;
	b)
		BIN=$OPTARG
	;;
	k)
		KEY=$OPTARG
	;;
	o)
		OUTPUT=$OPTARG
	;;
	l)
		LOADADDR=$OPTARG
	;;
	s)
		SHA=$OPTARG
		sha_valid=0
		for tsha in $VALID_SHAS
		do
			if [ "$tsha" == "$SHA" ]; then
				sha_valid=1
			fi
		done
		if [ $sha_valid == 0 ]; then
			usage "Invalid sha input $SHA"
			exit 1
		fi
	;;
	c)
		CORE=$OPTARG
	;;
	d)
		CERTTYPE=3	# CERT_TYPE_FIRMWARE_COUNTERSIGN
	;;
	m)
		MASTER=$OPTARG
		master_valid=0
		for vmaster in $VALID_MASTERS
		do
			if [ "$vmaster" == "$MASTER" ]; then
				master_valid=1
			fi
		done
		if [ $master_valid == 0 ]; then
			usage "Invalid master input $MASTER"
			exit 1
		fi
	;;
	h)
		usage
		exit 0
	;;
	\?)
		usage "Invalid Option '-$OPTARG'"
		exit 1
	;;
	:)
		usage "Option '-$OPTARG' Needs an argument."
		exit 1
	;;
	esac
done

if [ "$#" -eq 0 ]
then
	usage "Arguments missing"
	exit 1
fi

if [ -z "$BIN" -a -z "$ELF" ]; then
	usage "Either Input bin file or ELF file to sign"
	exit 1
fi

if [ "$MASTER" == "dmsc" ]; then
	VALID_CORES=$VALID_DMSC_CORES
else
	# Defaut to ROM image
	VALID_CORES=$VALID_ROM_CORES
	MASTER="rom"
fi

# Verify for valid core inputs
core_valid=0
for tcore in $VALID_CORES
do
	if [ "$tcore" == "$CORE" ]; then
		core_valid=1
	fi
done
if [ $core_valid == 0 ]; then
	usage "Invalid target core $CORE"
	exit 1
fi

# Generate random key if user doesn't provide a key
if [ -z "$KEY" ]; then
	gen_key
fi

if [ "$MASTER" == "dmsc" ]; then
	BOOTCORE=${core_ids["$CORE"]}
	BOOTCORE_OPTS_VER=$(printf "%01x" 1)
	# Add input args option for SET and CLR flags.
	BOOTCORE_OPTS_SETFLAG=$(printf "%08x" 0)
	BOOTCORE_OPTS_CLRFLAG=$(printf "%08x" 0x100) # Clear FLAG_ARMV8_AARCH32
	BOOTCORE_OPTS="0x$BOOTCORE_OPTS_VER$BOOTCORE_OPTS_SETFLAG$BOOTCORE_OPTS_CLRFLAG"
	# Set the cert type to zero.
	# We are not using public/private key store now
	CERTTYPE=$(printf "0x%08x" 0)
else
	if [ "$CORE" == "m3" ]; then
		if [ -z "$CERTTYPE" ]; then
			CERTTYPE=2	# CERT_TYPE_FIRMWARE_IMAGE_BIN
		fi
		BOOTCORE=0		# DMSC Controller (M3)
		BOOTCORE_OPTS=32
	else
		CERTTYPE=1		# CERT_TYPE_PRIMARY_IMAGE_BIN
		BOOTCORE=16		# MCU (R5)
		BOOTCORE_OPTS=32
	fi
fi

if [ -z "$BIN" ]; then
	echo "Generating bin from elf $ELF"
	BIN=firmware.bin
	${CROSS_COMPILE}objcopy -g -S --gap-fill 0x0 -O binary $ELF $BIN
	if [ "$?" != "0" ]; then
		echo "ERROR: Generating bin from $ELF failed. CROSS_COMPILE?"
		exit 1
	fi
fi

SHA_OID=${sha_oids["$SHA"]}
SHA_VAL=`openssl dgst -$SHA -hex $BIN | sed -e "s/^.*= //g"`
BIN_SIZE=`cat $BIN | wc -c`
ADDR=`printf "%08x" $LOADADDR`

# Generate x509 Template
gen_template() {
cat << 'EOF' > x509-template.txt
 [ req ]
 distinguished_name     = req_distinguished_name
 x509_extensions        = v3_ca
 prompt                 = no
 dirstring_type         = nobmp

 [ req_distinguished_name ]
 C                      = US
 ST                     = TX
 L                      = Dallas
 O                      = Texas Instruments Incorporated
 OU                     = Processors
 CN                     = TI Support
 emailAddress           = support@ti.com

 [ v3_ca ]
 basicConstraints = CA:true
 1.3.6.1.4.1.294.1.1 = ASN1:SEQUENCE:boot_seq
 1.3.6.1.4.1.294.1.2 = ASN1:SEQUENCE:image_integrity
 1.3.6.1.4.1.294.1.3 = ASN1:SEQUENCE:swrv
# 1.3.6.1.4.1.294.1.4 = ASN1:SEQUENCE:encryption
 1.3.6.1.4.1.294.1.8 = ASN1:SEQUENCE:debug

 [ boot_seq ]
 certType = INTEGER:TEST_CERT_TYPE
 bootCore = INTEGER:TEST_BOOT_CORE
 bootCoreOpts = INTEGER:TEST_BOOT_CORE_OPTS
 destAddr = FORMAT:HEX,OCT:TEST_BOOT_ADDR
 imageSize = INTEGER:TEST_IMAGE_LENGTH

 [ image_integrity ]
 shaType = OID:TEST_IMAGE_SHA_OID
 shaValue = FORMAT:HEX,OCT:TEST_IMAGE_SHA_VAL

 [ swrv ]
 swrv = INTEGER:0

# [ encryption ]
# initalVector = FORMAT:HEX,OCT:TEST_IMAGE_ENC_IV
# randomString = FORMAT:HEX,OCT:TEST_IMAGE_ENC_RS
# iterationCnt = INTEGER:TEST_IMAGE_KEY_DERIVE_INDEX
# salt = FORMAT:HEX,OCT:TEST_IMAGE_KEY_DERIVE_SALT

 [ debug ]
 debugUID = FORMAT:HEX,OCT:0000000000000000000000000000000000000000000000000000000000000000
 debugType = INTEGER:4
 coreDbgEn = INTEGER:0
 coreDbgSecEn = INTEGER:0
EOF
}

gen_cert() {
	echo "Certificate being generated :"
	echo "	LOADADDR = 0x$ADDR"
	echo "	IMAGE_SIZE = $BIN_SIZE"
	echo "	CERT_TYPE = $CERTTYPE"
	sed -e "s/TEST_IMAGE_LENGTH/$BIN_SIZE/"	\
		-e "s/TEST_IMAGE_SHA_OID/$SHA_OID/" \
		-e "s/TEST_IMAGE_SHA_VAL/$SHA_VAL/" \
		-e "s/TEST_CERT_TYPE/$CERTTYPE/" \
		-e "s/TEST_BOOT_CORE_OPTS/$BOOTCORE_OPTS/" \
		-e "s/TEST_BOOT_CORE/$BOOTCORE/" \
		-e "s/TEST_BOOT_ADDR/$ADDR/" x509-template.txt > $TEMP_X509
	openssl req -new -x509 -key $KEY -nodes -outform DER -out $CERT -config $TEMP_X509 -$SHA
}

gen_template
gen_cert
cat $CERT $BIN > $OUTPUT

echo "SUCCESS: Image $OUTPUT generated."

# Remove all intermediate files
rm $TEMP_X509 $CERT x509-template.txt
if [ "$KEY" == "$RAND_KEY" ]; then
	rm $RAND_KEY
fi