Skip to content

Commit

Permalink
TA dev kit: add support for TA encryption
Browse files Browse the repository at this point in the history
Add CFG_ENCRYPT_TA as TA build time configuration option to enable
encryption of TA using encryption key provided via TA_ENC_KEY build
time option. The default value of TA_ENC_KEY is derived from 16 zero
bytes default hardware unique key.

Also rename scripts/sign.py to scripts/sign_encrypt.py to reflect
optional encryption support along with signing of TAs.

Signed-off-by: Sumit Garg <[email protected]>
Reviewed-by: Jens Wiklander <[email protected]>
  • Loading branch information
b49020 authored and jforissier committed Nov 22, 2019
1 parent e1afc43 commit 2de17fd
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 27 deletions.
2 changes: 1 addition & 1 deletion mk/lib.mk
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ libdirs := $(out-dir)/$(base-prefix)$(libdir) $(libdirs)
libnames := $(libname) $(libnames)
libdeps := $(lib-libfile) $(libdeps)

SIGN = scripts/sign.py
SIGN = scripts/sign_encrypt.py
TA_SIGN_KEY ?= keys/default_ta.pem

define process-lib
Expand Down
70 changes: 50 additions & 20 deletions scripts/sign.py → scripts/sign_encrypt.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
#!/usr/bin/env python3
# SPDX-License-Identifier: BSD-2-Clause
#
# Copyright (c) 2015, 2017, Linaro Limited
# Copyright (c) 2015, 2017, 2019, Linaro Limited
#
# SPDX-License-Identifier: BSD-2-Clause

import sys

Expand All @@ -19,7 +19,7 @@ def int_parse(str):
def get_args(logger):
from argparse import ArgumentParser, RawDescriptionHelpFormatter
import textwrap
command_base = ['sign', 'digest', 'stitch']
command_base = ['sign-enc', 'digest', 'stitch']
command_aliases_digest = ['generate-digest']
command_aliases_stitch = ['stitch-ta']
command_aliases = command_aliases_digest + command_aliases_stitch
Expand All @@ -29,26 +29,31 @@ def get_args(logger):
sat = '[' + ', '.join(command_aliases_stitch) + ']'

parser = ArgumentParser(
description='Sign a Tusted Application for OP-TEE.',
description='Sign and encrypt (optional) a Tusted Application for' +
' OP-TEE.',
usage='\n %(prog)s command [ arguments ]\n\n'

' command:\n' +
' sign Generate signed loadable TA image file.\n' +
' Takes arguments --uuid, --ta-version, --in, --out' +
' and --key.\n' +
' sign-enc Generate signed and optionally encrypted loadable' +
' TA image file.\n' +
' Takes arguments --uuid, --ta-version, --in, --out,' +
' --key\n' +
' and --enc-key (optional).\n' +
' digest Generate loadable TA binary image digest' +
' for offline\n' +
' signing. Takes arguments --uuid, --ta-version,' +
' --in, --key and --dig.\n' +
' stitch Generate loadable signed TA binary image' +
' file from\n' +
' signing. Takes arguments --uuid, --ta-version,' +
' --in, --key,\n'
' --enc-key (optional) and --dig.\n' +
' stitch Generate loadable signed and encrypted TA binary' +
' image file from\n' +
' TA raw image and its signature. Takes' +
' arguments\n' +
' --uuid, --in, --key, --out, and --sig.\n\n' +
' --uuid, --in, --key, --enc-key (optional), --out,' +
' and --sig.\n\n' +
' %(prog)s --help show available commands and arguments\n\n',
formatter_class=RawDescriptionHelpFormatter,
epilog=textwrap.dedent('''\
If no command is given, the script will default to "sign".
If no command is given, the script will default to "sign-enc".
command aliases:
The command \'digest\' can be aliased by ''' + dat + '''
Expand All @@ -63,12 +68,14 @@ def get_args(logger):

parser.add_argument(
'command', choices=command_choices, nargs='?',
default='sign',
default='sign-enc',
help='Command, one of [' + ', '.join(command_base) + ']')
parser.add_argument('--uuid', required=True,
type=uuid_parse, help='String UUID of the TA')
parser.add_argument('--key', required=True,
help='Name of key file (PEM format)')
help='Name of signing key file (PEM format)')
parser.add_argument('--enc-key', required=False,
help='Encryption key string')
parser.add_argument(
'--ta-version', required=False, type=int_parse, default=0,
help='TA version stored as a 32-bit unsigned integer and used for\n' +
Expand Down Expand Up @@ -156,17 +163,34 @@ def main():
hdr_version = args.ta_version # struct shdr_bootstrap_ta::ta_version

magic = 0x4f545348 # SHDR_MAGIC
img_type = 1 # SHDR_BOOTSTRAP_TA
if args.enc_key:
img_type = 2 # SHDR_ENCRYPTED_TA
else:
img_type = 1 # SHDR_BOOTSTRAP_TA
algo = 0x70004830 # TEE_ALG_RSASSA_PKCS1_V1_5_SHA256

shdr = struct.pack('<IIIIHH',
magic, img_type, img_size, algo, digest_len, sig_len)
shdr_uuid = args.uuid.bytes
shdr_version = struct.pack('<I', hdr_version)

if args.enc_key:
from Cryptodome.Cipher import AES
cipher = AES.new(bytearray.fromhex(args.enc_key), AES.MODE_GCM)
ciphertext, tag = cipher.encrypt_and_digest(img)

enc_algo = 0x40000810 # TEE_ALG_AES_GCM
flags = 0 # SHDR_ENC_KEY_DEV_SPECIFIC
ehdr = struct.pack('<IIHH',
enc_algo, flags, len(cipher.nonce), len(tag))

h.update(shdr)
h.update(shdr_uuid)
h.update(shdr_version)
if args.enc_key:
h.update(ehdr)
h.update(cipher.nonce)
h.update(tag)
h.update(img)
img_digest = h.digest()

Expand All @@ -177,9 +201,15 @@ def write_image_with_signature(sig):
f.write(sig)
f.write(shdr_uuid)
f.write(shdr_version)
f.write(img)
if args.enc_key:
f.write(ehdr)
f.write(cipher.nonce)
f.write(tag)
f.write(ciphertext)
else:
f.write(img)

def sign_ta():
def sign_encrypt_ta():
if not key.has_private():
logger.error('Provided key cannot be used for signing, ' +
'please use offline-signing mode.')
Expand Down Expand Up @@ -222,12 +252,12 @@ def stitch_ta():

# dispatch command
{
'sign': sign_ta,
'sign-enc': sign_encrypt_ta,
'digest': generate_digest,
'generate-digest': generate_digest,
'stitch': stitch_ta,
'stitch-ta': stitch_ta
}.get(args.command, 'sign_ta')()
}.get(args.command, 'sign_encrypt_ta')()


if __name__ == "__main__":
Expand Down
24 changes: 20 additions & 4 deletions ta/arch/arm/link.mk
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,20 @@ link-script$(sm) = $(ta-dev-kit-dir$(sm))/src/ta.ld.S
link-script-pp$(sm) = $(link-out-dir$(sm))/ta.lds
link-script-dep$(sm) = $(link-out-dir$(sm))/.ta.ld.d

SIGN ?= $(ta-dev-kit-dir$(sm))/scripts/sign.py
SIGN_ENC ?= $(ta-dev-kit-dir$(sm))/scripts/sign_encrypt.py
TA_SIGN_KEY ?= $(ta-dev-kit-dir$(sm))/keys/default_ta.pem

ifeq ($(CFG_ENCRYPT_TA),y)
# Default TA encryption key is a dummy key derived from default
# hardware unique key (an array of 16 zero bytes) to demonstrate
# usage of REE-FS TAs encryption feature.
#
# Note that a user of this TA encryption feature needs to provide
# encryption key and its handling corresponding to their security
# requirements.
TA_ENC_KEY ?= 'b64d239b1f3c7d3b06506229cd8ff7c8af2bb4db2168621ac62c84948468c4f4'
endif

all: $(link-out-dir$(sm))/$(user-ta-uuid).dmp \
$(link-out-dir$(sm))/$(user-ta-uuid).stripped.elf \
$(link-out-dir$(sm))/$(user-ta-uuid).ta
Expand Down Expand Up @@ -72,12 +83,17 @@ $(link-out-dir$(sm))/$(user-ta-uuid).stripped.elf: \
@$(cmd-echo-silent) ' OBJCOPY $$@'
$(q)$(OBJCOPY$(sm)) --strip-unneeded $$< $$@

cmd-echo$(user-ta-uuid) := SIGN #
ifeq ($(CFG_ENCRYPT_TA),y)
crypt-args$(user-ta-uuid) := --enc-key $(TA_ENC_KEY)
cmd-echo$(user-ta-uuid) := SIGNENC
endif
$(link-out-dir$(sm))/$(user-ta-uuid).ta: \
$(link-out-dir$(sm))/$(user-ta-uuid).stripped.elf \
$(TA_SIGN_KEY)
@$(cmd-echo-silent) ' SIGN $$@'
$(q)$(SIGN) --key $(TA_SIGN_KEY) --uuid $(user-ta-uuid) \
--in $$< --out $$@
@$(cmd-echo-silent) ' $$(cmd-echo$(user-ta-uuid)) $$@'
$(q)$(SIGN_ENC) --key $(TA_SIGN_KEY) $$(crypt-args$(user-ta-uuid)) \
--uuid $(user-ta-uuid) --in $$< --out $$@
endef

$(eval $(call gen-link-t))
Expand Down
2 changes: 1 addition & 1 deletion ta/arch/arm/link_shlib.mk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ $(error SHLIBUUID not set)
endif
link-out-dir = $(out-dir)

SIGN ?= $(TA_DEV_KIT_DIR)/scripts/sign.py
SIGN ?= $(TA_DEV_KIT_DIR)/scripts/sign_encrypt.py
TA_SIGN_KEY ?= $(TA_DEV_KIT_DIR)/keys/default_ta.pem

all: $(link-out-dir)/$(shlibname).so $(link-out-dir)/$(shlibname).dmp \
Expand Down
3 changes: 2 additions & 1 deletion ta/ta.mk
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,8 @@ $(foreach f, $(ta-keys), \
$(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/keys)))

# Copy the scripts
ta-scripts = scripts/sign.py scripts/symbolize.py scripts/llvm-objcopy-wrapper
ta-scripts = scripts/sign_encrypt.py scripts/symbolize.py \
scripts/llvm-objcopy-wrapper
$(foreach f, $(ta-scripts), \
$(eval $(call copy-file, $(f), $(out-dir)/export-$(sm)/scripts)))

Expand Down

0 comments on commit 2de17fd

Please sign in to comment.