From bc420748bfc44a9e09000a3966fc59e9e0219df4 Mon Sep 17 00:00:00 2001 From: Jens Wiklander Date: Tue, 5 May 2015 14:59:15 +0200 Subject: [PATCH] TA as ELF + signature Changes format of TA to use the ELF format instead. This patch also adds signature checking of the TA. The format of the TA is: (part of ELF spec, pointing out segments to load) A struct ta_head is placed in the first section of the first segment to carry flags and other properties of the TA. elf32.h, elf64.h and elf_common.h are imported from FreeBSD. In addition to the R_ARM_RELATIVE relocation type, adds support for R_ARM_ABS32 relocations. Since a symbol table is needed to process this relocation type a separate program header is added in the TA ELF containing the sections .dynamic, .dynsym, .dynstr and .hash. These sections are only needed during relocation and could be released once the TA is relocated. A default signing key has been generated with openssl genrsa -out key.pem and added as keys/default_ta.pem Signed-off-by: Jens Wiklander Tested-by: Jens Wiklander (QEMU, FVP) Reviewed-by: Pascal Brand Tested-by: Pascal Brand (STM platform) Tested-by: Pascal Brand (QEMU platform) Reviewed-by: Jerome Forissier Tested-by: Jerome Forissier (HiKey) --- core/arch/arm/kernel/elf32.h | 245 ++++ core/arch/arm/kernel/elf64.h | 248 ++++ core/arch/arm/kernel/elf_common.h | 1006 +++++++++++++++++ core/arch/arm/kernel/elf_load.c | 399 +++++++ .../kernel/kta_types.h => kernel/elf_load.h} | 33 +- core/arch/arm/kernel/sub.mk | 1 + core/arch/arm/kernel/tee_ta_manager.c | 577 ++++------ core/arch/arm/mm/tee_mmu.c | 6 +- core/arch/arm/plat-hikey/conf.mk | 1 - core/arch/arm/plat-mediatek/conf.mk | 1 - core/arch/arm/plat-stm/conf.mk | 1 - core/arch/arm/plat-sunxi/conf.mk | 1 - core/arch/arm/plat-vexpress/conf.mk | 1 - core/core.mk | 8 + core/default_signing.properties | 11 - core/include/kernel/tee_ta_manager.h | 15 +- core/include/kernel/tee_ta_manager_unpg.h | 14 +- core/include/signed_hdr.h | 75 ++ .../include/{kernel/tee_ta.h => ta_pub_key.h} | 56 +- core/tee/tee_svc.c | 14 +- core/tee/tee_svc_storage.c | 10 +- documentation/build_system.md | 2 +- documentation/optee_design.md | 26 +- keys/default_ta.pem | 27 + lib/libutee/arch/arm/user_ta_entry.c | 8 +- lib/libutee/include/user_ta_header.h | 63 +- mk/cleanvars.mk | 1 + mk/compile.mk | 4 + mk/config.mk | 3 + scripts/pem_to_pub_c.py | 79 ++ scripts/sign.py | 80 ++ ta/arch/arm/fix_ta_binary | 131 --- ta/arch/arm/link.mk | 20 +- ta/arch/arm/user_ta_elf_arm.lds | 221 ++-- ta/arch/arm/user_ta_header.c | 41 +- ta/ta.mk | 7 +- 36 files changed, 2567 insertions(+), 869 deletions(-) create mode 100644 core/arch/arm/kernel/elf32.h create mode 100644 core/arch/arm/kernel/elf64.h create mode 100644 core/arch/arm/kernel/elf_common.h create mode 100644 core/arch/arm/kernel/elf_load.c rename core/arch/arm/{include/kernel/kta_types.h => kernel/elf_load.h} (65%) delete mode 100644 core/default_signing.properties create mode 100644 core/include/signed_hdr.h rename core/include/{kernel/tee_ta.h => ta_pub_key.h} (57%) create mode 100644 keys/default_ta.pem create mode 100755 scripts/pem_to_pub_c.py create mode 100755 scripts/sign.py delete mode 100755 ta/arch/arm/fix_ta_binary diff --git a/core/arch/arm/kernel/elf32.h b/core/arch/arm/kernel/elf32.h new file mode 100644 index 00000000000..d374208587f --- /dev/null +++ b/core/arch/arm/kernel/elf32.h @@ -0,0 +1,245 @@ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF32_H_ +#define _SYS_ELF32_H_ 1 + +#include "elf_common.h" + +/* + * ELF definitions common to all 32-bit architectures. + */ + +typedef uint32_t Elf32_Addr; +typedef uint16_t Elf32_Half; +typedef uint32_t Elf32_Off; +typedef int32_t Elf32_Sword; +typedef uint32_t Elf32_Word; +typedef uint64_t Elf32_Lword; + +typedef Elf32_Word Elf32_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf32_Word Elf32_Size; +typedef Elf32_Sword Elf32_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf32_Half e_type; /* File type. */ + Elf32_Half e_machine; /* Machine architecture. */ + Elf32_Word e_version; /* ELF format version. */ + Elf32_Addr e_entry; /* Entry point. */ + Elf32_Off e_phoff; /* Program header file offset. */ + Elf32_Off e_shoff; /* Section header file offset. */ + Elf32_Word e_flags; /* Architecture-specific flags. */ + Elf32_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf32_Half e_phentsize; /* Size of program header entry. */ + Elf32_Half e_phnum; /* Number of program header entries. */ + Elf32_Half e_shentsize; /* Size of section header entry. */ + Elf32_Half e_shnum; /* Number of section header entries. */ + Elf32_Half e_shstrndx; /* Section name strings section. */ +} Elf32_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf32_Word sh_name; /* Section name (index into the + section header string table). */ + Elf32_Word sh_type; /* Section type. */ + Elf32_Word sh_flags; /* Section flags. */ + Elf32_Addr sh_addr; /* Address in memory image. */ + Elf32_Off sh_offset; /* Offset in file. */ + Elf32_Word sh_size; /* Size in bytes. */ + Elf32_Word sh_link; /* Index of a related section. */ + Elf32_Word sh_info; /* Depends on section type. */ + Elf32_Word sh_addralign; /* Alignment in bytes. */ + Elf32_Word sh_entsize; /* Size of each entry in section. */ +} Elf32_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf32_Word p_type; /* Entry type. */ + Elf32_Off p_offset; /* File offset of contents. */ + Elf32_Addr p_vaddr; /* Virtual address in memory image. */ + Elf32_Addr p_paddr; /* Physical address (not used). */ + Elf32_Word p_filesz; /* Size of contents in file. */ + Elf32_Word p_memsz; /* Size of contents in memory. */ + Elf32_Word p_flags; /* Access permission flags. */ + Elf32_Word p_align; /* Alignment in memory and file. */ +} Elf32_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf32_Sword d_tag; /* Entry type. */ + union { + Elf32_Word d_val; /* Integer value. */ + Elf32_Addr d_ptr; /* Address value. */ + } d_un; +} Elf32_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ +} Elf32_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf32_Addr r_offset; /* Location to be relocated. */ + Elf32_Word r_info; /* Relocation type and symbol index. */ + Elf32_Sword r_addend; /* Addend. */ +} Elf32_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF32_R_SYM(info) ((info) >> 8) +#define ELF32_R_TYPE(info) ((unsigned char)(info)) + +/* Macro for constructing r_info from field values. */ +#define ELF32_R_INFO(sym, type) (((sym) << 8) + (unsigned char)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf32_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf32_Lword m_value; /* symbol value */ + Elf32_Word m_info; /* size + index */ + Elf32_Word m_poffset; /* symbol offset */ + Elf32_Half m_repeat; /* repeat count */ + Elf32_Half m_stride; /* stride info */ +} Elf32_Move; + +/* + * The macros compose and decompose values for Move.r_info + * + * sym = ELF32_M_SYM(M.m_info) + * size = ELF32_M_SIZE(M.m_info) + * M.m_info = ELF32_M_INFO(sym, size) + */ +#define ELF32_M_SYM(info) ((info)>>8) +#define ELF32_M_SIZE(info) ((unsigned char)(info)) +#define ELF32_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf32_Word c_tag; /* how to interpret value */ + union { + Elf32_Word c_val; + Elf32_Addr c_ptr; + } c_un; +} Elf32_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf32_Word st_name; /* String table index of name. */ + Elf32_Addr st_value; /* Symbol value. */ + Elf32_Word st_size; /* Size of associated object. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf32_Half st_shndx; /* Section index of symbol. */ +} Elf32_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF32_ST_BIND(info) ((info) >> 4) +#define ELF32_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF32_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF32_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU symbol versioning. */ +typedef struct +{ + Elf32_Half vd_version; + Elf32_Half vd_flags; + Elf32_Half vd_ndx; + Elf32_Half vd_cnt; + Elf32_Word vd_hash; + Elf32_Word vd_aux; + Elf32_Word vd_next; +} Elf32_Verdef; + +typedef struct +{ + Elf32_Word vda_name; + Elf32_Word vda_next; +} Elf32_Verdaux; + +typedef struct +{ + Elf32_Half vn_version; + Elf32_Half vn_cnt; + Elf32_Word vn_file; + Elf32_Word vn_aux; + Elf32_Word vn_next; +} Elf32_Verneed; + +typedef struct +{ + Elf32_Word vna_hash; + Elf32_Half vna_flags; + Elf32_Half vna_other; + Elf32_Word vna_name; + Elf32_Word vna_next; +} Elf32_Vernaux; + +typedef Elf32_Half Elf32_Versym; + +typedef struct { + Elf32_Half si_boundto; /* direct bindings - symbol bound to */ + Elf32_Half si_flags; /* per symbol flags */ +} Elf32_Syminfo; + +#endif /* !_SYS_ELF32_H_ */ diff --git a/core/arch/arm/kernel/elf64.h b/core/arch/arm/kernel/elf64.h new file mode 100644 index 00000000000..c468dcda4a7 --- /dev/null +++ b/core/arch/arm/kernel/elf64.h @@ -0,0 +1,248 @@ +/*- + * Copyright (c) 1996-1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF64_H_ +#define _SYS_ELF64_H_ 1 + +#include "elf_common.h" + +/* + * ELF definitions common to all 64-bit architectures. + */ + +typedef uint64_t Elf64_Addr; +typedef uint16_t Elf64_Half; +typedef uint64_t Elf64_Off; +typedef int32_t Elf64_Sword; +typedef int64_t Elf64_Sxword; +typedef uint32_t Elf64_Word; +typedef uint64_t Elf64_Lword; +typedef uint64_t Elf64_Xword; + +/* + * Types of dynamic symbol hash table bucket and chain elements. + * + * This is inconsistent among 64 bit architectures, so a machine dependent + * typedef is required. + */ + +typedef Elf64_Word Elf64_Hashelt; + +/* Non-standard class-dependent datatype used for abstraction. */ +typedef Elf64_Xword Elf64_Size; +typedef Elf64_Sxword Elf64_Ssize; + +/* + * ELF header. + */ + +typedef struct { + unsigned char e_ident[EI_NIDENT]; /* File identification. */ + Elf64_Half e_type; /* File type. */ + Elf64_Half e_machine; /* Machine architecture. */ + Elf64_Word e_version; /* ELF format version. */ + Elf64_Addr e_entry; /* Entry point. */ + Elf64_Off e_phoff; /* Program header file offset. */ + Elf64_Off e_shoff; /* Section header file offset. */ + Elf64_Word e_flags; /* Architecture-specific flags. */ + Elf64_Half e_ehsize; /* Size of ELF header in bytes. */ + Elf64_Half e_phentsize; /* Size of program header entry. */ + Elf64_Half e_phnum; /* Number of program header entries. */ + Elf64_Half e_shentsize; /* Size of section header entry. */ + Elf64_Half e_shnum; /* Number of section header entries. */ + Elf64_Half e_shstrndx; /* Section name strings section. */ +} Elf64_Ehdr; + +/* + * Section header. + */ + +typedef struct { + Elf64_Word sh_name; /* Section name (index into the + section header string table). */ + Elf64_Word sh_type; /* Section type. */ + Elf64_Xword sh_flags; /* Section flags. */ + Elf64_Addr sh_addr; /* Address in memory image. */ + Elf64_Off sh_offset; /* Offset in file. */ + Elf64_Xword sh_size; /* Size in bytes. */ + Elf64_Word sh_link; /* Index of a related section. */ + Elf64_Word sh_info; /* Depends on section type. */ + Elf64_Xword sh_addralign; /* Alignment in bytes. */ + Elf64_Xword sh_entsize; /* Size of each entry in section. */ +} Elf64_Shdr; + +/* + * Program header. + */ + +typedef struct { + Elf64_Word p_type; /* Entry type. */ + Elf64_Word p_flags; /* Access permission flags. */ + Elf64_Off p_offset; /* File offset of contents. */ + Elf64_Addr p_vaddr; /* Virtual address in memory image. */ + Elf64_Addr p_paddr; /* Physical address (not used). */ + Elf64_Xword p_filesz; /* Size of contents in file. */ + Elf64_Xword p_memsz; /* Size of contents in memory. */ + Elf64_Xword p_align; /* Alignment in memory and file. */ +} Elf64_Phdr; + +/* + * Dynamic structure. The ".dynamic" section contains an array of them. + */ + +typedef struct { + Elf64_Sxword d_tag; /* Entry type. */ + union { + Elf64_Xword d_val; /* Integer value. */ + Elf64_Addr d_ptr; /* Address value. */ + } d_un; +} Elf64_Dyn; + +/* + * Relocation entries. + */ + +/* Relocations that don't need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ +} Elf64_Rel; + +/* Relocations that need an addend field. */ +typedef struct { + Elf64_Addr r_offset; /* Location to be relocated. */ + Elf64_Xword r_info; /* Relocation type and symbol index. */ + Elf64_Sxword r_addend; /* Addend. */ +} Elf64_Rela; + +/* Macros for accessing the fields of r_info. */ +#define ELF64_R_SYM(info) ((info) >> 32) +#define ELF64_R_TYPE(info) ((info) & 0xffffffffL) + +/* Macro for constructing r_info from field values. */ +#define ELF64_R_INFO(sym, type) (((sym) << 32) + ((type) & 0xffffffffL)) + +#define ELF64_R_TYPE_DATA(info) (((Elf64_Xword)(info)<<32)>>40) +#define ELF64_R_TYPE_ID(info) (((Elf64_Xword)(info)<<56)>>56) +#define ELF64_R_TYPE_INFO(data, type) \ + (((Elf64_Xword)(data)<<8)+(Elf64_Xword)(type)) + +/* + * Note entry header + */ +typedef Elf_Note Elf64_Nhdr; + +/* + * Move entry + */ +typedef struct { + Elf64_Lword m_value; /* symbol value */ + Elf64_Xword m_info; /* size + index */ + Elf64_Xword m_poffset; /* symbol offset */ + Elf64_Half m_repeat; /* repeat count */ + Elf64_Half m_stride; /* stride info */ +} Elf64_Move; + +#define ELF64_M_SYM(info) ((info)>>8) +#define ELF64_M_SIZE(info) ((unsigned char)(info)) +#define ELF64_M_INFO(sym, size) (((sym)<<8)+(unsigned char)(size)) + +/* + * Hardware/Software capabilities entry + */ +typedef struct { + Elf64_Xword c_tag; /* how to interpret value */ + union { + Elf64_Xword c_val; + Elf64_Addr c_ptr; + } c_un; +} Elf64_Cap; + +/* + * Symbol table entries. + */ + +typedef struct { + Elf64_Word st_name; /* String table index of name. */ + unsigned char st_info; /* Type and binding information. */ + unsigned char st_other; /* Reserved (not used). */ + Elf64_Half st_shndx; /* Section index of symbol. */ + Elf64_Addr st_value; /* Symbol value. */ + Elf64_Xword st_size; /* Size of associated object. */ +} Elf64_Sym; + +/* Macros for accessing the fields of st_info. */ +#define ELF64_ST_BIND(info) ((info) >> 4) +#define ELF64_ST_TYPE(info) ((info) & 0xf) + +/* Macro for constructing st_info from field values. */ +#define ELF64_ST_INFO(bind, type) (((bind) << 4) + ((type) & 0xf)) + +/* Macro for accessing the fields of st_other. */ +#define ELF64_ST_VISIBILITY(oth) ((oth) & 0x3) + +/* Structures used by Sun & GNU-style symbol versioning. */ +typedef struct { + Elf64_Half vd_version; + Elf64_Half vd_flags; + Elf64_Half vd_ndx; + Elf64_Half vd_cnt; + Elf64_Word vd_hash; + Elf64_Word vd_aux; + Elf64_Word vd_next; +} Elf64_Verdef; + +typedef struct { + Elf64_Word vda_name; + Elf64_Word vda_next; +} Elf64_Verdaux; + +typedef struct { + Elf64_Half vn_version; + Elf64_Half vn_cnt; + Elf64_Word vn_file; + Elf64_Word vn_aux; + Elf64_Word vn_next; +} Elf64_Verneed; + +typedef struct { + Elf64_Word vna_hash; + Elf64_Half vna_flags; + Elf64_Half vna_other; + Elf64_Word vna_name; + Elf64_Word vna_next; +} Elf64_Vernaux; + +typedef Elf64_Half Elf64_Versym; + +typedef struct { + Elf64_Half si_boundto; /* direct bindings - symbol bound to */ + Elf64_Half si_flags; /* per symbol flags */ +} Elf64_Syminfo; + +#endif /* !_SYS_ELF64_H_ */ diff --git a/core/arch/arm/kernel/elf_common.h b/core/arch/arm/kernel/elf_common.h new file mode 100644 index 00000000000..dd8cd507143 --- /dev/null +++ b/core/arch/arm/kernel/elf_common.h @@ -0,0 +1,1006 @@ +/*- + * Copyright (c) 2000, 2001, 2008, 2011, David E. O'Brien + * Copyright (c) 1998 John D. Polstra. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. 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. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. + * + * $FreeBSD$ + */ + +#ifndef _SYS_ELF_COMMON_H_ +#define _SYS_ELF_COMMON_H_ 1 + +/* + * ELF definitions that are independent of architecture or word size. + */ + +/* + * Note header. The ".note" section contains an array of notes. Each + * begins with this header, aligned to a word boundary. Immediately + * following the note header is n_namesz bytes of name, padded to the + * next word boundary. Then comes n_descsz bytes of descriptor, again + * padded to a word boundary. The values of n_namesz and n_descsz do + * not include the padding. + */ + +typedef struct { + uint32_t n_namesz; /* Length of name. */ + uint32_t n_descsz; /* Length of descriptor. */ + uint32_t n_type; /* Type of this note. */ +} Elf_Note; + +/* + * The header for GNU-style hash sections. + */ + +typedef struct { + uint32_t gh_nbuckets; /* Number of hash buckets. */ + uint32_t gh_symndx; /* First visible symbol in .dynsym. */ + uint32_t gh_maskwords; /* #maskwords used in bloom filter. */ + uint32_t gh_shift2; /* Bloom filter shift count. */ +} Elf_GNU_Hash_Header; + +/* Indexes into the e_ident array. Keep synced with + http://www.sco.com/developers/gabi/latest/ch4.eheader.html */ +#define EI_MAG0 0 /* Magic number, byte 0. */ +#define EI_MAG1 1 /* Magic number, byte 1. */ +#define EI_MAG2 2 /* Magic number, byte 2. */ +#define EI_MAG3 3 /* Magic number, byte 3. */ +#define EI_CLASS 4 /* Class of machine. */ +#define EI_DATA 5 /* Data format. */ +#define EI_VERSION 6 /* ELF format version. */ +#define EI_OSABI 7 /* Operating system / ABI identification */ +#define EI_ABIVERSION 8 /* ABI version */ +#define OLD_EI_BRAND 8 /* Start of architecture identification. */ +#define EI_PAD 9 /* Start of padding (per SVR4 ABI). */ +#define EI_NIDENT 16 /* Size of e_ident array. */ + +/* Values for the magic number bytes. */ +#define ELFMAG0 0x7f +#define ELFMAG1 'E' +#define ELFMAG2 'L' +#define ELFMAG3 'F' +#define ELFMAG "\177ELF" /* magic string */ +#define SELFMAG 4 /* magic string size */ + +/* Values for e_ident[EI_VERSION] and e_version. */ +#define EV_NONE 0 +#define EV_CURRENT 1 + +/* Values for e_ident[EI_CLASS]. */ +#define ELFCLASSNONE 0 /* Unknown class. */ +#define ELFCLASS32 1 /* 32-bit architecture. */ +#define ELFCLASS64 2 /* 64-bit architecture. */ + +/* Values for e_ident[EI_DATA]. */ +#define ELFDATANONE 0 /* Unknown data format. */ +#define ELFDATA2LSB 1 /* 2's complement little-endian. */ +#define ELFDATA2MSB 2 /* 2's complement big-endian. */ + +/* Values for e_ident[EI_OSABI]. */ +#define ELFOSABI_NONE 0 /* UNIX System V ABI */ +#define ELFOSABI_HPUX 1 /* HP-UX operating system */ +#define ELFOSABI_NETBSD 2 /* NetBSD */ +#define ELFOSABI_LINUX 3 /* GNU/Linux */ +#define ELFOSABI_HURD 4 /* GNU/Hurd */ +#define ELFOSABI_86OPEN 5 /* 86Open common IA32 ABI */ +#define ELFOSABI_SOLARIS 6 /* Solaris */ +#define ELFOSABI_AIX 7 /* AIX */ +#define ELFOSABI_IRIX 8 /* IRIX */ +#define ELFOSABI_FREEBSD 9 /* FreeBSD */ +#define ELFOSABI_TRU64 10 /* TRU64 UNIX */ +#define ELFOSABI_MODESTO 11 /* Novell Modesto */ +#define ELFOSABI_OPENBSD 12 /* OpenBSD */ +#define ELFOSABI_OPENVMS 13 /* Open VMS */ +#define ELFOSABI_NSK 14 /* HP Non-Stop Kernel */ +#define ELFOSABI_AROS 15 /* Amiga Research OS */ +#define ELFOSABI_ARM 97 /* ARM */ +#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ + +#define ELFOSABI_SYSV ELFOSABI_NONE /* symbol used in old spec */ +#define ELFOSABI_MONTEREY ELFOSABI_AIX /* Monterey */ + +/* e_ident */ +#define IS_ELF(ehdr) ((ehdr).e_ident[EI_MAG0] == ELFMAG0 && \ + (ehdr).e_ident[EI_MAG1] == ELFMAG1 && \ + (ehdr).e_ident[EI_MAG2] == ELFMAG2 && \ + (ehdr).e_ident[EI_MAG3] == ELFMAG3) + +/* Values for e_type. */ +#define ET_NONE 0 /* Unknown type. */ +#define ET_REL 1 /* Relocatable. */ +#define ET_EXEC 2 /* Executable. */ +#define ET_DYN 3 /* Shared object. */ +#define ET_CORE 4 /* Core file. */ +#define ET_LOOS 0xfe00 /* First operating system specific. */ +#define ET_HIOS 0xfeff /* Last operating system-specific. */ +#define ET_LOPROC 0xff00 /* First processor-specific. */ +#define ET_HIPROC 0xffff /* Last processor-specific. */ + +/* Values for e_machine. */ +#define EM_NONE 0 /* Unknown machine. */ +#define EM_M32 1 /* AT&T WE32100. */ +#define EM_SPARC 2 /* Sun SPARC. */ +#define EM_386 3 /* Intel i386. */ +#define EM_68K 4 /* Motorola 68000. */ +#define EM_88K 5 /* Motorola 88000. */ +#define EM_860 7 /* Intel i860. */ +#define EM_MIPS 8 /* MIPS R3000 Big-Endian only. */ +#define EM_S370 9 /* IBM System/370. */ +#define EM_MIPS_RS3_LE 10 /* MIPS R3000 Little-Endian. */ +#define EM_PARISC 15 /* HP PA-RISC. */ +#define EM_VPP500 17 /* Fujitsu VPP500. */ +#define EM_SPARC32PLUS 18 /* SPARC v8plus. */ +#define EM_960 19 /* Intel 80960. */ +#define EM_PPC 20 /* PowerPC 32-bit. */ +#define EM_PPC64 21 /* PowerPC 64-bit. */ +#define EM_S390 22 /* IBM System/390. */ +#define EM_V800 36 /* NEC V800. */ +#define EM_FR20 37 /* Fujitsu FR20. */ +#define EM_RH32 38 /* TRW RH-32. */ +#define EM_RCE 39 /* Motorola RCE. */ +#define EM_ARM 40 /* ARM. */ +#define EM_SH 42 /* Hitachi SH. */ +#define EM_SPARCV9 43 /* SPARC v9 64-bit. */ +#define EM_TRICORE 44 /* Siemens TriCore embedded processor. */ +#define EM_ARC 45 /* Argonaut RISC Core. */ +#define EM_H8_300 46 /* Hitachi H8/300. */ +#define EM_H8_300H 47 /* Hitachi H8/300H. */ +#define EM_H8S 48 /* Hitachi H8S. */ +#define EM_H8_500 49 /* Hitachi H8/500. */ +#define EM_IA_64 50 /* Intel IA-64 Processor. */ +#define EM_MIPS_X 51 /* Stanford MIPS-X. */ +#define EM_COLDFIRE 52 /* Motorola ColdFire. */ +#define EM_68HC12 53 /* Motorola M68HC12. */ +#define EM_MMA 54 /* Fujitsu MMA. */ +#define EM_PCP 55 /* Siemens PCP. */ +#define EM_NCPU 56 /* Sony nCPU. */ +#define EM_NDR1 57 /* Denso NDR1 microprocessor. */ +#define EM_STARCORE 58 /* Motorola Star*Core processor. */ +#define EM_ME16 59 /* Toyota ME16 processor. */ +#define EM_ST100 60 /* STMicroelectronics ST100 processor. */ +#define EM_TINYJ 61 /* Advanced Logic Corp. TinyJ processor. */ +#define EM_X86_64 62 /* Advanced Micro Devices x86-64 */ +#define EM_AMD64 EM_X86_64 /* Advanced Micro Devices x86-64 (compat) */ +#define EM_PDSP 63 /* Sony DSP Processor. */ +#define EM_FX66 66 /* Siemens FX66 microcontroller. */ +#define EM_ST9PLUS 67 /* STMicroelectronics ST9+ 8/16 + microcontroller. */ +#define EM_ST7 68 /* STmicroelectronics ST7 8-bit + microcontroller. */ +#define EM_68HC16 69 /* Motorola MC68HC16 microcontroller. */ +#define EM_68HC11 70 /* Motorola MC68HC11 microcontroller. */ +#define EM_68HC08 71 /* Motorola MC68HC08 microcontroller. */ +#define EM_68HC05 72 /* Motorola MC68HC05 microcontroller. */ +#define EM_SVX 73 /* Silicon Graphics SVx. */ +#define EM_ST19 74 /* STMicroelectronics ST19 8-bit mc. */ +#define EM_VAX 75 /* Digital VAX. */ +#define EM_CRIS 76 /* Axis Communications 32-bit embedded + processor. */ +#define EM_JAVELIN 77 /* Infineon Technologies 32-bit embedded + processor. */ +#define EM_FIREPATH 78 /* Element 14 64-bit DSP Processor. */ +#define EM_ZSP 79 /* LSI Logic 16-bit DSP Processor. */ +#define EM_MMIX 80 /* Donald Knuth's educational 64-bit proc. */ +#define EM_HUANY 81 /* Harvard University machine-independent + object files. */ +#define EM_PRISM 82 /* SiTera Prism. */ +#define EM_AVR 83 /* Atmel AVR 8-bit microcontroller. */ +#define EM_FR30 84 /* Fujitsu FR30. */ +#define EM_D10V 85 /* Mitsubishi D10V. */ +#define EM_D30V 86 /* Mitsubishi D30V. */ +#define EM_V850 87 /* NEC v850. */ +#define EM_M32R 88 /* Mitsubishi M32R. */ +#define EM_MN10300 89 /* Matsushita MN10300. */ +#define EM_MN10200 90 /* Matsushita MN10200. */ +#define EM_PJ 91 /* picoJava. */ +#define EM_OPENRISC 92 /* OpenRISC 32-bit embedded processor. */ +#define EM_ARC_A5 93 /* ARC Cores Tangent-A5. */ +#define EM_XTENSA 94 /* Tensilica Xtensa Architecture. */ +#define EM_VIDEOCORE 95 /* Alphamosaic VideoCore processor. */ +#define EM_TMM_GPP 96 /* Thompson Multimedia General Purpose + Processor. */ +#define EM_NS32K 97 /* National Semiconductor 32000 series. */ +#define EM_TPC 98 /* Tenor Network TPC processor. */ +#define EM_SNP1K 99 /* Trebia SNP 1000 processor. */ +#define EM_ST200 100 /* STMicroelectronics ST200 microcontroller. */ +#define EM_IP2K 101 /* Ubicom IP2xxx microcontroller family. */ +#define EM_MAX 102 /* MAX Processor. */ +#define EM_CR 103 /* National Semiconductor CompactRISC + microprocessor. */ +#define EM_F2MC16 104 /* Fujitsu F2MC16. */ +#define EM_MSP430 105 /* Texas Instruments embedded microcontroller + msp430. */ +#define EM_BLACKFIN 106 /* Analog Devices Blackfin (DSP) processor. */ +#define EM_SE_C33 107 /* S1C33 Family of Seiko Epson processors. */ +#define EM_SEP 108 /* Sharp embedded microprocessor. */ +#define EM_ARCA 109 /* Arca RISC Microprocessor. */ +#define EM_UNICORE 110 /* Microprocessor series from PKU-Unity Ltd. + and MPRC of Peking University */ +#define EM_AARCH64 183 /* AArch64 (64-bit ARM) */ + +/* Non-standard or deprecated. */ +#define EM_486 6 /* Intel i486. */ +#define EM_MIPS_RS4_BE 10 /* MIPS R4000 Big-Endian */ +#define EM_ALPHA_STD 41 /* Digital Alpha (standard value). */ +#define EM_ALPHA 0x9026 /* Alpha (written in the absence of an ABI) */ + +/* e_flags for EM_ARM */ +#define EF_ARM_ABI_VERSION 0x05000000 /* ABI version 5 */ +#define EF_ARM_ABIMASK 0xFF000000 +#define EF_ARM_BE8 0x00800000 +#define EF_ARM_ABI_FLOAT_HARD 0x00000400 /* ABI version 5 and later */ +#define EF_ARM_ABI_FLOAT_SOFT 0x00000200 /* ABI version 5 and later */ + +/* Special section indexes. */ +#define SHN_UNDEF 0 /* Undefined, missing, irrelevant. */ +#define SHN_LORESERVE 0xff00 /* First of reserved range. */ +#define SHN_LOPROC 0xff00 /* First processor-specific. */ +#define SHN_HIPROC 0xff1f /* Last processor-specific. */ +#define SHN_LOOS 0xff20 /* First operating system-specific. */ +#define SHN_HIOS 0xff3f /* Last operating system-specific. */ +#define SHN_ABS 0xfff1 /* Absolute values. */ +#define SHN_COMMON 0xfff2 /* Common data. */ +#define SHN_XINDEX 0xffff /* Escape -- index stored elsewhere. */ +#define SHN_HIRESERVE 0xffff /* Last of reserved range. */ + +/* sh_type */ +#define SHT_NULL 0 /* inactive */ +#define SHT_PROGBITS 1 /* program defined information */ +#define SHT_SYMTAB 2 /* symbol table section */ +#define SHT_STRTAB 3 /* string table section */ +#define SHT_RELA 4 /* relocation section with addends */ +#define SHT_HASH 5 /* symbol hash table section */ +#define SHT_DYNAMIC 6 /* dynamic section */ +#define SHT_NOTE 7 /* note section */ +#define SHT_NOBITS 8 /* no space section */ +#define SHT_REL 9 /* relocation section - no addends */ +#define SHT_SHLIB 10 /* reserved - purpose unknown */ +#define SHT_DYNSYM 11 /* dynamic symbol table section */ +#define SHT_INIT_ARRAY 14 /* Initialization function pointers. */ +#define SHT_FINI_ARRAY 15 /* Termination function pointers. */ +#define SHT_PREINIT_ARRAY 16 /* Pre-initialization function ptrs. */ +#define SHT_GROUP 17 /* Section group. */ +#define SHT_SYMTAB_SHNDX 18 /* Section indexes (see SHN_XINDEX). */ +#define SHT_LOOS 0x60000000 /* First of OS specific semantics */ +#define SHT_LOSUNW 0x6ffffff4 +#define SHT_SUNW_dof 0x6ffffff4 +#define SHT_SUNW_cap 0x6ffffff5 +#define SHT_SUNW_SIGNATURE 0x6ffffff6 +#define SHT_GNU_HASH 0x6ffffff6 +#define SHT_GNU_LIBLIST 0x6ffffff7 +#define SHT_SUNW_ANNOTATE 0x6ffffff7 +#define SHT_SUNW_DEBUGSTR 0x6ffffff8 +#define SHT_SUNW_DEBUG 0x6ffffff9 +#define SHT_SUNW_move 0x6ffffffa +#define SHT_SUNW_COMDAT 0x6ffffffb +#define SHT_SUNW_syminfo 0x6ffffffc +#define SHT_SUNW_verdef 0x6ffffffd +#define SHT_GNU_verdef 0x6ffffffd /* Symbol versions provided */ +#define SHT_SUNW_verneed 0x6ffffffe +#define SHT_GNU_verneed 0x6ffffffe /* Symbol versions required */ +#define SHT_SUNW_versym 0x6fffffff +#define SHT_GNU_versym 0x6fffffff /* Symbol version table */ +#define SHT_HISUNW 0x6fffffff +#define SHT_HIOS 0x6fffffff /* Last of OS specific semantics */ +#define SHT_LOPROC 0x70000000 /* reserved range for processor */ +#define SHT_AMD64_UNWIND 0x70000001 /* unwind information */ +#define SHT_ARM_EXIDX 0x70000001 /* Exception index table. */ +#define SHT_ARM_PREEMPTMAP 0x70000002 /* BPABI DLL dynamic linking + pre-emption map. */ +#define SHT_ARM_ATTRIBUTES 0x70000003 /* Object file compatibility + attributes. */ +#define SHT_ARM_DEBUGOVERLAY 0x70000004 /* See DBGOVL for details. */ +#define SHT_ARM_OVERLAYSECTION 0x70000005 /* See DBGOVL for details. */ +#define SHT_MIPS_REGINFO 0x70000006 +#define SHT_MIPS_OPTIONS 0x7000000d +#define SHT_MIPS_DWARF 0x7000001e /* MIPS gcc uses MIPS_DWARF */ +#define SHT_HIPROC 0x7fffffff /* specific section header types */ +#define SHT_LOUSER 0x80000000 /* reserved range for application */ +#define SHT_HIUSER 0xffffffff /* specific indexes */ + +/* Flags for sh_flags. */ +#define SHF_WRITE 0x1 /* Section contains writable data. */ +#define SHF_ALLOC 0x2 /* Section occupies memory. */ +#define SHF_EXECINSTR 0x4 /* Section contains instructions. */ +#define SHF_MERGE 0x10 /* Section may be merged. */ +#define SHF_STRINGS 0x20 /* Section contains strings. */ +#define SHF_INFO_LINK 0x40 /* sh_info holds section index. */ +#define SHF_LINK_ORDER 0x80 /* Special ordering requirements. */ +#define SHF_OS_NONCONFORMING 0x100 /* OS-specific processing required. */ +#define SHF_GROUP 0x200 /* Member of section group. */ +#define SHF_TLS 0x400 /* Section contains TLS data. */ +#define SHF_MASKOS 0x0ff00000 /* OS-specific semantics. */ +#define SHF_MASKPROC 0xf0000000 /* Processor-specific semantics. */ + +/* Values for p_type. */ +#define PT_NULL 0 /* Unused entry. */ +#define PT_LOAD 1 /* Loadable segment. */ +#define PT_DYNAMIC 2 /* Dynamic linking information segment. */ +#define PT_INTERP 3 /* Pathname of interpreter. */ +#define PT_NOTE 4 /* Auxiliary information. */ +#define PT_SHLIB 5 /* Reserved (not used). */ +#define PT_PHDR 6 /* Location of program header itself. */ +#define PT_TLS 7 /* Thread local storage segment */ +#define PT_LOOS 0x60000000 /* First OS-specific. */ +#define PT_SUNW_UNWIND 0x6464e550 /* amd64 UNWIND program header */ +#define PT_GNU_EH_FRAME 0x6474e550 +#define PT_GNU_STACK 0x6474e551 +#define PT_GNU_RELRO 0x6474e552 +#define PT_LOSUNW 0x6ffffffa +#define PT_SUNWBSS 0x6ffffffa /* Sun Specific segment */ +#define PT_SUNWSTACK 0x6ffffffb /* describes the stack segment */ +#define PT_SUNWDTRACE 0x6ffffffc /* private */ +#define PT_SUNWCAP 0x6ffffffd /* hard/soft capabilities segment */ +#define PT_HISUNW 0x6fffffff +#define PT_HIOS 0x6fffffff /* Last OS-specific. */ +#define PT_LOPROC 0x70000000 /* First processor-specific type. */ +#define PT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for p_flags. */ +#define PF_X 0x1 /* Executable. */ +#define PF_W 0x2 /* Writable. */ +#define PF_R 0x4 /* Readable. */ +#define PF_MASKOS 0x0ff00000 /* Operating system-specific. */ +#define PF_MASKPROC 0xf0000000 /* Processor-specific. */ + +/* Extended program header index. */ +#define PN_XNUM 0xffff + +/* Values for d_tag. */ +#define DT_NULL 0 /* Terminating entry. */ +#define DT_NEEDED 1 /* String table offset of a needed shared + library. */ +#define DT_PLTRELSZ 2 /* Total size in bytes of PLT relocations. */ +#define DT_PLTGOT 3 /* Processor-dependent address. */ +#define DT_HASH 4 /* Address of symbol hash table. */ +#define DT_STRTAB 5 /* Address of string table. */ +#define DT_SYMTAB 6 /* Address of symbol table. */ +#define DT_RELA 7 /* Address of ElfNN_Rela relocations. */ +#define DT_RELASZ 8 /* Total size of ElfNN_Rela relocations. */ +#define DT_RELAENT 9 /* Size of each ElfNN_Rela relocation entry. */ +#define DT_STRSZ 10 /* Size of string table. */ +#define DT_SYMENT 11 /* Size of each symbol table entry. */ +#define DT_INIT 12 /* Address of initialization function. */ +#define DT_FINI 13 /* Address of finalization function. */ +#define DT_SONAME 14 /* String table offset of shared object + name. */ +#define DT_RPATH 15 /* String table offset of library path. [sup] */ +#define DT_SYMBOLIC 16 /* Indicates "symbolic" linking. [sup] */ +#define DT_REL 17 /* Address of ElfNN_Rel relocations. */ +#define DT_RELSZ 18 /* Total size of ElfNN_Rel relocations. */ +#define DT_RELENT 19 /* Size of each ElfNN_Rel relocation. */ +#define DT_PLTREL 20 /* Type of relocation used for PLT. */ +#define DT_DEBUG 21 /* Reserved (not used). */ +#define DT_TEXTREL 22 /* Indicates there may be relocations in + non-writable segments. [sup] */ +#define DT_JMPREL 23 /* Address of PLT relocations. */ +#define DT_BIND_NOW 24 /* [sup] */ +#define DT_INIT_ARRAY 25 /* Address of the array of pointers to + initialization functions */ +#define DT_FINI_ARRAY 26 /* Address of the array of pointers to + termination functions */ +#define DT_INIT_ARRAYSZ 27 /* Size in bytes of the array of + initialization functions. */ +#define DT_FINI_ARRAYSZ 28 /* Size in bytes of the array of + termination functions. */ +#define DT_RUNPATH 29 /* String table offset of a null-terminated + library search path string. */ +#define DT_FLAGS 30 /* Object specific flag values. */ +#define DT_ENCODING 32 /* Values greater than or equal to DT_ENCODING + and less than DT_LOOS follow the rules for + the interpretation of the d_un union + as follows: even == 'd_ptr', odd == 'd_val' + or none */ +#define DT_PREINIT_ARRAY 32 /* Address of the array of pointers to + pre-initialization functions. */ +#define DT_PREINIT_ARRAYSZ 33 /* Size in bytes of the array of + pre-initialization functions. */ +#define DT_MAXPOSTAGS 34 /* number of positive tags */ +#define DT_LOOS 0x6000000d /* First OS-specific */ +#define DT_SUNW_AUXILIARY 0x6000000d /* symbol auxiliary name */ +#define DT_SUNW_RTLDINF 0x6000000e /* ld.so.1 info (private) */ +#define DT_SUNW_FILTER 0x6000000f /* symbol filter name */ +#define DT_SUNW_CAP 0x60000010 /* hardware/software */ +#define DT_HIOS 0x6ffff000 /* Last OS-specific */ + +/* + * DT_* entries which fall between DT_VALRNGHI & DT_VALRNGLO use the + * Dyn.d_un.d_val field of the Elf*_Dyn structure. + */ +#define DT_VALRNGLO 0x6ffffd00 +#define DT_CHECKSUM 0x6ffffdf8 /* elf checksum */ +#define DT_PLTPADSZ 0x6ffffdf9 /* pltpadding size */ +#define DT_MOVEENT 0x6ffffdfa /* move table entry size */ +#define DT_MOVESZ 0x6ffffdfb /* move table size */ +#define DT_FEATURE_1 0x6ffffdfc /* feature holder */ +#define DT_POSFLAG_1 0x6ffffdfd /* flags for DT_* entries, effecting */ + /* the following DT_* entry. */ + /* See DF_P1_* definitions */ +#define DT_SYMINSZ 0x6ffffdfe /* syminfo table size (in bytes) */ +#define DT_SYMINENT 0x6ffffdff /* syminfo entry size (in bytes) */ +#define DT_VALRNGHI 0x6ffffdff + +/* + * DT_* entries which fall between DT_ADDRRNGHI & DT_ADDRRNGLO use the + * Dyn.d_un.d_ptr field of the Elf*_Dyn structure. + * + * If any adjustment is made to the ELF object after it has been + * built, these entries will need to be adjusted. + */ +#define DT_ADDRRNGLO 0x6ffffe00 +#define DT_GNU_HASH 0x6ffffef5 /* GNU-style hash table */ +#define DT_CONFIG 0x6ffffefa /* configuration information */ +#define DT_DEPAUDIT 0x6ffffefb /* dependency auditing */ +#define DT_AUDIT 0x6ffffefc /* object auditing */ +#define DT_PLTPAD 0x6ffffefd /* pltpadding (sparcv9) */ +#define DT_MOVETAB 0x6ffffefe /* move table */ +#define DT_SYMINFO 0x6ffffeff /* syminfo table */ +#define DT_ADDRRNGHI 0x6ffffeff + +#define DT_VERSYM 0x6ffffff0 /* Address of versym section. */ +#define DT_RELACOUNT 0x6ffffff9 /* number of RELATIVE relocations */ +#define DT_RELCOUNT 0x6ffffffa /* number of RELATIVE relocations */ +#define DT_FLAGS_1 0x6ffffffb /* state flags - see DF_1_* defs */ +#define DT_VERDEF 0x6ffffffc /* Address of verdef section. */ +#define DT_VERDEFNUM 0x6ffffffd /* Number of elems in verdef section */ +#define DT_VERNEED 0x6ffffffe /* Address of verneed section. */ +#define DT_VERNEEDNUM 0x6fffffff /* Number of elems in verneed section */ + +#define DT_LOPROC 0x70000000 /* First processor-specific type. */ +#define DT_DEPRECATED_SPARC_REGISTER 0x7000001 +#define DT_AUXILIARY 0x7ffffffd /* shared library auxiliary name */ +#define DT_USED 0x7ffffffe /* ignored - same as needed */ +#define DT_FILTER 0x7fffffff /* shared library filter name */ +#define DT_HIPROC 0x7fffffff /* Last processor-specific type. */ + +/* Values for DT_FLAGS */ +#define DF_ORIGIN 0x0001 /* Indicates that the object being loaded may + make reference to the $ORIGIN substitution + string */ +#define DF_SYMBOLIC 0x0002 /* Indicates "symbolic" linking. */ +#define DF_TEXTREL 0x0004 /* Indicates there may be relocations in + non-writable segments. */ +#define DF_BIND_NOW 0x0008 /* Indicates that the dynamic linker should + process all relocations for the object + containing this entry before transferring + control to the program. */ +#define DF_STATIC_TLS 0x0010 /* Indicates that the shared object or + executable contains code using a static + thread-local storage scheme. */ + +/* Values for DT_FLAGS_1 */ +#define DF_1_BIND_NOW 0x00000001 /* Same as DF_BIND_NOW */ +#define DF_1_GLOBAL 0x00000002 /* Set the RTLD_GLOBAL for object */ +#define DF_1_NODELETE 0x00000008 /* Set the RTLD_NODELETE for object */ +#define DF_1_LOADFLTR 0x00000010 /* Immediate loading of filtees */ +#define DF_1_NOOPEN 0x00000040 /* Do not allow loading on dlopen() */ +#define DF_1_ORIGIN 0x00000080 /* Process $ORIGIN */ +#define DF_1_INTERPOSE 0x00000400 /* Interpose all objects but main */ +#define DF_1_NODEFLIB 0x00000800 /* Do not search default paths */ + +/* Values for n_type. Used in core files. */ +#define NT_PRSTATUS 1 /* Process status. */ +#define NT_FPREGSET 2 /* Floating point registers. */ +#define NT_PRPSINFO 3 /* Process state info. */ +#define NT_THRMISC 7 /* Thread miscellaneous info. */ +#define NT_PROCSTAT_PROC 8 /* Procstat proc data. */ +#define NT_PROCSTAT_FILES 9 /* Procstat files data. */ +#define NT_PROCSTAT_VMMAP 10 /* Procstat vmmap data. */ +#define NT_PROCSTAT_GROUPS 11 /* Procstat groups data. */ +#define NT_PROCSTAT_UMASK 12 /* Procstat umask data. */ +#define NT_PROCSTAT_RLIMIT 13 /* Procstat rlimit data. */ +#define NT_PROCSTAT_OSREL 14 /* Procstat osreldate data. */ +#define NT_PROCSTAT_PSSTRINGS 15 /* Procstat ps_strings data. */ +#define NT_PROCSTAT_AUXV 16 /* Procstat auxv data. */ + +/* Symbol Binding - ELFNN_ST_BIND - st_info */ +#define STB_LOCAL 0 /* Local symbol */ +#define STB_GLOBAL 1 /* Global symbol */ +#define STB_WEAK 2 /* like global - lower precedence */ +#define STB_LOOS 10 /* Reserved range for operating system */ +#define STB_HIOS 12 /* specific semantics. */ +#define STB_LOPROC 13 /* reserved range for processor */ +#define STB_HIPROC 15 /* specific semantics. */ + +/* Symbol type - ELFNN_ST_TYPE - st_info */ +#define STT_NOTYPE 0 /* Unspecified type. */ +#define STT_OBJECT 1 /* Data object. */ +#define STT_FUNC 2 /* Function. */ +#define STT_SECTION 3 /* Section. */ +#define STT_FILE 4 /* Source file. */ +#define STT_COMMON 5 /* Uninitialized common block. */ +#define STT_TLS 6 /* TLS object. */ +#define STT_NUM 7 +#define STT_LOOS 10 /* Reserved range for operating system */ +#define STT_GNU_IFUNC 10 +#define STT_HIOS 12 /* specific semantics. */ +#define STT_LOPROC 13 /* reserved range for processor */ +#define STT_HIPROC 15 /* specific semantics. */ + +/* Symbol visibility - ELFNN_ST_VISIBILITY - st_other */ +#define STV_DEFAULT 0x0 /* Default visibility (see binding). */ +#define STV_INTERNAL 0x1 /* Special meaning in relocatable objects. */ +#define STV_HIDDEN 0x2 /* Not visible. */ +#define STV_PROTECTED 0x3 /* Visible but not preemptible. */ +#define STV_EXPORTED 0x4 +#define STV_SINGLETON 0x5 +#define STV_ELIMINATE 0x6 + +/* Special symbol table indexes. */ +#define STN_UNDEF 0 /* Undefined symbol index. */ + +/* Symbol versioning flags. */ +#define VER_DEF_CURRENT 1 +#define VER_DEF_IDX(x) VER_NDX(x) + +#define VER_FLG_BASE 0x01 +#define VER_FLG_WEAK 0x02 + +#define VER_NEED_CURRENT 1 +#define VER_NEED_WEAK (1u << 15) +#define VER_NEED_HIDDEN VER_NDX_HIDDEN +#define VER_NEED_IDX(x) VER_NDX(x) + +#define VER_NDX_LOCAL 0 +#define VER_NDX_GLOBAL 1 +#define VER_NDX_GIVEN 2 + +#define VER_NDX_HIDDEN (1u << 15) +#define VER_NDX(x) ((x) & ~(1u << 15)) + +#define CA_SUNW_NULL 0 +#define CA_SUNW_HW_1 1 /* first hardware capabilities entry */ +#define CA_SUNW_SF_1 2 /* first software capabilities entry */ + +/* + * Syminfo flag values + */ +#define SYMINFO_FLG_DIRECT 0x0001 /* symbol ref has direct association */ + /* to object containing defn. */ +#define SYMINFO_FLG_PASSTHRU 0x0002 /* ignored - see SYMINFO_FLG_FILTER */ +#define SYMINFO_FLG_COPY 0x0004 /* symbol is a copy-reloc */ +#define SYMINFO_FLG_LAZYLOAD 0x0008 /* object containing defn should be */ + /* lazily-loaded */ +#define SYMINFO_FLG_DIRECTBIND 0x0010 /* ref should be bound directly to */ + /* object containing defn. */ +#define SYMINFO_FLG_NOEXTDIRECT 0x0020 /* don't let an external reference */ + /* directly bind to this symbol */ +#define SYMINFO_FLG_FILTER 0x0002 /* symbol ref is associated to a */ +#define SYMINFO_FLG_AUXILIARY 0x0040 /* standard or auxiliary filter */ + +/* + * Syminfo.si_boundto values. + */ +#define SYMINFO_BT_SELF 0xffff /* symbol bound to self */ +#define SYMINFO_BT_PARENT 0xfffe /* symbol bound to parent */ +#define SYMINFO_BT_NONE 0xfffd /* no special symbol binding */ +#define SYMINFO_BT_EXTERN 0xfffc /* symbol defined as external */ +#define SYMINFO_BT_LOWRESERVE 0xff00 /* beginning of reserved entries */ + +/* + * Syminfo version values. + */ +#define SYMINFO_NONE 0 /* Syminfo version */ +#define SYMINFO_CURRENT 1 +#define SYMINFO_NUM 2 + +/* + * Relocation types. + * + * All machine architectures are defined here to allow tools on one to + * handle others. + */ + +#define R_386_NONE 0 /* No relocation. */ +#define R_386_32 1 /* Add symbol value. */ +#define R_386_PC32 2 /* Add PC-relative symbol value. */ +#define R_386_GOT32 3 /* Add PC-relative GOT offset. */ +#define R_386_PLT32 4 /* Add PC-relative PLT offset. */ +#define R_386_COPY 5 /* Copy data from shared object. */ +#define R_386_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_386_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_386_RELATIVE 8 /* Add load address of shared object. */ +#define R_386_GOTOFF 9 /* Add GOT-relative symbol address. */ +#define R_386_GOTPC 10 /* Add PC-relative GOT table address. */ +#define R_386_TLS_TPOFF 14 /* Negative offset in static TLS block */ +#define R_386_TLS_IE 15 /* Absolute address of GOT for -ve static TLS */ +#define R_386_TLS_GOTIE 16 /* GOT entry for negative static TLS block */ +#define R_386_TLS_LE 17 /* Negative offset relative to static TLS */ +#define R_386_TLS_GD 18 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_LDM 19 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_GD_32 24 /* 32 bit offset to GOT (index,off) pair */ +#define R_386_TLS_GD_PUSH 25 /* pushl instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_CALL 26 /* call instruction for Sun ABI GD sequence */ +#define R_386_TLS_GD_POP 27 /* popl instruction for Sun ABI GD sequence */ +#define R_386_TLS_LDM_32 28 /* 32 bit offset to GOT (index,zero) pair */ +#define R_386_TLS_LDM_PUSH 29 /* pushl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_CALL 30 /* call instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDM_POP 31 /* popl instruction for Sun ABI LD sequence */ +#define R_386_TLS_LDO_32 32 /* 32 bit offset from start of TLS block */ +#define R_386_TLS_IE_32 33 /* 32 bit offset to GOT static TLS offset entry */ +#define R_386_TLS_LE_32 34 /* 32 bit offset within static TLS block */ +#define R_386_TLS_DTPMOD32 35 /* GOT entry containing TLS index */ +#define R_386_TLS_DTPOFF32 36 /* GOT entry containing TLS offset */ +#define R_386_TLS_TPOFF32 37 /* GOT entry of -ve static TLS offset */ +#define R_386_IRELATIVE 42 /* PLT entry resolved indirectly at runtime */ + +#define R_AARCH64_RELATIVE 1027 + +#define R_ARM_NONE 0 /* No relocation. */ +#define R_ARM_PC24 1 +#define R_ARM_ABS32 2 +#define R_ARM_REL32 3 +#define R_ARM_PC13 4 +#define R_ARM_ABS16 5 +#define R_ARM_ABS12 6 +#define R_ARM_THM_ABS5 7 +#define R_ARM_ABS8 8 +#define R_ARM_SBREL32 9 +#define R_ARM_THM_PC22 10 +#define R_ARM_THM_PC8 11 +#define R_ARM_AMP_VCALL9 12 +#define R_ARM_SWI24 13 +#define R_ARM_THM_SWI8 14 +#define R_ARM_XPC25 15 +#define R_ARM_THM_XPC22 16 +/* TLS relocations */ +#define R_ARM_TLS_DTPMOD32 17 /* ID of module containing symbol */ +#define R_ARM_TLS_DTPOFF32 18 /* Offset in TLS block */ +#define R_ARM_TLS_TPOFF32 19 /* Offset in static TLS block */ +#define R_ARM_COPY 20 /* Copy data from shared object. */ +#define R_ARM_GLOB_DAT 21 /* Set GOT entry to data address. */ +#define R_ARM_JUMP_SLOT 22 /* Set GOT entry to code address. */ +#define R_ARM_RELATIVE 23 /* Add load address of shared object. */ +#define R_ARM_GOTOFF 24 /* Add GOT-relative symbol address. */ +#define R_ARM_GOTPC 25 /* Add PC-relative GOT table address. */ +#define R_ARM_GOT32 26 /* Add PC-relative GOT offset. */ +#define R_ARM_PLT32 27 /* Add PC-relative PLT offset. */ +#define R_ARM_GNU_VTENTRY 100 +#define R_ARM_GNU_VTINHERIT 101 +#define R_ARM_RSBREL32 250 +#define R_ARM_THM_RPC22 251 +#define R_ARM_RREL32 252 +#define R_ARM_RABS32 253 +#define R_ARM_RPC24 254 +#define R_ARM_RBASE 255 + +/* Name Value Field Calculation */ +#define R_IA_64_NONE 0 /* None */ +#define R_IA_64_IMM14 0x21 /* immediate14 S + A */ +#define R_IA_64_IMM22 0x22 /* immediate22 S + A */ +#define R_IA_64_IMM64 0x23 /* immediate64 S + A */ +#define R_IA_64_DIR32MSB 0x24 /* word32 MSB S + A */ +#define R_IA_64_DIR32LSB 0x25 /* word32 LSB S + A */ +#define R_IA_64_DIR64MSB 0x26 /* word64 MSB S + A */ +#define R_IA_64_DIR64LSB 0x27 /* word64 LSB S + A */ +#define R_IA_64_GPREL22 0x2a /* immediate22 @gprel(S + A) */ +#define R_IA_64_GPREL64I 0x2b /* immediate64 @gprel(S + A) */ +#define R_IA_64_GPREL32MSB 0x2c /* word32 MSB @gprel(S + A) */ +#define R_IA_64_GPREL32LSB 0x2d /* word32 LSB @gprel(S + A) */ +#define R_IA_64_GPREL64MSB 0x2e /* word64 MSB @gprel(S + A) */ +#define R_IA_64_GPREL64LSB 0x2f /* word64 LSB @gprel(S + A) */ +#define R_IA_64_LTOFF22 0x32 /* immediate22 @ltoff(S + A) */ +#define R_IA_64_LTOFF64I 0x33 /* immediate64 @ltoff(S + A) */ +#define R_IA_64_PLTOFF22 0x3a /* immediate22 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64I 0x3b /* immediate64 @pltoff(S + A) */ +#define R_IA_64_PLTOFF64MSB 0x3e /* word64 MSB @pltoff(S + A) */ +#define R_IA_64_PLTOFF64LSB 0x3f /* word64 LSB @pltoff(S + A) */ +#define R_IA_64_FPTR64I 0x43 /* immediate64 @fptr(S + A) */ +#define R_IA_64_FPTR32MSB 0x44 /* word32 MSB @fptr(S + A) */ +#define R_IA_64_FPTR32LSB 0x45 /* word32 LSB @fptr(S + A) */ +#define R_IA_64_FPTR64MSB 0x46 /* word64 MSB @fptr(S + A) */ +#define R_IA_64_FPTR64LSB 0x47 /* word64 LSB @fptr(S + A) */ +#define R_IA_64_PCREL60B 0x48 /* immediate60 form1 S + A - P */ +#define R_IA_64_PCREL21B 0x49 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL21M 0x4a /* immediate21 form2 S + A - P */ +#define R_IA_64_PCREL21F 0x4b /* immediate21 form3 S + A - P */ +#define R_IA_64_PCREL32MSB 0x4c /* word32 MSB S + A - P */ +#define R_IA_64_PCREL32LSB 0x4d /* word32 LSB S + A - P */ +#define R_IA_64_PCREL64MSB 0x4e /* word64 MSB S + A - P */ +#define R_IA_64_PCREL64LSB 0x4f /* word64 LSB S + A - P */ +#define R_IA_64_LTOFF_FPTR22 0x52 /* immediate22 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64I 0x53 /* immediate64 @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32MSB 0x54 /* word32 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR32LSB 0x55 /* word32 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64MSB 0x56 /* word64 MSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_LTOFF_FPTR64LSB 0x57 /* word64 LSB @ltoff(@fptr(S + A)) */ +#define R_IA_64_SEGREL32MSB 0x5c /* word32 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL32LSB 0x5d /* word32 LSB @segrel(S + A) */ +#define R_IA_64_SEGREL64MSB 0x5e /* word64 MSB @segrel(S + A) */ +#define R_IA_64_SEGREL64LSB 0x5f /* word64 LSB @segrel(S + A) */ +#define R_IA_64_SECREL32MSB 0x64 /* word32 MSB @secrel(S + A) */ +#define R_IA_64_SECREL32LSB 0x65 /* word32 LSB @secrel(S + A) */ +#define R_IA_64_SECREL64MSB 0x66 /* word64 MSB @secrel(S + A) */ +#define R_IA_64_SECREL64LSB 0x67 /* word64 LSB @secrel(S + A) */ +#define R_IA_64_REL32MSB 0x6c /* word32 MSB BD + A */ +#define R_IA_64_REL32LSB 0x6d /* word32 LSB BD + A */ +#define R_IA_64_REL64MSB 0x6e /* word64 MSB BD + A */ +#define R_IA_64_REL64LSB 0x6f /* word64 LSB BD + A */ +#define R_IA_64_LTV32MSB 0x74 /* word32 MSB S + A */ +#define R_IA_64_LTV32LSB 0x75 /* word32 LSB S + A */ +#define R_IA_64_LTV64MSB 0x76 /* word64 MSB S + A */ +#define R_IA_64_LTV64LSB 0x77 /* word64 LSB S + A */ +#define R_IA_64_PCREL21BI 0x79 /* immediate21 form1 S + A - P */ +#define R_IA_64_PCREL22 0x7a /* immediate22 S + A - P */ +#define R_IA_64_PCREL64I 0x7b /* immediate64 S + A - P */ +#define R_IA_64_IPLTMSB 0x80 /* function descriptor MSB special */ +#define R_IA_64_IPLTLSB 0x81 /* function descriptor LSB speciaal */ +#define R_IA_64_SUB 0x85 /* immediate64 A - S */ +#define R_IA_64_LTOFF22X 0x86 /* immediate22 special */ +#define R_IA_64_LDXMOV 0x87 /* immediate22 special */ +#define R_IA_64_TPREL14 0x91 /* imm14 @tprel(S + A) */ +#define R_IA_64_TPREL22 0x92 /* imm22 @tprel(S + A) */ +#define R_IA_64_TPREL64I 0x93 /* imm64 @tprel(S + A) */ +#define R_IA_64_TPREL64MSB 0x96 /* word64 MSB @tprel(S + A) */ +#define R_IA_64_TPREL64LSB 0x97 /* word64 LSB @tprel(S + A) */ +#define R_IA_64_LTOFF_TPREL22 0x9a /* imm22 @ltoff(@tprel(S+A)) */ +#define R_IA_64_DTPMOD64MSB 0xa6 /* word64 MSB @dtpmod(S + A) */ +#define R_IA_64_DTPMOD64LSB 0xa7 /* word64 LSB @dtpmod(S + A) */ +#define R_IA_64_LTOFF_DTPMOD22 0xaa /* imm22 @ltoff(@dtpmod(S+A)) */ +#define R_IA_64_DTPREL14 0xb1 /* imm14 @dtprel(S + A) */ +#define R_IA_64_DTPREL22 0xb2 /* imm22 @dtprel(S + A) */ +#define R_IA_64_DTPREL64I 0xb3 /* imm64 @dtprel(S + A) */ +#define R_IA_64_DTPREL32MSB 0xb4 /* word32 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL32LSB 0xb5 /* word32 LSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64MSB 0xb6 /* word64 MSB @dtprel(S + A) */ +#define R_IA_64_DTPREL64LSB 0xb7 /* word64 LSB @dtprel(S + A) */ +#define R_IA_64_LTOFF_DTPREL22 0xba /* imm22 @ltoff(@dtprel(S+A)) */ + +#define R_MIPS_NONE 0 /* No reloc */ +#define R_MIPS_16 1 /* Direct 16 bit */ +#define R_MIPS_32 2 /* Direct 32 bit */ +#define R_MIPS_REL32 3 /* PC relative 32 bit */ +#define R_MIPS_26 4 /* Direct 26 bit shifted */ +#define R_MIPS_HI16 5 /* High 16 bit */ +#define R_MIPS_LO16 6 /* Low 16 bit */ +#define R_MIPS_GPREL16 7 /* GP relative 16 bit */ +#define R_MIPS_LITERAL 8 /* 16 bit literal entry */ +#define R_MIPS_GOT16 9 /* 16 bit GOT entry */ +#define R_MIPS_PC16 10 /* PC relative 16 bit */ +#define R_MIPS_CALL16 11 /* 16 bit GOT entry for function */ +#define R_MIPS_GPREL32 12 /* GP relative 32 bit */ +#define R_MIPS_64 18 /* Direct 64 bit */ +#define R_MIPS_GOTHI16 21 /* GOT HI 16 bit */ +#define R_MIPS_GOTLO16 22 /* GOT LO 16 bit */ +#define R_MIPS_CALLHI16 30 /* upper 16 bit GOT entry for function */ +#define R_MIPS_CALLLO16 31 /* lower 16 bit GOT entry for function */ + +#define R_PPC_NONE 0 /* No relocation. */ +#define R_PPC_ADDR32 1 +#define R_PPC_ADDR24 2 +#define R_PPC_ADDR16 3 +#define R_PPC_ADDR16_LO 4 +#define R_PPC_ADDR16_HI 5 +#define R_PPC_ADDR16_HA 6 +#define R_PPC_ADDR14 7 +#define R_PPC_ADDR14_BRTAKEN 8 +#define R_PPC_ADDR14_BRNTAKEN 9 +#define R_PPC_REL24 10 +#define R_PPC_REL14 11 +#define R_PPC_REL14_BRTAKEN 12 +#define R_PPC_REL14_BRNTAKEN 13 +#define R_PPC_GOT16 14 +#define R_PPC_GOT16_LO 15 +#define R_PPC_GOT16_HI 16 +#define R_PPC_GOT16_HA 17 +#define R_PPC_PLTREL24 18 +#define R_PPC_COPY 19 +#define R_PPC_GLOB_DAT 20 +#define R_PPC_JMP_SLOT 21 +#define R_PPC_RELATIVE 22 +#define R_PPC_LOCAL24PC 23 +#define R_PPC_UADDR32 24 +#define R_PPC_UADDR16 25 +#define R_PPC_REL32 26 +#define R_PPC_PLT32 27 +#define R_PPC_PLTREL32 28 +#define R_PPC_PLT16_LO 29 +#define R_PPC_PLT16_HI 30 +#define R_PPC_PLT16_HA 31 +#define R_PPC_SDAREL16 32 +#define R_PPC_SECTOFF 33 +#define R_PPC_SECTOFF_LO 34 +#define R_PPC_SECTOFF_HI 35 +#define R_PPC_SECTOFF_HA 36 + +/* + * 64-bit relocations + */ +#define R_PPC64_ADDR64 38 +#define R_PPC64_ADDR16_HIGHER 39 +#define R_PPC64_ADDR16_HIGHERA 40 +#define R_PPC64_ADDR16_HIGHEST 41 +#define R_PPC64_ADDR16_HIGHESTA 42 +#define R_PPC64_UADDR64 43 +#define R_PPC64_REL64 44 +#define R_PPC64_PLT64 45 +#define R_PPC64_PLTREL64 46 +#define R_PPC64_TOC16 47 +#define R_PPC64_TOC16_LO 48 +#define R_PPC64_TOC16_HI 49 +#define R_PPC64_TOC16_HA 50 +#define R_PPC64_TOC 51 +#define R_PPC64_DTPMOD64 68 +#define R_PPC64_TPREL64 73 +#define R_PPC64_DTPREL64 78 + +/* + * TLS relocations + */ +#define R_PPC_TLS 67 +#define R_PPC_DTPMOD32 68 +#define R_PPC_TPREL16 69 +#define R_PPC_TPREL16_LO 70 +#define R_PPC_TPREL16_HI 71 +#define R_PPC_TPREL16_HA 72 +#define R_PPC_TPREL32 73 +#define R_PPC_DTPREL16 74 +#define R_PPC_DTPREL16_LO 75 +#define R_PPC_DTPREL16_HI 76 +#define R_PPC_DTPREL16_HA 77 +#define R_PPC_DTPREL32 78 +#define R_PPC_GOT_TLSGD16 79 +#define R_PPC_GOT_TLSGD16_LO 80 +#define R_PPC_GOT_TLSGD16_HI 81 +#define R_PPC_GOT_TLSGD16_HA 82 +#define R_PPC_GOT_TLSLD16 83 +#define R_PPC_GOT_TLSLD16_LO 84 +#define R_PPC_GOT_TLSLD16_HI 85 +#define R_PPC_GOT_TLSLD16_HA 86 +#define R_PPC_GOT_TPREL16 87 +#define R_PPC_GOT_TPREL16_LO 88 +#define R_PPC_GOT_TPREL16_HI 89 +#define R_PPC_GOT_TPREL16_HA 90 + +/* + * The remaining relocs are from the Embedded ELF ABI, and are not in the + * SVR4 ELF ABI. + */ + +#define R_PPC_EMB_NADDR32 101 +#define R_PPC_EMB_NADDR16 102 +#define R_PPC_EMB_NADDR16_LO 103 +#define R_PPC_EMB_NADDR16_HI 104 +#define R_PPC_EMB_NADDR16_HA 105 +#define R_PPC_EMB_SDAI16 106 +#define R_PPC_EMB_SDA2I16 107 +#define R_PPC_EMB_SDA2REL 108 +#define R_PPC_EMB_SDA21 109 +#define R_PPC_EMB_MRKREF 110 +#define R_PPC_EMB_RELSEC16 111 +#define R_PPC_EMB_RELST_LO 112 +#define R_PPC_EMB_RELST_HI 113 +#define R_PPC_EMB_RELST_HA 114 +#define R_PPC_EMB_BIT_FLD 115 +#define R_PPC_EMB_RELSDA 116 + +#define R_SPARC_NONE 0 +#define R_SPARC_8 1 +#define R_SPARC_16 2 +#define R_SPARC_32 3 +#define R_SPARC_DISP8 4 +#define R_SPARC_DISP16 5 +#define R_SPARC_DISP32 6 +#define R_SPARC_WDISP30 7 +#define R_SPARC_WDISP22 8 +#define R_SPARC_HI22 9 +#define R_SPARC_22 10 +#define R_SPARC_13 11 +#define R_SPARC_LO10 12 +#define R_SPARC_GOT10 13 +#define R_SPARC_GOT13 14 +#define R_SPARC_GOT22 15 +#define R_SPARC_PC10 16 +#define R_SPARC_PC22 17 +#define R_SPARC_WPLT30 18 +#define R_SPARC_COPY 19 +#define R_SPARC_GLOB_DAT 20 +#define R_SPARC_JMP_SLOT 21 +#define R_SPARC_RELATIVE 22 +#define R_SPARC_UA32 23 +#define R_SPARC_PLT32 24 +#define R_SPARC_HIPLT22 25 +#define R_SPARC_LOPLT10 26 +#define R_SPARC_PCPLT32 27 +#define R_SPARC_PCPLT22 28 +#define R_SPARC_PCPLT10 29 +#define R_SPARC_10 30 +#define R_SPARC_11 31 +#define R_SPARC_64 32 +#define R_SPARC_OLO10 33 +#define R_SPARC_HH22 34 +#define R_SPARC_HM10 35 +#define R_SPARC_LM22 36 +#define R_SPARC_PC_HH22 37 +#define R_SPARC_PC_HM10 38 +#define R_SPARC_PC_LM22 39 +#define R_SPARC_WDISP16 40 +#define R_SPARC_WDISP19 41 +#define R_SPARC_GLOB_JMP 42 +#define R_SPARC_7 43 +#define R_SPARC_5 44 +#define R_SPARC_6 45 +#define R_SPARC_DISP64 46 +#define R_SPARC_PLT64 47 +#define R_SPARC_HIX22 48 +#define R_SPARC_LOX10 49 +#define R_SPARC_H44 50 +#define R_SPARC_M44 51 +#define R_SPARC_L44 52 +#define R_SPARC_REGISTER 53 +#define R_SPARC_UA64 54 +#define R_SPARC_UA16 55 +#define R_SPARC_TLS_GD_HI22 56 +#define R_SPARC_TLS_GD_LO10 57 +#define R_SPARC_TLS_GD_ADD 58 +#define R_SPARC_TLS_GD_CALL 59 +#define R_SPARC_TLS_LDM_HI22 60 +#define R_SPARC_TLS_LDM_LO10 61 +#define R_SPARC_TLS_LDM_ADD 62 +#define R_SPARC_TLS_LDM_CALL 63 +#define R_SPARC_TLS_LDO_HIX22 64 +#define R_SPARC_TLS_LDO_LOX10 65 +#define R_SPARC_TLS_LDO_ADD 66 +#define R_SPARC_TLS_IE_HI22 67 +#define R_SPARC_TLS_IE_LO10 68 +#define R_SPARC_TLS_IE_LD 69 +#define R_SPARC_TLS_IE_LDX 70 +#define R_SPARC_TLS_IE_ADD 71 +#define R_SPARC_TLS_LE_HIX22 72 +#define R_SPARC_TLS_LE_LOX10 73 +#define R_SPARC_TLS_DTPMOD32 74 +#define R_SPARC_TLS_DTPMOD64 75 +#define R_SPARC_TLS_DTPOFF32 76 +#define R_SPARC_TLS_DTPOFF64 77 +#define R_SPARC_TLS_TPOFF32 78 +#define R_SPARC_TLS_TPOFF64 79 + +#define R_X86_64_NONE 0 /* No relocation. */ +#define R_X86_64_64 1 /* Add 64 bit symbol value. */ +#define R_X86_64_PC32 2 /* PC-relative 32 bit signed sym value. */ +#define R_X86_64_GOT32 3 /* PC-relative 32 bit GOT offset. */ +#define R_X86_64_PLT32 4 /* PC-relative 32 bit PLT offset. */ +#define R_X86_64_COPY 5 /* Copy data from shared object. */ +#define R_X86_64_GLOB_DAT 6 /* Set GOT entry to data address. */ +#define R_X86_64_JMP_SLOT 7 /* Set GOT entry to code address. */ +#define R_X86_64_RELATIVE 8 /* Add load address of shared object. */ +#define R_X86_64_GOTPCREL 9 /* Add 32 bit signed pcrel offset to GOT. */ +#define R_X86_64_32 10 /* Add 32 bit zero extended symbol value */ +#define R_X86_64_32S 11 /* Add 32 bit sign extended symbol value */ +#define R_X86_64_16 12 /* Add 16 bit zero extended symbol value */ +#define R_X86_64_PC16 13 /* Add 16 bit signed extended pc relative symbol value */ +#define R_X86_64_8 14 /* Add 8 bit zero extended symbol value */ +#define R_X86_64_PC8 15 /* Add 8 bit signed extended pc relative symbol value */ +#define R_X86_64_DTPMOD64 16 /* ID of module containing symbol */ +#define R_X86_64_DTPOFF64 17 /* Offset in TLS block */ +#define R_X86_64_TPOFF64 18 /* Offset in static TLS block */ +#define R_X86_64_TLSGD 19 /* PC relative offset to GD GOT entry */ +#define R_X86_64_TLSLD 20 /* PC relative offset to LD GOT entry */ +#define R_X86_64_DTPOFF32 21 /* Offset in TLS block */ +#define R_X86_64_GOTTPOFF 22 /* PC relative offset to IE GOT entry */ +#define R_X86_64_TPOFF32 23 /* Offset in static TLS block */ +#define R_X86_64_IRELATIVE 37 + + +#endif /* !_SYS_ELF_COMMON_H_ */ diff --git a/core/arch/arm/kernel/elf_load.c b/core/arch/arm/kernel/elf_load.c new file mode 100644 index 00000000000..d5c26b8ba79 --- /dev/null +++ b/core/arch/arm/kernel/elf_load.c @@ -0,0 +1,399 @@ +/* + * Copyright (c) 2014, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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. + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "elf_load.h" +#include "elf_common.h" +#include "elf32.h" + + +struct elf_load_state { + uint8_t *nwdata; + size_t nwdata_len; + + void *hash_ctx; + uint32_t hash_algo; + + size_t next_offs; + + void *ta_head; + size_t ta_head_size; + + Elf32_Ehdr *ehdr; + Elf32_Phdr *phdr; + + size_t vasize; + Elf32_Shdr *shdr; +}; + +static TEE_Result advance_to(struct elf_load_state *state, size_t offs) +{ + TEE_Result res; + + if (offs < state->next_offs) + return TEE_ERROR_BAD_STATE; + if (offs == state->next_offs) + return TEE_SUCCESS; + + if (offs > state->nwdata_len) + return TEE_ERROR_SECURITY; + + res = crypto_ops.hash.update(state->hash_ctx, state->hash_algo, + state->nwdata + state->next_offs, + offs - state->next_offs); + if (res != TEE_SUCCESS) + return res; + state->next_offs = offs; + return res; +} + +static TEE_Result copy_to(struct elf_load_state *state, + void *dst, size_t dst_size, size_t dst_offs, + size_t offs, size_t len) +{ + TEE_Result res; + + res = advance_to(state, offs); + if (res != TEE_SUCCESS) + return res; + if (!len) + return TEE_SUCCESS; + + if (len > dst_size || (len + dst_offs) > dst_size) + return TEE_ERROR_SECURITY; + + if (!core_is_buffer_inside(state->nwdata + offs, len, + state->nwdata, state->nwdata_len)) + return TEE_ERROR_SECURITY; + + memcpy((uint8_t *)dst + dst_offs, state->nwdata + offs, len); + res = crypto_ops.hash.update(state->hash_ctx, state->hash_algo, + (uint8_t *)dst + dst_offs, len); + if (res != TEE_SUCCESS) + return res; + state->next_offs = offs + len; + return res; +} + +static TEE_Result alloc_and_copy_to(void **p, struct elf_load_state *state, + size_t offs, size_t len) +{ + TEE_Result res; + void *buf; + + buf = malloc(len); + if (!buf) + return TEE_ERROR_OUT_OF_MEMORY; + res = copy_to(state, buf, len, 0, offs, len); + if (res == TEE_SUCCESS) + *p = buf; + else + free(buf); + return res; +} + +TEE_Result elf_load_init(void *hash_ctx, uint32_t hash_algo, uint8_t *nwdata, + size_t nwdata_len, struct elf_load_state **ret_state) +{ + struct elf_load_state *state; + + state = calloc(1, sizeof(*state)); + if (!state) + return TEE_ERROR_OUT_OF_MEMORY; + state->hash_ctx = hash_ctx; + state->hash_algo = hash_algo; + state->nwdata = nwdata; + state->nwdata_len = nwdata_len; + *ret_state = state; + return TEE_SUCCESS; +} + +TEE_Result elf_load_head(struct elf_load_state *state, size_t head_size, + void **head, size_t *vasize) +{ + TEE_Result res; + size_t n; + void *p; + Elf32_Ehdr *ehdr; + + /* + * The ELF resides in shared memory, to avoid attacks based on + * modifying the ELF while we're parsing it here we only read each + * byte from the ELF once. We're also hashing the ELF while reading + * so we're limited to only read the ELF sequentially from start to + * end. + */ + + res = alloc_and_copy_to(&p, state, 0, sizeof(Elf32_Ehdr)); + if (res != TEE_SUCCESS) + return res; + ehdr = p; + state->ehdr = ehdr; + + if (!IS_ELF(*ehdr) || + ehdr->e_ident[EI_VERSION] != EV_CURRENT || + ehdr->e_ident[EI_CLASS] != ELFCLASS32 || + ehdr->e_ident[EI_DATA] != ELFDATA2LSB || + ehdr->e_ident[EI_OSABI] != ELFOSABI_NONE || + ehdr->e_type != ET_DYN || ehdr->e_machine != EM_ARM || + (ehdr->e_flags & EF_ARM_ABIMASK) != EF_ARM_ABI_VERSION || + (ehdr->e_flags & EF_ARM_ABI_FLOAT_HARD) || + ehdr->e_phentsize != sizeof(Elf32_Phdr) || + ehdr->e_shentsize != sizeof(Elf32_Shdr)) + return TEE_ERROR_BAD_FORMAT; + + /* + * Program headers are supposed to be arranged as: + * PT_LOAD [0] : .ta_head ... + * ... + * PT_LOAD [n] + * + * .ta_head must be located first in the first program header, + * which also has to be of PT_LOAD type. + * + * A PT_DYNAMIC segment may appear, but is ignored. Any other + * segment except PT_LOAD and PT_DYNAMIC will cause an error. All + * sections not included by a PT_LOAD segment are ignored. + */ + if (ehdr->e_phnum < 1) + return TEE_ERROR_BAD_FORMAT; + res = alloc_and_copy_to(&p, state, ehdr->e_phoff, + ehdr->e_phnum * sizeof(Elf32_Phdr)); + if (res != TEE_SUCCESS) + return res; + state->phdr = p; + + /* + * Check that the first program header is a PT_LOAD (not strictly + * needed but our link script is supposed to arrange it that way) + * and that it starts at virtual address 0. + */ + if (state->phdr[0].p_type != PT_LOAD || state->phdr[0].p_vaddr != 0) + return TEE_ERROR_BAD_FORMAT; + + /* + * Calculate amount of required virtual memory for TA. Find the max + * address used by a PT_LOAD type. Note that last PT_LOAD type + * dictates the total amount of needed memory. Eventual holes in + * the memory will also be allocated. + * + * Note that this loop will terminate at n = 0 if not earlier + * as we already know from above that state->phdr[0].p_type == PT_LOAD + */ + n = ehdr->e_phnum - 1; + while (state->phdr[n].p_type != PT_LOAD) + n--; + state->vasize = state->phdr[n].p_vaddr + state->phdr[n].p_memsz; + + /* + * Read .ta_head from first segment, make sure the segment is large + * enough. We're only interested in seeing that the + * TA_FLAG_EXEC_DDR flag is set. If that's true we set that flag in + * the TA context to enable mapping the TA. Later when this + * function has returned and the hash has been verified the flags + * field will be updated with eventual other flags. + */ + if (state->phdr[0].p_filesz < head_size) + return TEE_ERROR_BAD_FORMAT; + res = alloc_and_copy_to(&p, state, state->phdr[0].p_offset, head_size); + if (res != TEE_SUCCESS) + return res; + state->ta_head = p; + state->ta_head_size = head_size; + + *head = state->ta_head; + *vasize = state->vasize; + return TEE_SUCCESS; +} + +static TEE_Result elf_process_rel(struct elf_load_state *state, size_t rel_sidx, + vaddr_t vabase) +{ + Elf32_Shdr *shdr = state->shdr; + Elf32_Rel *rel; + Elf32_Rel *rel_end; + size_t sym_tab_idx; + Elf32_Sym *sym_tab = NULL; + size_t num_syms = 0; + + if (shdr[rel_sidx].sh_entsize != sizeof(Elf32_Rel)) + return TEE_ERROR_BAD_FORMAT; + + sym_tab_idx = shdr[rel_sidx].sh_link; + if (sym_tab_idx) { + if (sym_tab_idx >= state->ehdr->e_shnum) + return TEE_ERROR_BAD_FORMAT; + + if (shdr[sym_tab_idx].sh_entsize != sizeof(Elf32_Sym)) + return TEE_ERROR_BAD_FORMAT; + + /* Check the address is inside TA memory */ + if (shdr[sym_tab_idx].sh_addr > state->vasize || + (shdr[sym_tab_idx].sh_addr + + shdr[sym_tab_idx].sh_size) > state->vasize) + return TEE_ERROR_BAD_FORMAT; + + sym_tab = (Elf32_Sym *)(vabase + shdr[sym_tab_idx].sh_addr); + if (!TEE_ALIGNMENT_IS_OK(sym_tab, Elf32_Sym)) + return TEE_ERROR_BAD_FORMAT; + + num_syms = shdr[sym_tab_idx].sh_size / sizeof(Elf32_Sym); + } + + /* Check the address is inside TA memory */ + if (shdr[rel_sidx].sh_addr >= state->vasize) + return TEE_ERROR_BAD_FORMAT; + rel = (Elf32_Rel *)(vabase + shdr[rel_sidx].sh_addr); + if (!TEE_ALIGNMENT_IS_OK(rel, Elf32_Rel)) + return TEE_ERROR_BAD_FORMAT; + + /* Check the address is inside TA memory */ + if ((shdr[rel_sidx].sh_addr + shdr[rel_sidx].sh_size) >= state->vasize) + return TEE_ERROR_BAD_FORMAT; + rel_end = rel + shdr[rel_sidx].sh_size / sizeof(Elf32_Rel); + for (; rel < rel_end; rel++) { + Elf32_Addr *where; + size_t sym_idx; + + /* Check the address is inside TA memory */ + if (rel->r_offset >= state->vasize) + return TEE_ERROR_BAD_FORMAT; + + where = (Elf32_Addr *)(vabase + rel->r_offset); + if (!TEE_ALIGNMENT_IS_OK(where, Elf32_Addr)) + return TEE_ERROR_BAD_FORMAT; + + switch (ELF32_R_TYPE(rel->r_info)) { + case R_ARM_ABS32: + sym_idx = ELF32_R_SYM(rel->r_info); + if (sym_idx >= num_syms) + return TEE_ERROR_BAD_FORMAT; + + *where += vabase + sym_tab[sym_idx].st_value; + break; + case R_ARM_RELATIVE: + *where += vabase; + break; + default: + EMSG("Unknown relocation type %d", + ELF32_R_TYPE(rel->r_info)); + return TEE_ERROR_BAD_FORMAT; + } + } + return TEE_SUCCESS; +} + +TEE_Result elf_load_body(struct elf_load_state *state, vaddr_t vabase) +{ + TEE_Result res; + size_t n; + void *p; + uint8_t *dst = (uint8_t *)vabase; + Elf32_Ehdr *ehdr = state->ehdr; + Elf32_Phdr *phdr = state->phdr; + + /* + * Zero initialize everything to make sure that all memory not + * updated from the ELF is zero (covering .bss and eventual gaps). + */ + memset(dst, 0, state->vasize); + + /* + * Copy the segments + */ + memcpy(dst, state->ta_head, state->ta_head_size); + res = copy_to(state, dst, state->vasize, + phdr[0].p_vaddr + state->ta_head_size, + phdr[0].p_offset + state->ta_head_size, + phdr[0].p_filesz - state->ta_head_size); + if (res != TEE_SUCCESS) + return res; + + for (n = 1; n < ehdr->e_phnum; n++) { + if (phdr[n].p_type != PT_LOAD) + continue; + + res = copy_to(state, dst, state->vasize, phdr[n].p_vaddr, + phdr[n].p_offset, phdr[n].p_filesz); + if (res != TEE_SUCCESS) + return res; + } + + /* + * We have now loaded all segments into TA memory, now we need to + * process relocation information. To find relocation information + * we need to locate the section headers. The section headers are + * located somewhere between the last segment and the end of the + * ELF. + */ + if (ehdr->e_shoff) { + /* We have section headers */ + res = alloc_and_copy_to(&p, state, ehdr->e_shoff, + ehdr->e_shnum * sizeof(Elf32_Shdr)); + if (res != TEE_SUCCESS) + return res; + state->shdr = p; + } + + /* Hash until end of ELF */ + res = advance_to(state, state->nwdata_len); + if (res != TEE_SUCCESS) + return res; + + if (state->shdr) { + /* Process relocation */ + for (n = 0; n < ehdr->e_shnum; n++) { + if (state->shdr[n].sh_type == SHT_RELA) + return TEE_ERROR_NOT_IMPLEMENTED; + else if (state->shdr[n].sh_type == SHT_REL) { + res = elf_process_rel(state, n, vabase); + if (res != TEE_SUCCESS) + return res; + } + } + } + + return TEE_SUCCESS; +} + +void elf_load_final(struct elf_load_state *state) +{ + if (state) { + free(state->ta_head); + free(state->ehdr); + free(state->phdr); + free(state->shdr); + free(state); + } +} diff --git a/core/arch/arm/include/kernel/kta_types.h b/core/arch/arm/kernel/elf_load.h similarity index 65% rename from core/arch/arm/include/kernel/kta_types.h rename to core/arch/arm/kernel/elf_load.h index baa3a1a8962..dbe8d1646c5 100644 --- a/core/arch/arm/include/kernel/kta_types.h +++ b/core/arch/arm/kernel/elf_load.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2015, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,26 +24,19 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +#ifndef ELF_LOAD_H +#define ELF_LOAD_H -#ifndef KTA_TYPES_H -#define KTA_TYPES_H +#include +#include -#include +struct elf_load_state; -typedef struct kta_signed_header { - uint32_t magic; - uint16_t size_of_signed_header; - uint16_t size_of_signature; - uint32_t sign_hash_type; /* see t_hash_type */ - uint32_t signature_type; /* see t_signature_type */ - uint32_t hash_type; /* see t_hash_type */ - uint32_t payload_type; /* see enum kta_payload_type */ - uint32_t flags; /* reserved */ - uint32_t size_of_payload; - uint32_t sw_vers_nbr; - uint32_t load_address; - uint32_t startup_address; - uint32_t spare; /* reserved */ -} kta_signed_header_t; +TEE_Result elf_load_init(void *hash_ctx, uint32_t hash_algo, uint8_t *nwdata, + size_t nwdata_len, struct elf_load_state **state); +TEE_Result elf_load_head(struct elf_load_state *state, size_t head_size, + void **head, size_t *vasize); +TEE_Result elf_load_body(struct elf_load_state *state, vaddr_t vabase); +void elf_load_final(struct elf_load_state *state); -#endif /* End of kta_types.h */ +#endif /*ELF_LOAD_H*/ diff --git a/core/arch/arm/kernel/sub.mk b/core/arch/arm/kernel/sub.mk index ac31e4a0e89..d0225941715 100644 --- a/core/arch/arm/kernel/sub.mk +++ b/core/arch/arm/kernel/sub.mk @@ -1,4 +1,5 @@ srcs-y += tee_ta_manager.c +srcs-y += elf_load.c srcs-y += tee_time.c srcs-$(CFG_SECURE_TIME_SOURCE_CNTPCT) += tee_time_arm_cntpct.c diff --git a/core/arch/arm/kernel/tee_ta_manager.c b/core/arch/arm/kernel/tee_ta_manager.c index b02b22d92ed..9098ffe79a3 100644 --- a/core/arch/arm/kernel/tee_ta_manager.c +++ b/core/arch/arm/kernel/tee_ta_manager.c @@ -41,6 +41,8 @@ #include #include #include +#include +#include #include #include #include @@ -54,14 +56,18 @@ #include #include #include -#include "user_ta_header.h" +#include #include #include #include #include #include +#include #include #include +#include +#include +#include "elf_load.h" /* * Use this invalid ID for a static TA, since @@ -236,373 +242,225 @@ static struct tee_ta_ctx *tee_ta_context_find(const TEE_UUID *uuid) struct tee_ta_ctx *ctx; TAILQ_FOREACH(ctx, &tee_ctxes, link) { - if (memcmp(&ctx->head->uuid, uuid, sizeof(TEE_UUID)) == 0) + if (memcmp(&ctx->uuid, uuid, sizeof(TEE_UUID)) == 0) return ctx; } return NULL; } -static void tee_ta_init_got(struct tee_ta_ctx *const ctx) -{ - uint32_t *ptr; - uint32_t *end_ptr; - uint32_t va_start; - - /* - * GOT and find_service_addr follows right after ro section. - */ - if ((TA_HEAD_GOT_MASK & ctx->head->rel_dyn_got_size) == 0) - return; - - va_start = ctx->load_addr; - - ptr = (uint32_t *)(tee_ta_get_exec(ctx) + ctx->head->ro_size); - end_ptr = ptr + (TA_HEAD_GOT_MASK & ctx->head->rel_dyn_got_size) / - sizeof(uint32_t); - - while (ptr < end_ptr) { - *ptr += va_start; -#ifdef PAGER_DEBUG_PRINT - DMSG("GOT [%p] = 0x%x", (void *)ptr, *ptr); -#endif - ptr++; - } -} - -static void tee_ta_init_zi(struct tee_ta_ctx *const ctx) +static TEE_Result tee_ta_load_header(const struct shdr *signed_ta, + struct shdr **sec_shdr) { - /* setup ZI data */ - vaddr_t start = tee_ta_get_exec(ctx) + - ctx->head->rw_size + ctx->head->ro_size; - - memset((void *)start, 0, ctx->head->zi_size); -} + size_t s; -/* - * Process rel.dyn - */ -static void tee_ta_init_reldyn(struct tee_ta_ctx *const ctx) -{ - uint32_t rel_dyn_size = ctx->head->rel_dyn_got_size >> 16; - uint32_t n; - vaddr_t saddr = tee_ta_get_exec(ctx) + ctx->head->ro_size - - rel_dyn_size; - - for (n = 0; n < rel_dyn_size; n += sizeof(struct ta_rel_dyn)) { - struct ta_rel_dyn *rel_dyn = (struct ta_rel_dyn *)(saddr + n); - uint32_t *data; - - if (rel_dyn->info != 0x17) { - EMSG("Unknown rel_dyn info 0x%x", rel_dyn->info); - TEE_ASSERT(0); - } - - data = (uint32_t *)((vaddr_t)ctx->load_addr + rel_dyn->addr); - *data += ctx->load_addr; -#ifdef PAGER_DEBUG_PRINT - DMSG("rel.dyn [%p] = 0x%x", (void *)data, *data); -#endif - } -} - -/* - * Setup global variables initialized from TEE Core - */ -static void tee_ta_init_heap(struct tee_ta_ctx *const ctx, size_t heap_size) -{ - uint32_t *data; - tee_uaddr_t heap_start_addr; - vaddr_t va_start; - - /* - * User TA - * - * Heap base follows right after GOT - */ + if (!tee_vbuf_is_non_sec(signed_ta, sizeof(*signed_ta))) + return TEE_ERROR_SECURITY; - core_mmu_get_user_va_range(&va_start, NULL); - /* XXX this function shouldn't know this mapping */ - heap_start_addr = va_start + CORE_MMU_USER_CODE_SIZE - heap_size; + s = SHDR_GET_SIZE(signed_ta); + if (!tee_vbuf_is_non_sec(signed_ta, s)) + return TEE_ERROR_SECURITY; - data = (uint32_t *)(tee_ta_get_exec(ctx) + ctx->head->ro_size + - (ctx->head->rel_dyn_got_size & TA_HEAD_GOT_MASK)); + /* Copy signed header into secure memory */ + *sec_shdr = malloc(s); + if (!*sec_shdr) + return TEE_ERROR_OUT_OF_MEMORY; + memcpy(*sec_shdr, signed_ta, s); - *data = heap_start_addr; -#ifdef PAGER_DEBUG_PRINT - DMSG("heap_base [%p] = 0x%x", (void *)data, *data); -#endif + return TEE_SUCCESS; } -static TEE_Result tee_ta_load_header(const kta_signed_header_t *signed_ta, - kta_signed_header_t **sec_signed_ta, ta_head_t **sec_head, - const uint8_t **nmem_ta) +static TEE_Result tee_ta_load_check_shdr(struct shdr *shdr) { + struct rsa_public_key key; TEE_Result res; - size_t sz_sign_header; - size_t sz_ta_head; - size_t sz_hash_type; - size_t sz_ro; - size_t sz_rw; - size_t sz_hashes; - size_t num_hashes; - size_t sz_funcs; - const ta_head_t *nmem_head; - ta_head_t *head = NULL; - uint8_t *nmem_hashes; - uint8_t *hashes; - - if (!tee_vbuf_is_non_sec(signed_ta, sizeof(*signed_ta))) - return TEE_ERROR_SECURITY; + uint32_t e = TEE_U32_TO_BIG_ENDIAN(ta_pub_key_exponent); + size_t hash_size; - sz_sign_header = signed_ta->size_of_signed_header; - if (!tee_vbuf_is_non_sec(signed_ta, sz_sign_header)) + if (shdr->magic != SHDR_MAGIC || shdr->img_type != SHDR_TA) return TEE_ERROR_SECURITY; - nmem_head = (const void *)((uint8_t *)(signed_ta) + sz_sign_header); - if (!tee_vbuf_is_non_sec(nmem_head, sizeof(*nmem_head))) - return TEE_ERROR_SECURITY; - - sz_ro = nmem_head->ro_size; - sz_rw = nmem_head->rw_size; - - /* Obviously a fake TA since there's no code or data */ - if ((sz_ro + sz_rw) == 0) + if (TEE_ALG_GET_MAIN_ALG(shdr->algo) != TEE_MAIN_ALGO_RSA) return TEE_ERROR_SECURITY; - /* One hash per supplied page of code and data */ - num_hashes = ((sz_ro + sz_rw - 1) >> SMALL_PAGE_SHIFT) + 1; - -#ifdef CFG_NO_TA_HASH_SIGN - sz_hash_type = 0; -#else - /* COPY HEADERS & HASHES: ta_head + ta_func_head(s) + hashes */ - if (tee_hash_get_digest_size(nmem_head->hash_type, &sz_hash_type) != - TEE_SUCCESS) { - DMSG("warning: invalid signed header: invalid hash id found!"); + res = tee_hash_get_digest_size(TEE_DIGEST_HASH_TO_ALGO(shdr->algo), + &hash_size); + if (res != TEE_SUCCESS) + return res; + if (hash_size != shdr->hash_size) return TEE_ERROR_SECURITY; - } -#endif - - sz_hashes = sz_hash_type * num_hashes; - sz_funcs = nmem_head->nbr_func * sizeof(ta_func_head_t); - sz_ta_head = sizeof(*head) + sz_funcs + sz_hashes; - if (!tee_vbuf_is_non_sec(nmem_head, sz_ta_head - sz_hashes)) - return TEE_ERROR_SECURITY; + if (!crypto_ops.acipher.alloc_rsa_public_key || + !crypto_ops.acipher.rsassa_verify || + !crypto_ops.bignum.bin2bn || !crypto_ops.bignum.free) + return TEE_ERROR_NOT_SUPPORTED; - /* Copy TA header into secure memory */ - head = malloc(sz_ta_head); - if (!head) - return TEE_ERROR_OUT_OF_MEMORY; - memcpy(head, nmem_head, sz_ta_head - sz_hashes); + res = crypto_ops.acipher.alloc_rsa_public_key(&key, shdr->sig_size); + if (res != TEE_SUCCESS) + return res; - /* - * Check that the GOT ends up at a properly aligned address. - * See tee_ta_init_got() for update of GOT. - */ - if ((head->ro_size % 4) != 0) { - DMSG("Bad ro_size %u", head->ro_size); - res = TEE_ERROR_BAD_FORMAT; + res = crypto_ops.bignum.bin2bn((uint8_t *)&e, sizeof(e), key.e); + if (res != TEE_SUCCESS) goto out; - } - - /* Copy hashes into secure memory */ - hashes = (uint8_t *)head + sz_funcs; - nmem_hashes = (uint8_t *)nmem_head + sz_funcs + - head->ro_size + head->rw_size; - memcpy(hashes, nmem_hashes, sz_hashes); - - /* Copy signed header into secure memory */ - *sec_signed_ta = malloc(sz_sign_header); - if (!*sec_signed_ta) { - res = TEE_ERROR_OUT_OF_MEMORY; + res = crypto_ops.bignum.bin2bn(ta_pub_key_modulus, + ta_pub_key_modulus_size, key.n); + if (res != TEE_SUCCESS) goto out; - } - memcpy(*sec_signed_ta, signed_ta, sz_sign_header); - - *sec_head = head; - *nmem_ta = (const uint8_t *)nmem_head; - res = TEE_SUCCESS; + res = crypto_ops.acipher.rsassa_verify(shdr->algo, &key, -1, + SHDR_GET_HASH(shdr), shdr->hash_size, + SHDR_GET_SIG(shdr), shdr->sig_size); out: - if (res != TEE_SUCCESS) { - free(head); - } + crypto_ops.bignum.free(key.n); + crypto_ops.bignum.free(key.e); return res; } -static TEE_Result tee_ta_load_check_head_integrity( - kta_signed_header_t *signed_ta __unused, - ta_head_t *head __unused) -{ - /* - * This is where the signature of the signed header is verified - * and that the payload that "head" is a valid payload for - * that signed header. - * - * If this function returns success "head" together with - * the appended hashes are OK and we can continue to load - * the TA. - */ - return TEE_SUCCESS; -} - -static TEE_Result tee_ta_load_user_ta(struct tee_ta_ctx *ctx, - ta_head_t *sec_head, const void *nmem_ta, - size_t *heap_size) +static TEE_Result tee_ta_load_elf(struct tee_ta_ctx *ctx, struct shdr *shdr, + const struct shdr *nmem_shdr) { TEE_Result res; - size_t size; - ta_func_head_t *ta_func_head; - struct user_ta_sub_head *sub_head; - /* man_flags: mandatory flags */ - uint32_t man_flags = TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR; - /* opt_flags: optional flags */ - uint32_t opt_flags = man_flags | TA_FLAG_SINGLE_INSTANCE | - TA_FLAG_MULTI_SESSION | TA_FLAG_UNSAFE_NW_PARAMS; struct tee_ta_param param = { 0 }; - void *dst; - - /* full required execution size (not stack etc...) */ - size = ctx->head->ro_size + ctx->head->rw_size + ctx->head->zi_size; - - if (ctx->num_res_funcs != 2) - return TEE_ERROR_BAD_FORMAT; - - ta_func_head = (ta_func_head_t *)((vaddr_t)ctx->head + - sizeof(ta_head_t)); - - sub_head = (struct user_ta_sub_head *)&ta_func_head[ - ctx->head->nbr_func - ctx->num_res_funcs]; + size_t hash_ctx_size; + void *hash_ctx = NULL; + uint32_t hash_algo; + uint8_t *nwdata = (uint8_t *)nmem_shdr + SHDR_GET_SIZE(shdr); + size_t nwdata_len = shdr->img_size; + void *digest = NULL; + struct elf_load_state *elf_state = NULL; + struct ta_head *ta_head; + void *p; + size_t vasize; + + if (!crypto_ops.hash.get_ctx_size || !crypto_ops.hash.init || + !crypto_ops.hash.update || !crypto_ops.hash.final) { + res = TEE_ERROR_NOT_IMPLEMENTED; + goto out; + } + hash_algo = TEE_DIGEST_HASH_TO_ALGO(shdr->algo); + res = crypto_ops.hash.get_ctx_size(hash_algo, &hash_ctx_size); + if (res != TEE_SUCCESS) + goto out; + hash_ctx = malloc(hash_ctx_size); + if (!hash_ctx) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; + } + res = crypto_ops.hash.init(hash_ctx, hash_algo); + if (res != TEE_SUCCESS) + goto out; + res = crypto_ops.hash.update(hash_ctx, hash_algo, + (uint8_t *)shdr, sizeof(struct shdr)); + if (res != TEE_SUCCESS) + goto out; + res = elf_load_init(hash_ctx, hash_algo, nwdata, nwdata_len, + &elf_state); + if (res != TEE_SUCCESS) + goto out; - /* - * sub_head is the end area of func_head; the 2 last - * (2 'resisdent func') func_head area. - * sub_head structure is... twice the func_head struct. magic. - * sub_head stores the flags, heap_size, stack_size. - */ - COMPILE_TIME_ASSERT((sizeof(struct user_ta_sub_head)) == - (2 * sizeof(struct user_ta_func_head))); + res = elf_load_head(elf_state, sizeof(struct ta_head), &p, &vasize); + if (res != TEE_SUCCESS) + goto out; + ta_head = p; - /* check input flags bitmask consistency and save flags */ - if ((sub_head->flags & opt_flags) != sub_head->flags || - (sub_head->flags & man_flags) != man_flags) { - EMSG("TA flag issue: flags=%x opt=%X man=%X", - sub_head->flags, opt_flags, man_flags); - return TEE_ERROR_BAD_FORMAT; + ctx->mm = tee_mm_alloc(&tee_mm_sec_ddr, vasize); + if (!ctx->mm) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; } - ctx->flags = sub_head->flags; - - /* Check if multi instance && single session config */ - if (((ctx->flags & TA_FLAG_SINGLE_INSTANCE) == 0) && - ((ctx->flags & TA_FLAG_MULTI_SESSION) == 0)) { - /* - * assume MultiInstance/SingleSession, - * same as MultiInstance/MultiSession - */ - ctx->flags |= TA_FLAG_MULTI_SESSION; + /* Currently all TA must execute from DDR */ + if (!(ta_head->flags & TA_FLAG_EXEC_DDR)) { + res = TEE_ERROR_BAD_FORMAT; + goto out; } + /* Temporary assignment to setup memory mapping */ + ctx->flags = TA_FLAG_EXEC_DDR; /* Ensure proper aligment of stack */ - ctx->stack_size = ROUNDUP(sub_head->stack_size, - TEE_TA_STACK_ALIGNMENT); - - *heap_size = sub_head->heap_size; + ctx->stack_size = ROUNDUP(ta_head->stack_size, + TEE_TA_STACK_ALIGNMENT); - /* - * Allocate heap and stack - */ - ctx->mm_heap_stack = tee_mm_alloc(&tee_mm_sec_ddr, - *heap_size + ctx->stack_size); - if (!ctx->mm_heap_stack) { - EMSG("Failed to allocate %zu bytes\n", - *heap_size + ctx->stack_size); - EMSG(" of memory for user heap and stack\n"); - return TEE_ERROR_OUT_OF_MEMORY; + ctx->mm_stack = tee_mm_alloc(&tee_mm_sec_ddr, ctx->stack_size); + if (!ctx->mm_stack) { + EMSG("Failed to allocate %zu bytes for user stack", + ctx->stack_size); + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; } /* - * Note that only User TA can be supported in DDR - * if executing in DDR, the size of the execution area - */ - size += sizeof(ta_head_t) + - sec_head->nbr_func * sizeof(ta_func_head_t) + - (sec_head->rel_dyn_got_size & TA_HEAD_GOT_MASK); - - ctx->mm = tee_mm_alloc(&tee_mm_sec_ddr, size); - if (!ctx->mm) - return TEE_ERROR_OUT_OF_MEMORY; - - /* - * Copy TA into reserved memory space (DDR). + * Map physical memory into TA virtual memory */ res = tee_mmu_init(ctx); if (res != TEE_SUCCESS) - return res; + goto out; res = tee_mmu_map(ctx, ¶m); - if (res != TEE_SUCCESS) { - EMSG("call tee_mmu_map_uta() failed %X", res); - return res; - } + if (res != TEE_SUCCESS) + goto out; tee_mmu_set_ctx(ctx); - dst = (void *)tee_mmu_get_load_addr(ctx); - if (!tee_vbuf_is_non_sec(nmem_ta, size)) { - EMSG("User TA isn't in non-secure memory"); - return TEE_ERROR_SECURITY; + res = elf_load_body(elf_state, tee_mmu_get_load_addr(ctx)); + if (res != TEE_SUCCESS) + goto out; + + digest = malloc(shdr->hash_size); + if (!digest) { + res = TEE_ERROR_OUT_OF_MEMORY; + goto out; } - memcpy(dst, nmem_ta, size); - cache_maintenance_l1(DCACHE_AREA_CLEAN, dst, size); - cache_maintenance_l1(ICACHE_AREA_INVALIDATE, dst, size); + res = crypto_ops.hash.final(hash_ctx, hash_algo, digest, + shdr->hash_size); + if (res != TEE_SUCCESS) + goto out; - ctx->load_addr = tee_mmu_get_load_addr(ctx); + if (memcmp(digest, SHDR_GET_HASH(shdr), shdr->hash_size) != 0) + res = TEE_ERROR_SECURITY; - return TEE_SUCCESS; + cache_maintenance_l1(DCACHE_AREA_CLEAN, + (void *)tee_mmu_get_load_addr(ctx), vasize); + cache_maintenance_l1(ICACHE_AREA_INVALIDATE, + (void *)tee_mmu_get_load_addr(ctx), vasize); +out: + elf_load_final(elf_state); + free(digest); + free(hash_ctx); + return res; } -static void tee_ta_load_init_user_ta(struct tee_ta_ctx *ctx, size_t heap_size) -{ - /* Init rel.dyn, GOT, ZI and heap */ - tee_ta_init_reldyn(ctx); - tee_ta_init_got(ctx); - tee_ta_init_heap(ctx, heap_size); - tee_ta_init_zi(ctx); -} + /*----------------------------------------------------------------------------- * Loads TA header and hashes. * Verifies the TA signature. * Returns session ptr and TEE_Result. *---------------------------------------------------------------------------*/ -static TEE_Result tee_ta_load(const kta_signed_header_t *signed_ta, - struct tee_ta_ctx **ta_ctx) +static TEE_Result tee_ta_load(const TEE_UUID *uuid, + const struct shdr *signed_ta, + struct tee_ta_ctx **ta_ctx) { - /* ta & ta_session is assumed to be != NULL from previous checks */ TEE_Result res; - size_t heap_size = 0; /* gcc warning */ + /* man_flags: mandatory flags */ + uint32_t man_flags = TA_FLAG_USER_MODE | TA_FLAG_EXEC_DDR; + /* opt_flags: optional flags */ + uint32_t opt_flags = man_flags | TA_FLAG_SINGLE_INSTANCE | + TA_FLAG_MULTI_SESSION | TA_FLAG_UNSAFE_NW_PARAMS; struct tee_ta_ctx *ctx = NULL; - const uint8_t *nmem_ta; - kta_signed_header_t *sec_signed_ta = NULL; - ta_head_t *sec_head = NULL; + struct shdr *sec_shdr = NULL; + struct ta_head *ta_head; - res = tee_ta_load_header(signed_ta, &sec_signed_ta, &sec_head, - &nmem_ta); + res = tee_ta_load_header(signed_ta, &sec_shdr); if (res != TEE_SUCCESS) goto error_return; - res = tee_ta_load_check_head_integrity(sec_signed_ta, sec_head); + res = tee_ta_load_check_shdr(sec_shdr); if (res != TEE_SUCCESS) goto error_return; - free(sec_signed_ta); - sec_signed_ta = NULL; - /* * ------------------------------------------------------------------ @@ -626,57 +484,60 @@ static TEE_Result tee_ta_load(const kta_signed_header_t *signed_ta, TAILQ_INIT(&ctx->cryp_states); TAILQ_INIT(&ctx->objects); TAILQ_INIT(&ctx->storage_enums); - ctx->head = sec_head; #if defined(CFG_SE_API) ctx->se_service = NULL; #endif - /* by default NSec DDR: starts at TA function code. */ - ctx->mem_swap = (uintptr_t)(nmem_ta + sizeof(ta_head_t) + - sec_head->nbr_func * sizeof(ta_func_head_t)); + res = tee_ta_load_elf(ctx, sec_shdr, signed_ta); + if (res != TEE_SUCCESS) + goto error_return; - ctx->num_res_funcs = ctx->head->zi_size >> 20; - ctx->head->zi_size &= 0xfffff; - if (ctx->num_res_funcs > ctx->head->nbr_func) { - res = TEE_ERROR_BAD_FORMAT; + ctx->load_addr = tee_mmu_get_load_addr(ctx); + ta_head = (struct ta_head *)(vaddr_t)ctx->load_addr; + + if (memcmp(&ta_head->uuid, uuid, sizeof(TEE_UUID)) != 0) { + res = TEE_ERROR_SECURITY; goto error_return; } - res = tee_ta_load_user_ta(ctx, sec_head, nmem_ta, &heap_size); - if (res != TEE_SUCCESS) + /* check input flags bitmask consistency and save flags */ + if ((ta_head->flags & opt_flags) != ta_head->flags || + (ta_head->flags & man_flags) != man_flags) { + EMSG("TA flag issue: flags=%x opt=%X man=%X", + ta_head->flags, opt_flags, man_flags); + res = TEE_ERROR_BAD_FORMAT; goto error_return; + } + + ctx->flags = ta_head->flags; + ctx->uuid = ta_head->uuid; + ctx->open_session_func = ta_head->open_session; + ctx->close_session_func = ta_head->close_session; + ctx->invoke_command_func = ta_head->invoke_command; ctx->ref_count = 1; TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link); *ta_ctx = ctx; - /* - * Note that the setup below will cause at least one page fault so it's - * important that the session is fully registered at this stage. - */ - tee_ta_load_init_user_ta(ctx, heap_size); - DMSG("Loaded TA at 0x%" PRIxPTR ", ro_size %u, rw_size %u, zi_size %u", - tee_mm_get_smem(ctx->mm), ctx->head->ro_size, - ctx->head->rw_size, ctx->head->zi_size); + DMSG("Loaded TA at 0x%" PRIxPTR, tee_mm_get_smem(ctx->mm)); DMSG("ELF load address 0x%x", ctx->load_addr); set_tee_rs(NULL); tee_mmu_set_ctx(NULL); /* end thread protection (multi-threaded) */ + free(sec_shdr); return TEE_SUCCESS; error_return: + free(sec_shdr); set_tee_rs(NULL); tee_mmu_set_ctx(NULL); if (ctx != NULL) { - if ((ctx->flags & TA_FLAG_USER_MODE) != 0) - tee_mmu_final(ctx); - tee_mm_free(ctx->mm_heap_stack); + tee_mmu_final(ctx); + tee_mm_free(ctx->mm_stack); tee_mm_free(ctx->mm); - /* If sec DDR was allocated for mem_swap free it */ - tee_mm_free(tee_mm_find(&tee_mm_sec_ddr, ctx->mem_swap)); free(ctx); } return res; @@ -754,18 +615,12 @@ static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, struct abi_user32_param *usr_params; tee_paddr_t usr_stack; tee_uaddr_t stack_uaddr; - tee_uaddr_t start_uaddr; struct tee_ta_ctx *ctx = session->ctx; - ta_func_head_t *ta_func_head = (ta_func_head_t *)((vaddr_t)ctx->head + - sizeof(ta_head_t)); tee_uaddr_t params_uaddr; TEE_ErrorOrigin serr = TEE_ORIGIN_TEE; TEE_ASSERT((ctx->flags & TA_FLAG_EXEC_DDR) != 0); - TEE_ASSERT((uint32_t) func <= - (ctx->head->nbr_func - ctx->num_res_funcs)); - /* Set timeout of entry */ tee_ta_set_invoke_timeout(session, cancel_req_to); @@ -778,7 +633,7 @@ static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, tee_ta_set_current_session(session); /* Make room for usr_params at top of stack */ - usr_stack = tee_mm_get_smem(ctx->mm_heap_stack) + ctx->stack_size; + usr_stack = tee_mm_get_smem(ctx->mm_stack) + ctx->stack_size; usr_stack -= sizeof(struct abi_user32_param); usr_params = (struct abi_user32_param *)usr_stack; abi_param_to_user32_param(usr_params, param->params, param->types); @@ -792,15 +647,13 @@ static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, if (res != TEE_SUCCESS) goto cleanup_return; - start_uaddr = ctx->load_addr + ta_func_head[func].start; - switch (func) { case USER_TA_FUNC_OPEN_CLIENT_SESSION: res = thread_enter_user_mode(param->types, params_uaddr, (vaddr_t)session, 0, stack_uaddr, - start_uaddr, &ctx->panicked, - &ctx->panic_code); + ctx->open_session_func, + &ctx->panicked, &ctx->panic_code); /* * According to GP spec the origin should allways be set to the @@ -811,7 +664,8 @@ static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, case USER_TA_FUNC_CLOSE_CLIENT_SESSION: res = thread_enter_user_mode((vaddr_t)session, 0, 0, 0, - stack_uaddr, start_uaddr, + stack_uaddr, + ctx->close_session_func, &ctx->panicked, &ctx->panic_code); serr = TEE_ORIGIN_TRUSTED_APP; @@ -820,8 +674,8 @@ static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, case USER_TA_FUNC_INVOKE_COMMAND: res = thread_enter_user_mode(cmd, param->types, params_uaddr, (vaddr_t)session, stack_uaddr, - start_uaddr, &ctx->panicked, - &ctx->panic_code); + ctx->invoke_command_func, + &ctx->panicked, &ctx->panic_code); serr = TEE_ORIGIN_TRUSTED_APP; break; @@ -868,7 +722,7 @@ static TEE_Result tee_user_ta_enter(TEE_ErrorOrigin *err, * Function is not thread safe */ static TEE_Result tee_ta_rpc_load(const TEE_UUID *uuid, - kta_signed_header_t **ta, + struct shdr **ta, uint32_t *handle, uint32_t *ret_orig) { @@ -969,10 +823,10 @@ static void tee_ta_destroy_context(struct tee_ta_ctx *ctx) } } - if (ctx->mm_heap_stack != NULL) { - pa = tee_mm_get_smem(ctx->mm_heap_stack); + if (ctx->mm_stack) { + pa = tee_mm_get_smem(ctx->mm_stack); if (tee_mmu_user_pa2va(ctx, pa, &va) == TEE_SUCCESS) { - s = tee_mm_get_bytes(ctx->mm_heap_stack); + s = tee_mm_get_bytes(ctx->mm_stack); memset(va, 0, s); cache_maintenance_l1(DCACHE_AREA_CLEAN, va, s); } @@ -994,17 +848,12 @@ static void tee_ta_destroy_context(struct tee_ta_ctx *ctx) &ctx->open_sessions, KERN_IDENTITY); } - - /* If TA was loaded in reserved DDR free the alloc. */ - tee_mm_free(tee_mm_find(&tee_mm_sec_ddr, ctx->mem_swap)); - if ((ctx->flags & TA_FLAG_USER_MODE) != 0) { tee_mmu_final(ctx); - tee_mm_free(ctx->mm_heap_stack); + tee_mm_free(ctx->mm_stack); } if (ctx->static_ta == NULL) { tee_mm_free(ctx->mm); - free(ctx->head); } /* Free cryp states created by this TA */ @@ -1168,8 +1017,8 @@ static TEE_Result tee_ta_init_session_with_context(struct tee_ta_ctx *ctx, return TEE_ERROR_BUSY; DMSG(" ... Re-open TA %08x-%04x-%04x", - ctx->head->uuid.timeLow, - ctx->head->uuid.timeMid, ctx->head->uuid.timeHiAndVersion); + ctx->uuid.timeLow, + ctx->uuid.timeMid, ctx->uuid.timeHiAndVersion); ctx->ref_count++; @@ -1210,39 +1059,37 @@ static TEE_Result tee_ta_init_static_ta_session(const TEE_UUID *uuid, TAILQ_INIT(&ctx->open_sessions); TAILQ_INIT(&ctx->cryp_states); TAILQ_INIT(&ctx->objects); - ctx->num_res_funcs = 0; ctx->ref_count = 1; s->ctx = ctx; ctx->flags = TA_FLAG_MULTI_SESSION; - ctx->head = (ta_head_t *)ta; ctx->static_ta = ta; + ctx->uuid = ta->uuid; TAILQ_INSERT_TAIL(&tee_ctxes, ctx, link); DMSG(" %s : %08x-%04x-%04x", ctx->static_ta->name, - ctx->head->uuid.timeLow, - ctx->head->uuid.timeMid, - ctx->head->uuid.timeHiAndVersion); + ctx->uuid.timeLow, + ctx->uuid.timeMid, + ctx->uuid.timeHiAndVersion); return TEE_SUCCESS; } -static TEE_Result tee_ta_init_session_with_signed_ta( - const kta_signed_header_t *signed_ta, +static TEE_Result tee_ta_init_session_with_signed_ta(const TEE_UUID *uuid, + const struct shdr *signed_ta, struct tee_ta_session *s) { TEE_Result res; DMSG(" Load dynamic TA"); /* load and verify */ - res = tee_ta_load(signed_ta, &s->ctx); + res = tee_ta_load(uuid, signed_ta, &s->ctx); if (res != TEE_SUCCESS) return res; DMSG(" dyn TA : %08x-%04x-%04x", - s->ctx->head->uuid.timeLow, - s->ctx->head->uuid.timeMid, - s->ctx->head->uuid.timeHiAndVersion); + s->ctx->uuid.timeLow, s->ctx->uuid.timeMid, + s->ctx->uuid.timeHiAndVersion); return res; } @@ -1254,7 +1101,7 @@ static TEE_Result tee_ta_init_session(TEE_ErrorOrigin *err, { TEE_Result res; struct tee_ta_ctx *ctx; - kta_signed_header_t *ta = NULL; + struct shdr *ta = NULL; uint32_t handle = 0; struct tee_ta_session *s = calloc(1, sizeof(struct tee_ta_session)); @@ -1285,7 +1132,7 @@ static TEE_Result tee_ta_init_session(TEE_ErrorOrigin *err, if (res != TEE_SUCCESS) goto out; - res = tee_ta_init_session_with_signed_ta(ta, s); + res = tee_ta_init_session_with_signed_ta(uuid, ta, s); /* * Free normal world shared memory now that the TA either has been * copied into secure memory or the TA failed to be initialized. @@ -1520,16 +1367,6 @@ TEE_Result tee_ta_get_client_id(TEE_Identity *id) return TEE_SUCCESS; } -uintptr_t tee_ta_get_exec(const struct tee_ta_ctx *const ctx) -{ - if ((ctx->flags & TA_FLAG_EXEC_DDR) == 0) { - return tee_mm_get_smem(ctx->mm); - } else { - return tee_mmu_get_load_addr(ctx) + sizeof(ta_head_t) + - ctx->head->nbr_func * sizeof(ta_func_head_t); - } -} - TEE_Result tee_ta_verify_session_pointer(struct tee_ta_session *sess, struct tee_ta_session_head *open_sessions) @@ -1614,19 +1451,17 @@ static void dump_state(struct tee_ta_ctx *ctx) char uuid[TEE_UUID_STRING_LEN]; bool active __unused; - uuid2str(uuid, &ctx->head->uuid); + uuid2str(uuid, &ctx->uuid); active = ((tee_ta_get_current_session(&s) == TEE_SUCCESS) && s && s->ctx == ctx); EMSG_RAW("Status of TA %s (%p)", uuid, (void *)ctx); EMSG_RAW("- load addr : 0x%x ctx-idr: %d %s", ctx->load_addr, ctx->context, active ? "(active)" : ""); - EMSG_RAW("- code area : 0x%" PRIxPTR " ro:%u rw:%u zi:%u", - tee_mm_get_smem(ctx->mm), ctx->head->ro_size, - ctx->head->rw_size, ctx->head->zi_size); - EMSG_RAW("- heap/stack: 0x%" PRIxPTR " stack:%zu", - tee_mm_get_smem(ctx->mm_heap_stack), - ctx->stack_size); + EMSG_RAW("- code area : 0x%" PRIxPTR " %zu", + tee_mm_get_smem(ctx->mm), tee_mm_get_bytes(ctx->mm)); + EMSG_RAW("- stack: 0x%" PRIxPTR " stack:%zu", + tee_mm_get_smem(ctx->mm_stack), ctx->stack_size); } void tee_ta_dump_current(void) diff --git a/core/arch/arm/mm/tee_mmu.c b/core/arch/arm/mm/tee_mmu.c index cf40c72b52c..1e301d7d3f1 100644 --- a/core/arch/arm/mm/tee_mmu.c +++ b/core/arch/arm/mm/tee_mmu.c @@ -270,16 +270,16 @@ TEE_Result tee_mmu_map(struct tee_ta_ctx *ctx, struct tee_ta_param *param) goto exit; /* - * Map heap and stack + * Map stack */ - smem = tee_mm_get_smem(ctx->mm_heap_stack); + smem = tee_mm_get_smem(ctx->mm_stack); if (core_va2pa((void *)smem, &pa)) { res = TEE_ERROR_SECURITY; goto exit; } tee_mmu_umap_set_pa(ctx->mmu->table + TEE_MMU_UMAP_HEAP_STACK_IDX, CORE_MMU_USER_CODE_SIZE, - pa, tee_mm_get_bytes(ctx->mm_heap_stack), + pa, tee_mm_get_bytes(ctx->mm_stack), TEE_MMU_UDATA_ATTR | TEE_MMU_UCACHE_DEFAULT_ATTR); /* diff --git a/core/arch/arm/plat-hikey/conf.mk b/core/arch/arm/plat-hikey/conf.mk index abe840e4cc9..906b9a51a6d 100644 --- a/core/arch/arm/plat-hikey/conf.mk +++ b/core/arch/arm/plat-hikey/conf.mk @@ -20,7 +20,6 @@ CFG_SECURE_TIME_SOURCE_CNTPCT ?= y CFG_PL011 ?= y CFG_HWSUPP_MEM_PERM_PXN ?= y CFG_WITH_STACK_CANARIES ?= y -CFG_NO_TA_HASH_SIGN ?= y CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= n CFG_GENERIC_BOOT ?= y CFG_PM_STUBS ?= y diff --git a/core/arch/arm/plat-mediatek/conf.mk b/core/arch/arm/plat-mediatek/conf.mk index 27c632cea9a..41b09fa5bd0 100644 --- a/core/arch/arm/plat-mediatek/conf.mk +++ b/core/arch/arm/plat-mediatek/conf.mk @@ -20,7 +20,6 @@ CFG_SECURE_TIME_SOURCE_CNTPCT ?= y CFG_8250_UART ?= y CFG_HWSUPP_MEM_PERM_PXN ?= y CFG_WITH_STACK_CANARIES ?= y -CFG_NO_TA_HASH_SIGN ?= y CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= n CFG_GENERIC_BOOT ?= y CFG_PM_STUBS ?= y diff --git a/core/arch/arm/plat-stm/conf.mk b/core/arch/arm/plat-stm/conf.mk index 9aea6c51a24..3efb959568b 100644 --- a/core/arch/arm/plat-stm/conf.mk +++ b/core/arch/arm/plat-stm/conf.mk @@ -19,7 +19,6 @@ CFG_GENERIC_BOOT ?= y CFG_WITH_SOFTWARE_PRNG ?= n CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y CFG_MMU_V7_TTB ?= y -CFG_NO_TA_HASH_SIGN ?= y CFG_PL310_LOCKED ?= n CFG_TEE_GDB_BOOT ?= y CFG_BOOT_SYNC_CPU ?= y diff --git a/core/arch/arm/plat-sunxi/conf.mk b/core/arch/arm/plat-sunxi/conf.mk index 854fc643a05..fa8f5410277 100644 --- a/core/arch/arm/plat-sunxi/conf.mk +++ b/core/arch/arm/plat-sunxi/conf.mk @@ -22,5 +22,4 @@ CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y core-platform-cppflags += -DTEE_USE_DLMALLOC core-platform-cppflags += -D_USE_SLAPORT_LIB -core-platform-cppflags += -DCFG_NO_TA_HASH_SIGN CFG_GIC := y diff --git a/core/arch/arm/plat-vexpress/conf.mk b/core/arch/arm/plat-vexpress/conf.mk index f7760effe0d..c3a259cc530 100644 --- a/core/arch/arm/plat-vexpress/conf.mk +++ b/core/arch/arm/plat-vexpress/conf.mk @@ -28,7 +28,6 @@ CFG_PM_STUBS := y CFG_GENERIC_BOOT := y CFG_TEE_CORE_EMBED_INTERNAL_TESTS ?= y CFG_TEE_FS_KEY_MANAGER_TEST := y -CFG_NO_TA_HASH_SIGN ?= y ifeq ($(PLATFORM_FLAVOR),juno) CFG_CRYPTO_SHA256_ARM32_CE ?= $(CFG_ARM32_core) diff --git a/core/core.mk b/core/core.mk index 3e38c257c55..01fecd6d493 100644 --- a/core/core.mk +++ b/core/core.mk @@ -69,8 +69,16 @@ include mk/lib.mk # # Do main source # + subdirs = $(core-platform-subdirs) core include mk/subdir.mk + +# Generate C file to embed public key for TA verification +gen-srcs += core/ta_pub_key.c +$(out-dir)/core/ta_pub_key.c: $(TA_SIGN_KEY) + @$(cmd-echo-silent) ' GEN $@' + @$(q)scripts/pem_to_pub_c.py --prefix ta_pub_key --key $< --out $@ + include mk/compile.mk include $(platform-dir)/link.mk diff --git a/core/default_signing.properties b/core/default_signing.properties deleted file mode 100644 index fd6c7dbfeb6..00000000000 --- a/core/default_signing.properties +++ /dev/null @@ -1,11 +0,0 @@ -PAYLOAD_HASH_TYPE=SHA256_HASH -LOAD_ADDRESS=0x0 -START_ADDRESS=0x0 -DMA_FLAG=false -PKA_FLAG=false -BUFFER_SIZE=8k -SW_VERSION=0 -MAJOR_BUILD_VERSION=0 -MINOR_BUILD_VERSION=0 -FLAGS=0 -TRUSTED_APP_HASH_TYPE=SHA256_HASH diff --git a/core/include/kernel/tee_ta_manager.h b/core/include/kernel/tee_ta_manager.h index a6af57bf7a5..4d70a327d1d 100644 --- a/core/include/kernel/tee_ta_manager.h +++ b/core/include/kernel/tee_ta_manager.h @@ -28,14 +28,10 @@ #ifndef TEE_TA_MANAGER_H #define TEE_TA_MANAGER_H +#include +#include #include - -#include "tee_api_types.h" -#include "tee_api_types.h" -#include "tee_ta.h" -#include -#include "tee_ta_manager_unpg.h" -#include "utee_types.h" +#include /* Magic TEE identity pointer: set when teecore requests a TA close */ #define KERN_IDENTITY ((TEE_Identity *)-1) @@ -99,11 +95,6 @@ void tee_ta_set_current_session(struct tee_ta_session *sess); TEE_Result tee_ta_get_client_id(TEE_Identity *id); -/* - * Get pointer of executable part of the TA located in virtual kernel memory - */ -uintptr_t tee_ta_get_exec(const struct tee_ta_ctx *const ctx); - /* Returns OK is sess is a valid session pointer or static TA */ TEE_Result tee_ta_verify_session_pointer(struct tee_ta_session *sess, struct tee_ta_session_head diff --git a/core/include/kernel/tee_ta_manager_unpg.h b/core/include/kernel/tee_ta_manager_unpg.h index 67e9a19ccf5..33023d959d5 100644 --- a/core/include/kernel/tee_ta_manager_unpg.h +++ b/core/include/kernel/tee_ta_manager_unpg.h @@ -31,7 +31,6 @@ #include #include -#include #include #include #if defined(CFG_SE_API) @@ -49,6 +48,12 @@ TAILQ_HEAD(tee_storage_enum_head, tee_storage_enum); /* Context of a loaded TA */ struct tee_ta_ctx { + TEE_UUID uuid; + tee_uaddr_t open_session_func; + tee_uaddr_t close_session_func; + tee_uaddr_t invoke_command_func; + size_t stack_size; /* size of stack */ + uint32_t flags; /* TA_FLAGS from TA header */ TAILQ_ENTRY(tee_ta_ctx) link; /* list of sessions opened by this TA */ struct tee_ta_session_head open_sessions; @@ -58,16 +63,11 @@ struct tee_ta_ctx { struct tee_obj_head objects; /* List of storage enumerators opened by this TA */ struct tee_storage_enum_head storage_enums; - ta_head_t *head; /* ptr to the ta head in secure memory */ - uintptr_t mem_swap; /* ptr to code and data in memory swap */ tee_mm_entry_t *mm; /* secure world memory */ - tee_mm_entry_t *mm_heap_stack; /* shared section of heap and stack */ - size_t stack_size; /* size of stack */ + tee_mm_entry_t *mm_stack;/* stack */ uint32_t load_addr; /* elf load addr (from TAs address space) */ uint32_t context; /* Context ID of the process */ struct tee_mmu_info *mmu; /* Saved MMU information (ddr only) */ - uint32_t num_res_funcs; /* number of reserved ta_func_head_t (2 or 0) */ - uint32_t flags; /* TA_FLAGS from sub header */ uint32_t panicked; /* True if TA has panicked, written from asm */ uint32_t panic_code; /* Code supplied for panic */ uint32_t ref_count; /* Reference counter for multi session TA */ diff --git a/core/include/signed_hdr.h b/core/include/signed_hdr.h new file mode 100644 index 00000000000..01a329da6d4 --- /dev/null +++ b/core/include/signed_hdr.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2015, Linaro Limited + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. 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. + * + * 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 HOLDER 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. + */ +#ifndef SIGNED_HDR_H +#define SIGNED_HDR_H + +#include + +enum shdr_img_type { + SHDR_TA = 0, +}; + +#define SHDR_MAGIC 0x4f545348 + +/** + * struct shdr - signed header + * @magic: magic number must match SHDR_MAGIC + * @img_type: image type, values defined by enum shdr_img_type + * @img_size: image size in bytes + * @algo: algorithm, defined by public key algorithms TEE_ALG_* + * from TEE Internal API specification + * @hash_size: size of the signed hash + * @sig_size: size of the signature + * @hash: hash of an image + * @sig: signature of @hash + */ +struct shdr { + uint32_t magic; + uint32_t img_type; + uint32_t img_size; + uint32_t algo; + uint16_t hash_size; + uint16_t sig_size; + /* + * Commented out element used to visualize the layout dynamic part + * of the struct. + * + * hash is accessed through the macro SHDR_GET_HASH and + * signature is accessed through the macro SHDR_GET_SIG + * + * uint8_t hash[hash_size]; + * uint8_t sig[sig_size]; + */ +}; + +#define SHDR_GET_SIZE(x) (sizeof(struct shdr) + (x)->hash_size + \ + (x)->sig_size) +#define SHDR_GET_HASH(x) (uint8_t *)(((struct shdr *)(x)) + 1) +#define SHDR_GET_SIG(x) (SHDR_GET_HASH(x) + (x)->hash_size) + +#endif /*SIGNED_HDR_H*/ + diff --git a/core/include/kernel/tee_ta.h b/core/include/ta_pub_key.h similarity index 57% rename from core/include/kernel/tee_ta.h rename to core/include/ta_pub_key.h index a25dde919fb..d6ad73a3162 100644 --- a/core/include/kernel/tee_ta.h +++ b/core/include/ta_pub_key.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, STMicroelectronics International N.V. + * Copyright (c) 2015, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -24,54 +24,14 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ +#ifndef KERNEL_TA_PUB_KEY_H +#define KERNEL_TA_PUB_KEY_H -#ifndef TEE_TA_H -#define TEE_TA_H +#include -#include -#include +extern const uint32_t ta_pub_key_exponent; +extern const uint8_t ta_pub_key_modulus[]; +extern const size_t ta_pub_key_modulus_size; -#define TA_HASH_SIZE 32 -#define TA_UUID_CLOCK_SIZE 8 -#define TA_SIGNATURE_SIZE 264 +#endif /*KERNEL_TA_PUB_KEY_H*/ -#define TA_HEAD_FLAG_MASK 0xFFF00000UL -#define TA_HEAD_GOT_MASK 0xFFFFUL - -/* Trusted Application header */ -typedef struct { - TEE_UUID uuid; - uint32_t nbr_func; - uint32_t ro_size; - uint32_t rw_size; - uint32_t zi_size; - uint32_t rel_dyn_got_size; - uint32_t hash_type; - /* uint32_t prop_tracelevel; */ -} ta_head_t; - -struct ta_rel_dyn { - uint32_t addr; - uint32_t info; -}; - -/*----------------------------------------------------------------------------- - signed header - ta_head_t - ta_func_head_t (1) - ta_func_head_t (2) - ... - ta_func_head_t (N) N = ta_head(_t).nbr_func - func_1 - func_1 - ... - func_N - GOT - find_service_addr - hash_1 - hash_2 - ... - hash_M - *---------------------------------------------------------------------------*/ - -#endif diff --git a/core/tee/tee_svc.c b/core/tee/tee_svc.c index f15f7389e9f..3a867f1c0cd 100644 --- a/core/tee/tee_svc.c +++ b/core/tee/tee_svc.c @@ -260,7 +260,7 @@ TEE_Result tee_svc_sys_get_property(uint32_t prop, tee_uaddr_t buf, size_t blen) if (blen < sizeof(TEE_UUID)) return TEE_ERROR_SHORT_BUFFER; return tee_svc_copy_to_user(sess, (void *)buf, - &sess->ctx->head->uuid, + &sess->ctx->uuid, sizeof(TEE_UUID)); default: if (blen < tee_props_lut[prop].len) @@ -454,6 +454,7 @@ static TEE_Result tee_svc_update_out_param( (called_sess->ctx->static_ta != NULL) || ((called_sess->ctx->flags & TA_FLAG_USER_MODE) != 0); + tee_ta_set_current_session(sess); abi_user32_param_to_param(callee_params, usr_param, param->types); @@ -550,7 +551,7 @@ TEE_Result tee_svc_open_ta_session(const TEE_UUID *dest, goto function_exit; clnt_id->login = TEE_LOGIN_TRUSTED_APP; - memcpy(&clnt_id->uuid, &sess->ctx->head->uuid, sizeof(TEE_UUID)); + memcpy(&clnt_id->uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); res = tee_svc_copy_param(sess, NULL, param_types, usr_param, param, tmp_buf_pa, &mm_param); @@ -609,7 +610,7 @@ TEE_Result tee_svc_close_ta_session(TEE_TASessionHandle ta_sess) return res; clnt_id.login = TEE_LOGIN_TRUSTED_APP; - memcpy(&clnt_id.uuid, &sess->ctx->head->uuid, sizeof(TEE_UUID)); + memcpy(&clnt_id.uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); tee_ta_set_current_session(NULL); res = tee_ta_close_session((struct tee_ta_session *)ta_sess, @@ -645,7 +646,7 @@ TEE_Result tee_svc_invoke_ta_command(TEE_TASessionHandle ta_sess, return res; clnt_id.login = TEE_LOGIN_TRUSTED_APP; - memcpy(&clnt_id.uuid, &sess->ctx->head->uuid, sizeof(TEE_UUID)); + memcpy(&clnt_id.uuid, &sess->ctx->uuid, sizeof(TEE_UUID)); res = tee_svc_copy_param(sess, called_sess, param_types, usr_param, ¶m, tmp_buf_pa, &mm_param); @@ -887,8 +888,7 @@ TEE_Result tee_svc_get_time(enum utee_time_category cat, TEE_Time *mytime) res = tee_time_get_sys_time(&t); break; case UTEE_TIME_CAT_TA_PERSISTENT: - res = tee_time_get_ta_time((const void *)&s->ctx->head->uuid, - &t); + res = tee_time_get_ta_time((const void *)&s->ctx->uuid, &t); break; case UTEE_TIME_CAT_REE: res = tee_time_get_ree_time(&t); @@ -921,7 +921,7 @@ TEE_Result tee_svc_set_ta_time(const TEE_Time *mytime) if (res != TEE_SUCCESS) return res; - return tee_time_set_ta_time((const void *)&s->ctx->head->uuid, &t); + return tee_time_set_ta_time((const void *)&s->ctx->uuid, &t); } #ifdef CFG_CACHE_API diff --git a/core/tee/tee_svc_storage.c b/core/tee/tee_svc_storage.c index 45c722a423a..26f3ad81588 100644 --- a/core/tee/tee_svc_storage.c +++ b/core/tee/tee_svc_storage.c @@ -110,7 +110,7 @@ static char *tee_svc_storage_create_filename(struct tee_ta_session *sess, if (file == NULL) return NULL; - pos = tee_b2hs((uint8_t *)&sess->ctx->head->uuid, file, + pos = tee_b2hs((uint8_t *)&sess->ctx->uuid, file, sizeof(TEE_UUID), hslen); file[pos] = '/'; pos++; @@ -136,7 +136,7 @@ static char *tee_svc_storage_create_dirname(struct tee_ta_session *sess) if (dir == NULL) return NULL; - tee_b2hs((uint8_t *)&sess->ctx->head->uuid, dir, sizeof(TEE_UUID), + tee_b2hs((uint8_t *)&sess->ctx->uuid, dir, sizeof(TEE_UUID), hslen); return (char *)dir; @@ -434,7 +434,7 @@ TEE_Result tee_svc_storage_obj_open(uint32_t storage_id, void *object_id, if (res != TEE_SUCCESS) goto exit; - res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id, + res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, object_id_len, flags, &po); if (res != TEE_SUCCESS) goto exit; @@ -543,7 +543,7 @@ TEE_Result tee_svc_storage_obj_create(uint32_t storage_id, void *object_id, if (res != TEE_SUCCESS) goto err; - res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id, + res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, object_id_len, flags, &po); if (res != TEE_SUCCESS) goto err; @@ -766,7 +766,7 @@ TEE_Result tee_svc_storage_obj_rename(uint32_t obj, void *object_id, } /* reserve dest name */ - res = tee_pobj_get((void *)&sess->ctx->head->uuid, object_id, + res = tee_pobj_get((void *)&sess->ctx->uuid, object_id, object_id_len, TEE_DATA_FLAG_ACCESS_WRITE_META, &po); if (res != TEE_SUCCESS) goto exit; diff --git a/documentation/build_system.md b/documentation/build_system.md index 181380c142a..035e27caa3a 100644 --- a/documentation/build_system.md +++ b/documentation/build_system.md @@ -81,7 +81,7 @@ contains: - In `include/`: header files for the above libraries - In `mk/`: **ta_dev_kit.mk**, which is a Make include file with suitable rules to build a TA, and its dependencies - - `scripts/fix_ta_binary`: a Perl script used by ta_dev_kit.mk. + - `scripts/sign.py`: a Python script used by ta_dev_kit.mk to sign TAs. - In `src`: **user_ta_header.c** and **user_ta_elf_arm.lds**: source file and linker script to add a suitable header to the Trusted Application (as expected by the loader code in the TEE Core) diff --git a/documentation/optee_design.md b/documentation/optee_design.md index 90d509a0743..a7a63b08501 100644 --- a/documentation/optee_design.md +++ b/documentation/optee_design.md @@ -505,7 +505,31 @@ layer allows for replacing the default implementation, as explained in Will be written soon. # 11. Trusted Applications -Will be written soon. +## Format +Trusted Applications consists of a signed ELF file. + +The format a TA is: +``` + + +``` + +Where `` is the content of a standard ELF file and `` +consists of: + +| Type | Name | Comment | +|------|------|---------| +| `uint32_t` | magic | Holds the magic number `0x4f545348` | +| `uint32_t` | img_type | image type, values defined by enum shdr_img_type | +| `uint32_t` | img_size | image size in bytes | +| `uint32_t` | algo | algorithm, defined by public key algorithms `TEE_ALG_*` from TEE Internal API specification | +| `uint16_t` | hash_size | size of the signed hash | +| `uint16_t` | sig_size | size of the signature | +| `uint8_t[hash_size]` | hash | Hash of the fields above and the `` above | +| `uint8_t[sig_size]` | signature | Signature of hash | + + +## Will be written soon. ### Initialize context ### Open Session ### Invoke command diff --git a/keys/default_ta.pem b/keys/default_ta.pem new file mode 100644 index 00000000000..a8e5dcdfe4f --- /dev/null +++ b/keys/default_ta.pem @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEAploYrcCzzuMMkCt9QJusu1pJiEIKseCSwIaR5p7voOHxL5D2 +Zt3qFVrAKLSd31IMbqXGGUOsaajyX/5gAKXSOswSAfNbugxRHCz0sHe51nI1HA9z +zS8W+bqJhKCbv4tbf+iLi5/IceocbB8AoO7KPr8YjlebSGbri9RAUa6GoYb40Av6 +ti4lLgX/dgFG1z3rH3z83x6Ci16wyqPqFr4tblRQnLhB7xfHf2BUqvlwoPiYLoL5 +jF/7nIiOd7Aycpka4ARevx2q9/AFPLSV3U26OnGh+HKOHZjjE7rKsCe/h1lUJ/jo +7MaFN9I6leSlCZrQH6OGsJLYAh4zddsmvyf8NQIDAQABAoIBAEoooBfVcFMqpM8g +lBXZUIe1GFLGHj5t/v4U/7Xv5KO0FfE+jpoNE+2xJzj+S+LikOhCvq1Enff8eRCS +NfoT8kSD9QMpmhq2ovIMmIiS1yXihAqeWOF/vJ5XqjaV4tjhJ0k+Qfdco98knscU +ixMzYLXYOvo509/TAe60EHhZdWtMKCmHqvFBRDhYFF+HUxWnJa39G1u828ljv8uN +iRCXbEjoaWDwBJWRzDZJehrkQc2gQAkFpyePVqA3wm1tx1ZHEVwCqYOXOP49/LAc +rQfoWUpm4chjEHnZEb+dQxa3N8Qeq2lqgcqrOX8NIfpzWTWQ1JM+ksinQwMJ0BDV ++Lf1nAECgYEA2KBBtsj41ITez8iA0DpXovH1F9oU9aJ9JKopNos8zIZg012bE5Ib +kFII0LiBGKLUP2PepTsPDIOxibLQDojg1aBGHISZVp/y81B4Rk7Wwg206ZQ848dM +AhACIrzOtJLoVEZTPf7C5QrNMhViyf2c8vFBjfTuM7Ze6a0fsvfJ2ikCgYEAxJaO +XKnOgKoG1Fe9JVM01U+260BEybNUbbXQCnvMjTSZCsOEmST9mhXhC56lhCNqmynt +FxNuq/JMwtS3TRhrYCPPCLFly+JNTqUS1mLQ9ytVbaw6fp9mSxFUQE9d9obkGwJC +3uXEx+bc7YSGuwD34wikX0tB1zzGIXRH2JlB6y0CgYEAgFlDVjdxJwmqslXL7JQE +xKizXPR7oqYpm4WucYDB/zRHPjSh41CYQEQ6sOAArUYcl4pmqmN5oSKOGFX37ASx +oiEaKV9vMuIGIp+1A4NGvyc734FTKmo04Kv3d/mCR38bZINeYscFVou11EzTgXZg +fZjwDFnooH8XcUCAHZuu3zECgYEAt6pltSMcgE7Z9JdIas/TI5vHLQEtgzhdH+bm +SHUjRaWnekvy3VWW7deVGtMMlmi0V+US0iVgl5rXposv+gJfh0HNUrTSg2qZiWlm +MQ+/Zb2BoeZv/A8Wdfnpue+svP+Hq8gwC6mlcJI7RFk1uw8LiXxwfWuFRv9LqMPH +wBBnar0CgYAJF3ukzm7rnut19lzS4r1uEIuuPwk/DjEkkil7U9wE5fr+ds5rCtXj +9591DLHrtE/CBOWym2+tIDr7OnmfU+934524mtLWVZdf39/DFM9Fc1VaSualrj/1 +BOLhBb7MEZqN7hHcQP7+49YW72GgX3pm0Ov5ke33FzN3ubIwAS6T7A== +-----END RSA PRIVATE KEY----- diff --git a/lib/libutee/arch/arm/user_ta_entry.c b/lib/libutee/arch/arm/user_ta_entry.c index 548752c2392..98bafbc8b6e 100644 --- a/lib/libutee/arch/arm/user_ta_entry.c +++ b/lib/libutee/arch/arm/user_ta_entry.c @@ -37,8 +37,6 @@ #include #include -/* From user_ta_header.c, built within TA */ -extern const size_t ta_data_size; /* Exported to user_ta_header.c, built within TA */ @@ -64,7 +62,9 @@ TAILQ_HEAD_INITIALIZER(ta_sessions); static uint32_t ta_ref_count; static bool context_init; -extern uint8_t *ta_heap_base; +/* From user_ta_header.c, built within TA */ +extern uint8_t ta_heap[]; +extern const size_t ta_heap_size; uint32_t ta_param_types; TEE_Param ta_params[TEE_NUM_PARAMS]; @@ -102,7 +102,7 @@ static TEE_Result ta_header_add_session(uint32_t session_id) if (!context_init) { trace_set_level(tahead_get_trace_level()); - malloc_init(ta_heap_base, ta_data_size); + malloc_init(ta_heap, ta_heap_size); _TEE_MathAPI_Init(); context_init = true; } diff --git a/lib/libutee/include/user_ta_header.h b/lib/libutee/include/user_ta_header.h index c38d13d1367..cc7061abd65 100644 --- a/lib/libutee/include/user_ta_header.h +++ b/lib/libutee/include/user_ta_header.h @@ -30,60 +30,6 @@ #include -/* - * The generic format of a TA header. - * - * signed_header - * ta_head_t - * ta_func_head_t (1) - * ta_func_head_t (2) - * ... - * ta_func_head_t (N) N = ta_head(_t).nbr_func - * func_1 - * func_1 - * ... - * func_N - * hash_1 - * hash_2 - * ... - * hash_M - * - * The currently this format is limited to N = 5, resulting in a TA header as - * - * signed_header - * struct user_ta_head - * struct user_ta_func_head (1) - * struct user_ta_func_head (2) - * struct user_ta_func_head (3) - * struct user_ta_sub_head - * - * Note that the last two func heads are replaced by struct user_ta_sub_head. - */ - -struct user_ta_head { - TEE_UUID uuid; - uint32_t nbr_func; - uint32_t ro_size; - uint32_t rw_size; - uint32_t zi_size; - uint32_t got_size; - uint32_t hash_type; -}; - -#define USER_TA_HEAD_FLAG_USER_MODE 0x80000000UL -#define USER_TA_HEAD_FLAG_DDR_EXEC 0x40000000UL - -struct user_ta_func_head { - uint32_t cmd_id; - uint32_t start; /* offset to start func */ -}; - -struct user_ta_sub_head { - uint32_t flags; - uint32_t spare; - uint32_t heap_size; - uint32_t stack_size; -}; #define TA_FLAG_USER_MODE (1 << 0) #define TA_FLAG_EXEC_DDR (1 << 1) @@ -98,6 +44,15 @@ struct user_ta_sub_head { #define TA_FLAG_REMAP_SUPPORT (1 << 6) /* use map/unmap syscalls */ #define TA_FLAG_CACHE_MAINTENANCE (1 << 7) /* use cache flush syscall */ +struct ta_head { + TEE_UUID uuid; + uint32_t stack_size; + uint32_t flags; + uint32_t open_session; + uint32_t close_session; + uint32_t invoke_command; +}; + #define TA_PROP_STR_SINGLE_INSTANCE "gpd.ta.singleInstance" #define TA_PROP_STR_MULTI_SESSION "gpd.ta.multiSession" #define TA_PROP_STR_KEEP_ALIVE "gpd.ta.instanceKeepAlive" diff --git a/mk/cleanvars.mk b/mk/cleanvars.mk index abbdfee9868..cba4db187ec 100644 --- a/mk/cleanvars.mk +++ b/mk/cleanvars.mk @@ -1,5 +1,6 @@ # Cleans all output variables from other make files to allow for a new start +gen-srcs := srcs := objs := libfiles := diff --git a/mk/compile.mk b/mk/compile.mk index 44748de553d..d085c6efa96 100644 --- a/mk/compile.mk +++ b/mk/compile.mk @@ -141,4 +141,8 @@ endef $(foreach f, $(srcs), $(eval $(call \ process_srcs,$(f),$(out-dir)/$(base-prefix)$$(basename $f).o))) +# Handle generated source files, that is, files that are compiled from out-dir +$(foreach f, $(gen-srcs), $(eval $(call \ + process_srcs,$(out-dir)/$(f),$(out-dir)/$(base-prefix)$$(basename $f).o))) + $(objs): $(conf-file) diff --git a/mk/config.mk b/mk/config.mk index 6466267055a..55e6415096c 100644 --- a/mk/config.mk +++ b/mk/config.mk @@ -84,3 +84,6 @@ CFG_TEE_FW_MANUFACTURER ?= FW_MAN_UNDEF # Encrypted File System Support CFG_ENC_FS ?= y + +# Embed public part of this key in OP-TEE OS +TA_SIGN_KEY ?= keys/default_ta.pem diff --git a/scripts/pem_to_pub_c.py b/scripts/pem_to_pub_c.py new file mode 100755 index 00000000000..47c004da2da --- /dev/null +++ b/scripts/pem_to_pub_c.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python +# +# Copyright (c) 2015, Linaro Limited +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. 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. +# +# 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 HOLDER 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. +# + +def get_args(): + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument('--prefix', required=True, \ + help='Prefix for the public key exponent and modulus in c file') + + parser.add_argument('--out', required=True, \ + help='Name of c file for the public key') + + parser.add_argument('--key', required=True, help='Name of key file') + + return parser.parse_args() + +def main(): + import array + from Crypto.PublicKey import RSA + from Crypto.Util.number import long_to_bytes + + args = get_args(); + + f = open(args.key, 'r') + key = RSA.importKey(f.read()) + f.close + + f = open(args.out, 'w') + + f.write("#include \n"); + f.write("#include \n\n"); + + f.write("const uint32_t " + args.prefix + "_exponent = " + + str(key.publickey().e) + ";\n\n") + + f.write("const uint8_t " + args.prefix + "_modulus[] = {\n") + i = 0; + for x in array.array("B", long_to_bytes(key.publickey().n)): + f.write("0x" + '{0:02x}'.format(x) + ",") + i = i + 1; + if i % 8 == 0: + f.write("\n"); + else: + f.write(" "); + f.write("};\n"); + + f.write("const size_t " + args.prefix + "_modulus_size = sizeof(" + \ + args.prefix + "_modulus);\n") + + f.close() + +if __name__ == "__main__": + main() diff --git a/scripts/sign.py b/scripts/sign.py new file mode 100755 index 00000000000..f407f3beebb --- /dev/null +++ b/scripts/sign.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python +# +# Copyright (c) 2015, Linaro Limited +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright notice, +# this list of conditions and the following disclaimer. +# +# 2. 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. +# +# 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 HOLDER 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. +# + +def get_args(): + from argparse import ArgumentParser + + parser = ArgumentParser() + parser.add_argument('--key', required=True, help='Name of key file') + parser.add_argument('--in', required=True, dest='inf', \ + help='Name of in file') + parser.add_argument('--out', required=True, help='Name of out file') + return parser.parse_args() + +def main(): + from Crypto.Signature import PKCS1_v1_5 + from Crypto.Hash import SHA256 + from Crypto.PublicKey import RSA + import struct + + args = get_args() + + f = open(args.key, 'rb') + key = RSA.importKey(f.read()) + f.close() + + f = open(args.inf, 'rb') + img = f.read() + f.close() + + signer = PKCS1_v1_5.new(key) + h = SHA256.new() + + digest_len = h.digest_size + sig_len = len(signer.sign(h)) + img_size = len(img) + + magic = 0x4f545348 # SHDR_MAGIC + img_type = 0 # SHDR_TA + algo = 0x70004830 # TEE_ALG_RSASSA_PKCS1_V1_5_SHA256 + shdr = struct.pack(' \n"; - exit(1); -} - -usage if ($#ARGV < 1); - -my $verbose = 0; - -if ($ARGV[0] =~ m/^-v$/) { - $verbose = 1; - shift @ARGV; -} - -usage if ($#ARGV != 1); -my ($elf, $bin) = @ARGV; - -open(BIN, "+<$bin") || die("Error opening TA file $bin"); -binmode(BIN); - -my $readelf = "readelf"; - -# In some build environments $READELF is not defined. -# As a 2nd alternative we use the environment variable $CROSS_COMPILE_user_ta -# to target the correct "readelf" - -if ($READELF) { - $readelf = $READELF -} -elsif ($CROSS_COMPILE_user_ta) { - $readelf = "${CROSS_COMPILE_user_ta}readelf" -} - -my $readelfcmd = "$readelf -s -W $elf"; -print "$readelfcmd\n" if ($verbose); -open(ELF, "$readelfcmd|") || die "Error exec $readelfcmd"; - -my $offs_0x14; -my $offs_0x14sym = "linker_RO_sections_size"; -my $offs_0x18; -my $offs_0x18sym = "linker_RW_sections_size"; -my $offs_0x1c; -my $offs_0x1csym = "linker_res_funcs_ZI_sections_size"; -my $offs_0x20; -my $offs_0x20sym = "linker_rel_dyn_GOT"; - -sub read_value -{ - my @args = split; - my $value = $args[1]; - return $value; -} - -while () { - last if defined $offs_0x14 && defined $offs_0x18 && - defined $offs_0x1c && defined $offs_0x20; - #print "Got $_"; - my @line = split; - my $line_elems = @line; - if ($line_elems > 6 && $line[6] =~ m/^ABS$/) { - if ($_ =~ m/$offs_0x14sym/) { - $offs_0x14 = read_value($_); - } elsif ($_ =~ m/$offs_0x18sym/) { - $offs_0x18 = read_value($_); - } elsif ($_ =~ m/$offs_0x1csym/) { - $offs_0x1c = read_value($_); - } elsif ($_ =~ m/$offs_0x20sym/) { - $offs_0x20 = read_value($_); - } - } -} - -die "Didn't find required symbol $offs_0x14sym in $elf" - unless defined $offs_0x14; -die "Didn't find required symbol $offs_0x18sym in $elf" - unless defined $offs_0x18; -die "Didn't find required symbol $offs_0x1csym in $elf" - unless defined $offs_0x1c; -die "Didn't find required symbol $offs_0x20sym in $elf" - unless defined $offs_0x20; - -sub write_value -{ - my ($val, $offs, $sym) = @_; - printf("%s = 0x%08x offset 0x%x\n", $sym, $val, $offs) if $verbose; - my $b = pack( 'V', $val); - seek(BIN, $offs, 0) || die "Couldn't seek to $_[1]: $!\n"; - syswrite(BIN, $b, 4) || die "$!"; -} - -write_value(hex $offs_0x14, 0x14, $offs_0x14sym); -write_value(hex $offs_0x18, 0x18, $offs_0x18sym); -write_value(hex $offs_0x1c, 0x1c, $offs_0x1csym); -write_value(hex $offs_0x20, 0x20, $offs_0x20sym); - -close(BIN); -close(ELF); -exit; - diff --git a/ta/arch/arm/link.mk b/ta/arch/arm/link.mk index f3a7fb4a2d3..abc89c5a984 100644 --- a/ta/arch/arm/link.mk +++ b/ta/arch/arm/link.mk @@ -3,14 +3,14 @@ link-out-dir = $(out-dir) link-script = $(TA_DEV_KIT_DIR)/src/user_ta_elf_arm.lds link-script-pp = $(link-out-dir)/ta.lds -FIX_TA_BINARY = $(TA_DEV_KIT_DIR)/scripts/fix_ta_binary - +SIGN = $(TA_DEV_KIT_DIR)/scripts/sign.py +TA_SIGN_KEY ?= $(TA_DEV_KIT_DIR)/keys/default_ta.pem all: $(link-out-dir)/$(binary).elf $(link-out-dir)/$(binary).dmp \ - $(link-out-dir)/$(binary).bin + $(link-out-dir)/$(binary).stripped.elf $(link-out-dir)/$(binary).ta cleanfiles += $(link-out-dir)/$(binary).elf $(link-out-dir)/$(binary).dmp cleanfiles += $(link-out-dir)/$(binary).map -cleanfiles += $(link-out-dir)/$(binary).bin +cleanfiles += $(link-out-dir)/$(binary).stripped.elf cleanfiles += $(link-out-dir)/$(binary).ta cleanfiles += $(link-script-pp) @@ -27,13 +27,11 @@ link-ldadd += $(addprefix -L,$(libdirs)) link-ldadd += $(addprefix -l,$(call reverse,$(libnames))) ldargs-$(binary).elf := $(link-ldflags) $(objs) $(link-ldadd) - $(link-script-pp): $(link-script) $(MAKEFILE_LIST) @$(cmd-echo-silent) ' CP $@' $(q)mkdir -p $(dir $@) $(q)cp $< $@ - $(link-out-dir)/$(binary).elf: $(objs) $(libdeps) $(link-script-pp) @$(cmd-echo-silent) ' LD $@' $(q)$(LD$(sm)) $(ldargs-$(binary).elf) -o $@ @@ -42,7 +40,11 @@ $(link-out-dir)/$(binary).dmp: $(link-out-dir)/$(binary).elf @$(cmd-echo-silent) ' OBJDUMP $@' $(q)$(OBJDUMP$(sm)) -l -x -d $< > $@ -$(link-out-dir)/$(binary).bin: $(link-out-dir)/$(binary).elf +$(link-out-dir)/$(binary).stripped.elf: $(link-out-dir)/$(binary).elf @$(cmd-echo-silent) ' OBJCOPY $@' - $(q)$(OBJCOPY$(sm)) -O binary $< $@ - $(q)$(FIX_TA_BINARY) $< $@ + $(q)$(OBJCOPY$(sm)) --strip-unneeded $< $@ + +$(link-out-dir)/$(binary).ta: $(link-out-dir)/$(binary).stripped.elf \ + $(TA_SIGN_KEY) + @echo ' SIGN $@' + $(q)$(SIGN) --key $(TA_SIGN_KEY) --in $< --out $@ diff --git a/ta/arch/arm/user_ta_elf_arm.lds b/ta/arch/arm/user_ta_elf_arm.lds index e280e3414b4..a77982318e4 100644 --- a/ta/arch/arm/user_ta_elf_arm.lds +++ b/ta/arch/arm/user_ta_elf_arm.lds @@ -1,153 +1,80 @@ OUTPUT_FORMAT("elf32-littlearm") OUTPUT_ARCH(arm) -/* The format of the TA binary should be - * - * ta_head - * ta_func_head - * RO Sections - * RW Sections - * ZI Sections - */ - -SECTIONS -{ - .ta_head : {*(.ta_head)} - .ta_func_head : {*(.ta_func_head)} - - /* RO sections */ - - start_of_RO_sections = .; - - /*. = 0x00100000 */ /* uTA runs in vmem at 1st MiB */ - .text : - { - *(.text .text.*) - *(.stub) - - /* ARM glue code for ARM and thumb */ - *(.glue_7) - *(.glue_7t) - - /* - * The below input sections should not be of use, but put - * in this output section to define their position. - */ - - /* Workaround for an erratum in ARM's VFP11 coprocessor */ - *(.vfp11_veneer) - /* ARMv4 interworking compatibility */ - *(.v4_bx) - /* GCC/ld specific */ - *(.gnu.linkonce.t.*) - *(.gnu.linkonce.r.*) - *(.gnu.warning) - *(.gcc_except_table) - } - .rodata : ALIGN(4) - { - *(.rodata .rodata.*) - *(.rodata1) - . = ALIGN(4); - } - .rel.dyn : - { - start_of_rel_data_section = .; - *(.rel.data) - *(.rel.data .rel.data.* .rel.gnu.linkonce.d.*) - end_of_rel_data_section = .; - start_of_rela_data_section = .; - *(.rela.data .rela.data.* .rela.gnu.linkonce.d.*) - end_of_rela_data_section = .; - } - - . = ALIGN(4); - end_of_RO_sections = .; - - /* RW sections */ - - start_of_RW_sections = .; - start_of_GOT_sections = .; - - .data : ALIGN(4) - { - *(.got.*) - *(.got) - end_of_GOT_sections = .; - - *(.ta_heap_base) - - *(.data .data.*) - /* GCC/ld specific */ - *(.gnu.linkonce.d.*) - } - .data1 : {*(.data1)} - .tdata : {*(.tdata .tdata.*)} - - end_of_RW_sections = .; - - /* ZI sections */ - - start_of_ZI_sections = .; - - .bss : ALIGN(4) - { - *(.dynbss) - *(.bss .bss.*) - /* GCC/ld specific */ - *(.gnu.linkonce.b.*) - } - .tbss : {*(.tbss .tbss.*)} - - end_of_ZI_sections = .; - - .interp ALIGN(4) : { *(.interp) } - .hash ALIGN(4) : { *(.hash) } - .dynsym ALIGN(4) : { *(.dynsym) } - .dynstr ALIGN(4) : { *(.dynstr) } - .gnu.version ALIGN(4) : { *(.gnu.version) } - .gnu.version_d ALIGN(4) : { *(.gnu.version_d) } - .gnu.version_r ALIGN(4) : { *(.gnu.version_r) } - .dynamic ALIGN(4) : { *(.dynamic) } - - /* Stabs debugging sections. */ - .stab : { *(.stab) } - .stabstr : { *(.stabstr) } - .stab.excl : { *(.stab.excl) } - .stab.exclstr : { *(.stab.exclstr) } - .stab.index : { *(.stab.index) } - .stab.indexstr : { *(.stab.indexstr) } - .comment : { *(.comment) } - - /* - * Remove relocation information for GOT and the headers. - * All needed relocation informtion should already be matched above. - */ - .junkedrel /*ALIGN(4)*/ : - { - *(.rel.*) - *(.rela.*) - } - - PROVIDE(linker_RO_sections_size = end_of_RO_sections - start_of_RO_sections); - - linker_RW_sections_size = end_of_RW_sections - start_of_RW_sections; - - ZI_sections_size = end_of_ZI_sections - start_of_ZI_sections; - ASSERT(ZI_sections_size <= 0xfffff, "Too large ZI_sections_size") - /* - * Reserve the last two struct user_ta_func_head elements for the - * properties - */ - linker_res_funcs_ZI_sections_size = (2 << 20) + ZI_sections_size; - - GOT_sections_size = end_of_GOT_sections - start_of_GOT_sections; - rel_sections_size = end_of_rel_data_section - start_of_rel_data_section; - rela_sections_size = end_of_rela_data_section - start_of_rela_data_section; - ASSERT(rela_sections_size == 0, "Can't handle nonzero rela_sections_size") - ASSERT(GOT_sections_size <= 0xffff, "Too large GOT_sections_size") - ASSERT(rel_sections_size <= 0xffff, "Too large rel_sections_size") - linker_rel_dyn_GOT = (rel_sections_size << 16) + GOT_sections_size; +PHDRS { + rodata PT_LOAD; + rwdata PT_LOAD; + rodata2 PT_LOAD; + dyn PT_DYNAMIC; +} +SECTIONS { + .ta_head : {*(.ta_head)} :rodata + + .text : { + *(.text .text.*) + *(.stub) + *(.glue_7) + *(.glue_7t) + *(.gnu.linkonce.t.*) + /* Workaround for an erratum in ARM's VFP11 coprocessor */ + *(.vfp11_veneer) + } + .eh_frame : { *(.eh_frame) } + .rodata : { + *(.gnu.linkonce.r.*) + *(.rodata .rodata.*) + } + /* .ARM.exidx is sorted, so has to go in its own output section. */ + .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } + + .ctors : { *(.ctors) } + .dtors : { *(.dtors) } + .plt : { *(.plt) } + .got : { *(.got.plt) *(.got) } + + .rel.text : { *(.rel.text) *(.rel.gnu.linkonce.t*) } + .rela.text : { *(.rela.text) *(.rela.gnu.linkonce.t*) } + .rel.data : { *(.rel.data) *(.rel.gnu.linkonce.d*) } + .rela.data : { *(.rela.data) *(.rela.gnu.linkonce.d*) } + .rel.rodata : { *(.rel.rodata) *(.rel.gnu.linkonce.r*) } + .rela.rodata : { *(.rela.rodata) *(.rela.gnu.linkonce.r*) } + .rel.dyn : { *(.rel.dyn) } + .rel.got : { *(.rel.got) } + .rela.got : { *(.rela.got) } + .rel.ctors : { *(.rel.ctors) } + .rela.ctors : { *(.rela.ctors) } + .rel.dtors : { *(.rel.dtors) } + .rela.dtors : { *(.rela.dtors) } + .rel.init : { *(.rel.init) } + .rela.init : { *(.rela.init) } + .rel.fini : { *(.rel.fini) } + .rela.fini : { *(.rela.fini) } + .rel.bss : { *(.rel.bss) } + .rela.bss : { *(.rela.bss) } + .rel.plt : { *(.rel.plt) } + .rela.plt : { *(.rela.plt) } + + /* Page align to allow dropping execute bit for RW data */ + . = ALIGN(4096); + + .data : { *(.data .data.* .gnu.linkonce.d.*) } :rwdata + + .bss : { *(.bss .bss.* .gnu.linkonce.b.* COMMON) } + + /* Page align to separate from RW data */ + . = ALIGN(4096); + + .dynamic : { *(.dynamic) } :dyn :rodata2 + .dynsym : { *(.dynsym) } :rodata2 + .dynstr : { *(.dynstr) } + .hash : { *(.hash) } + + /DISCARD/ : { *(.interp) } + + linker_RO_sections_size = 12; + linker_RW_sections_size = 12; + linker_res_funcs_ZI_sections_size = 12; + linker_rel_dyn_GOT = 12; } diff --git a/ta/arch/arm/user_ta_header.c b/ta/arch/arm/user_ta_header.c index 034443f24da..b5f211ad660 100644 --- a/ta/arch/arm/user_ta_header.c +++ b/ta/arch/arm/user_ta_header.c @@ -58,42 +58,19 @@ void ta_entry_invoke_command(uint32_t cmd_id, uint32_t param_types, TEE_Param params[TEE_NUM_PARAMS], uint32_t session_id) __noreturn; -/* These externs are defined in the ld link script */ -extern uint32_t linker_RO_sections_size; -extern uint32_t linker_RW_sections_size; -extern uint32_t linker_res_funcs_ZI_sections_size; -extern uint32_t linker_rel_dyn_GOT; - -/* Note that cmd_id is not used in a User Mode TA */ -const struct user_ta_func_head user_ta_func_head[] - __attribute__ ((section(".ta_func_head"))) = { - { 0, (uint32_t)ta_entry_open_session }, - { 0, (uint32_t)ta_entry_close_session }, - { 0, (uint32_t)ta_entry_invoke_command }, - { (TA_FLAG_USER_MODE | TA_FLAGS), 0 /* Spare */ }, - { (TA_DATA_SIZE), (TA_STACK_SIZE) }, -}; - -const struct user_ta_head ta_head __attribute__ ((section(".ta_head"))) = { +const struct ta_head ta_head __section(".ta_head") = { /* UUID, unique to each TA */ TA_UUID, - /* Number of functions in the TA */ - sizeof(user_ta_func_head) / sizeof(struct user_ta_func_head), - /* Section size information */ - (uint32_t)&linker_RO_sections_size, - (uint32_t)&linker_RW_sections_size, - (uint32_t)&linker_res_funcs_ZI_sections_size, - (uint32_t)&linker_rel_dyn_GOT, - /* Hash type, filled in by sign-tool */ - 0, - /* TA trace level */ - /* TA_TRACE_LEVEL_DEFAULT, */ + TA_STACK_SIZE, + TA_FLAG_USER_MODE | TA_FLAGS, + (uint32_t)ta_entry_open_session, + (uint32_t)ta_entry_close_session, + (uint32_t)ta_entry_invoke_command }; -/* Filled in by TEE Core when loading the TA */ -uint8_t *ta_heap_base __attribute__ ((section(".ta_heap_base"))); - -const size_t ta_data_size = TA_DATA_SIZE; +/* Keeping the heap in bss */ +uint8_t ta_heap[TA_DATA_SIZE]; +const size_t ta_heap_size = sizeof(ta_heap); const struct user_ta_property ta_props[] = { {TA_PROP_STR_SINGLE_INSTANCE, USER_TA_PROP_TYPE_BOOL, diff --git a/ta/ta.mk b/ta/ta.mk index 70f480bd04a..650465b8aaa 100644 --- a/ta/ta.mk +++ b/ta/ta.mk @@ -100,7 +100,12 @@ ta-srcfiles = ta/arch/$(ARCH)/user_ta_header.c \ $(foreach f, $(ta-srcfiles), \ $(eval $(call copy-file, $(f), $(out-dir)/export-user_ta/src))) +# Copy keys +ta-keys = keys/default_ta.pem +$(foreach f, $(ta-keys), \ + $(eval $(call copy-file, $(f), $(out-dir)/export-user_ta/keys))) + # Copy the scripts -ta-scripts = $(wildcard ta/arch/$(ARCH)/fix_ta_binary) +ta-scripts = $(wildcard scripts/sign.py) $(foreach f, $(ta-scripts), \ $(eval $(call copy-file, $(f), $(out-dir)/export-user_ta/scripts)))