From 1ddb8668abe3749db8c80ebbfecf4be8f3d1fe57 Mon Sep 17 00:00:00 2001 From: berinpaul Date: Wed, 17 Oct 2018 12:34:00 +0530 Subject: [PATCH] Added command in oesign to dump oeinfo and signature information #564 --- cmake/add_enclave_executable.cmake | 2 +- samples/data-sealing/enc1/Makefile | 2 +- samples/data-sealing/enc2/Makefile | 2 +- samples/data-sealing/enc3/Makefile | 2 +- samples/file-encryptor/enc/Makefile | 2 +- samples/helloworld/enc/Makefile | 2 +- samples/local_attestation/enc1/Makefile | 2 +- samples/local_attestation/enc2/Makefile | 2 +- samples/remote_attestation/enc1/Makefile | 2 +- samples/remote_attestation/enc2/Makefile | 2 +- tools/oesign/CMakeLists.txt | 2 +- tools/oesign/main.c | 203 ++++++++++++-- tools/oesign/oedump.c | 324 +++++++++++++++++++++++ 13 files changed, 516 insertions(+), 33 deletions(-) create mode 100644 tools/oesign/oedump.c diff --git a/cmake/add_enclave_executable.cmake b/cmake/add_enclave_executable.cmake index 94018e14c5..3a6432d89c 100644 --- a/cmake/add_enclave_executable.cmake +++ b/cmake/add_enclave_executable.cmake @@ -28,7 +28,7 @@ function(add_enclave_executable BIN SIGNCONF) # custom rule to sign the binary add_custom_command(OUTPUT ${BIN}.signed.so - COMMAND oesign $ ${SIGNCONF} ${CMAKE_CURRENT_BINARY_DIR}/${BIN}-private.pem + COMMAND oesign "sign" $ ${SIGNCONF} ${CMAKE_CURRENT_BINARY_DIR}/${BIN}-private.pem DEPENDS oesign ${BIN} ${SIGNCONF} ${BIN}-private.pem WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} ) diff --git a/samples/data-sealing/enc1/Makefile b/samples/data-sealing/enc1/Makefile index e01ebcde70..c55a6a70d6 100644 --- a/samples/data-sealing/enc1/Makefile +++ b/samples/data-sealing/enc1/Makefile @@ -33,7 +33,7 @@ build: $(CXX) -o enclave_a_v1.so ecalls.o dispatcher.o keys.o datasealing_t.o $(LDFLAGS) sign: - oesign enclave_a_v1.so data-sealing.conf private.pem + oesign sign enclave_a_v1.so data-sealing.conf private.pem clean: rm -f *.so *.o *.pem ../common/datasealing_t.* ../common/datasealing_args.h diff --git a/samples/data-sealing/enc2/Makefile b/samples/data-sealing/enc2/Makefile index c0e7b082b5..624dd1aec0 100644 --- a/samples/data-sealing/enc2/Makefile +++ b/samples/data-sealing/enc2/Makefile @@ -32,7 +32,7 @@ build: $(CXX) -o enclave_a_v2.so ecalls.o dispatcher.o keys.o datasealing_t.o $(LDFLAGS) sign: - oesign enclave_a_v2.so data-sealing.conf private.pem + oesign sign enclave_a_v2.so data-sealing.conf private.pem clean: rm -f *.so *.o *.pem diff --git a/samples/data-sealing/enc3/Makefile b/samples/data-sealing/enc3/Makefile index cee9f8857e..5edc148e70 100644 --- a/samples/data-sealing/enc3/Makefile +++ b/samples/data-sealing/enc3/Makefile @@ -32,7 +32,7 @@ build: $(CXX) -o enclave_b.so ecalls.o dispatcher.o keys.o datasealing_t.o $(LDFLAGS) sign: - oesign enclave_b.so data-sealing.conf private.pem + oesign sign enclave_b.so data-sealing.conf private.pem clean: rm -f *.so *.o *.pem diff --git a/samples/file-encryptor/enc/Makefile b/samples/file-encryptor/enc/Makefile index d49705dfe1..5a3a0fae48 100644 --- a/samples/file-encryptor/enc/Makefile +++ b/samples/file-encryptor/enc/Makefile @@ -33,7 +33,7 @@ build: $(CXX) -o file-encryptorenc.so ecalls.o encryptor.o keys.o fileencryptor_t.o $(LDFLAGS) sign: - oesign file-encryptorenc.so file-encryptor.conf private.pem + oesign sign file-encryptorenc.so file-encryptor.conf private.pem clean: rm -f *.so *.o fileencryptor_t.* fileencryptor_args.h private.pem public.pem diff --git a/samples/helloworld/enc/Makefile b/samples/helloworld/enc/Makefile index 37d4593188..3b8837ba4e 100644 --- a/samples/helloworld/enc/Makefile +++ b/samples/helloworld/enc/Makefile @@ -30,7 +30,7 @@ build: $(CC) -o helloworldenc.so helloworld_t.o enc.o $(LDFLAGS) sign: - oesign helloworldenc.so helloworld.conf private.pem + oesign sign helloworldenc.so helloworld.conf private.pem clean: rm -f enc.o helloworldenc.so helloworldenc.signed.so private.pem public.pem helloworld_t.o helloworld_t.h helloworld_t.c helloworld_args.h diff --git a/samples/local_attestation/enc1/Makefile b/samples/local_attestation/enc1/Makefile index a65f5db1c1..45aabe28b1 100644 --- a/samples/local_attestation/enc1/Makefile +++ b/samples/local_attestation/enc1/Makefile @@ -52,7 +52,7 @@ build: $(CXX) -o enclave1.so attestation.o crypto.o ecalls.o dispatcher.o localattestation_t.o $(LDFLAGS) sign: - oesign enclave1.so enc.conf private.pem + oesign sign enclave1.so enc.conf private.pem clean: rm -f *.o *.so ../common/localattestation_t.* ../common/localattestation_args.h *.pem enc2_pubkey.h diff --git a/samples/local_attestation/enc2/Makefile b/samples/local_attestation/enc2/Makefile index f7470416fe..94df584b05 100644 --- a/samples/local_attestation/enc2/Makefile +++ b/samples/local_attestation/enc2/Makefile @@ -52,7 +52,7 @@ build: $(CXX) -o enclave2.so attestation.o crypto.o ecalls.o dispatcher.o localattestation_t.o $(LDFLAGS) sign: - oesign enclave2.so enc.conf private.pem + oesign sign enclave2.so enc.conf private.pem clean: rm -f *.o *.so ../common/localattestation_t.* ../common/remoteattestation_args.h *.pem enc1_pubkey.h diff --git a/samples/remote_attestation/enc1/Makefile b/samples/remote_attestation/enc1/Makefile index de3ab054ca..e5ecaf36db 100644 --- a/samples/remote_attestation/enc1/Makefile +++ b/samples/remote_attestation/enc1/Makefile @@ -52,7 +52,7 @@ build: $(CXX) -o enclave1.so attestation.o crypto.o ecalls.o dispatcher.o remoteattestation_t.o $(LDFLAGS) sign: - oesign enclave1.so enc.conf private.pem + oesign sign enclave1.so enc.conf private.pem clean: rm -f *.o *.so ../common/remoteattestation_t.* ../common/remoteattestation_args.h *.pem enc2_pubkey.h diff --git a/samples/remote_attestation/enc2/Makefile b/samples/remote_attestation/enc2/Makefile index 61c13e41e8..a0639eeafb 100644 --- a/samples/remote_attestation/enc2/Makefile +++ b/samples/remote_attestation/enc2/Makefile @@ -51,7 +51,7 @@ build: $(CXX) -o enclave2.so attestation.o crypto.o ecalls.o dispatcher.o remoteattestation_t.o $(LDFLAGS) sign: - oesign enclave2.so enc.conf private.pem + oesign sign enclave2.so enc.conf private.pem clean: rm -f *.o *.so remoteattestation_t.* *.pem enc1_pubkey.h diff --git a/tools/oesign/CMakeLists.txt b/tools/oesign/CMakeLists.txt index 95a4b32e58..4bacc139b7 100644 --- a/tools/oesign/CMakeLists.txt +++ b/tools/oesign/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -add_executable(oesign main.c) +add_executable(oesign main.c oedump.c) target_link_libraries(oesign oehost) diff --git a/tools/oesign/main.c b/tools/oesign/main.c index 100d3be316..7bc1418acf 100644 --- a/tools/oesign/main.c +++ b/tools/oesign/main.c @@ -13,6 +13,8 @@ #include "../host/enclave.h" static const char* arg0; +int oedump(const char*); +int oesign(const char*, const char*, const char*); OE_PRINTF_FORMAT(1, 2) void Err(const char* format, ...) @@ -456,13 +458,23 @@ void _merge_config_file_options( properties->header.size_settings.num_tcs = options->num_tcs; } -static const char _usage[] = - "Usage: %s EnclaveImage ConfigFile KeyFile\n" +static const char _usage_gen[] = + "Usage: %s [options]\n" + "\n" + "Commands:\n" + " sign - Sign the specified enclave.\n" + " dump - Print out the Open Enclave metadata for the specified " + "enclave.\n" + "\n" + "For help with a specific command, enter \"%s -?\"\n"; + +static const char _usage_sign[] = + "Usage: %s enclave_image sign config_file key_file\n" "\n" "Where:\n" - " EnclaveImage -- path of an enclave image file\n" - " ConfigFile -- configuration file containing enclave properties\n" - " KeyFile -- private key file used to digitally sign the image\n" + " enclave_image -- path of an enclave image file\n" + " config_file -- configuration file containing enclave properties\n" + " key_file -- private key file used to digitally sign the image\n" "\n" "Description:\n" " This utility (1) injects runtime properties into an enclave image " @@ -497,14 +509,21 @@ static const char _usage[] = " The resulting image is written to .signed.so.\n" "\n"; -int main(int argc, const char* argv[]) +static const char _usage_dump[] = + "\n" + "Usage: %s dump enclave_image\n" + "\n" + "Where:\n" + " enclave_image -- path of an enclave image file\n" + "\n" + "Description:\n" + " This option dumps the oeinfo and signature information of an " + "enclave\n"; + +int oesign(const char* enclave, const char* conffile, const char* keyfile) { - arg0 = argv[0]; int ret = 1; oe_result_t result; - const char* enclave; - const char* conffile; - const char* keyfile; oe_enclave_t enc; void* pem_data = NULL; size_t pem_size; @@ -512,18 +531,6 @@ int main(int argc, const char* argv[]) oe_sgx_enclave_properties_t props; oe_sgx_load_context_t context; - /* Check arguments */ - if (argc != 4) - { - fprintf(stderr, _usage, arg0); - exit(1); - } - - /* Collect arguments */ - enclave = argv[1]; - conffile = argv[2]; - keyfile = argv[3]; - /* Load the configuration file */ if (_load_config_file(conffile, &options) != 0) { @@ -628,3 +635,155 @@ int main(int argc, const char* argv[]) return ret; } + +int dump_parser(const char* argv[]) +{ + int ret = 1; + const char* enclave; + + if (strcmp(argv[2], "-?") == 0) + { + fprintf(stderr, _usage_dump, argv[0]); + exit(1); + } + else + { + if (strstr(argv[2], "_enc") != NULL) + { + enclave = argv[2]; + /* dump oeinfo and signature information */ + ret = oedump(enclave); + } + else + { + fprintf(stderr, _usage_gen, argv[0], argv[0]); + exit(1); + } + } + + return ret; +} + +int sign_parser(int argc, const char* argv[]) +{ + int ret = 1; + const char* enclave; + const char* conffile; + const char* keyfile; + + if (strcmp(argv[2], "-?") == 0) + { + fprintf(stderr, _usage_sign, argv[0]); + exit(1); + } + else if (argc == 5) + { + if (strstr(argv[2], "enc") != NULL) + { + enclave = argv[2]; + if (strstr(argv[3], "conf") != NULL) + { + /* Collect arguments for signing*/ + conffile = argv[3]; + keyfile = argv[4]; + } + else if (strstr(argv[3], "pem") != NULL) + { + /* Collect arguments for signing*/ + keyfile = argv[3]; + conffile = argv[4]; + } + else + { + fprintf(stderr, _usage_gen, argv[0], argv[0]); + exit(1); + } + } + else if (strstr(argv[3], "enc") != NULL) + { + enclave = argv[3]; + if (strstr(argv[2], "conf") != NULL) + { + /* Collect arguments for signing*/ + conffile = argv[2]; + keyfile = argv[4]; + } + else if (strstr(argv[2], "pem") != NULL) + { + /* Collect arguments for signing*/ + keyfile = argv[2]; + conffile = argv[4]; + } + else + { + fprintf(stderr, _usage_gen, argv[0], argv[0]); + exit(1); + } + } + else if (strstr(argv[4], "enc") != NULL) + { + enclave = argv[4]; + if (strstr(argv[2], "conf") != NULL) + { + /* Collect arguments for signing*/ + conffile = argv[2]; + keyfile = argv[3]; + } + else if (strstr(argv[2], "pem") != NULL) + { + /* Collect arguments for signing*/ + keyfile = argv[2]; + conffile = argv[3]; + } + else + { + fprintf(stderr, _usage_gen, argv[0], argv[0]); + exit(1); + } + } + else + { + fprintf(stderr, _usage_gen, argv[0], argv[0]); + exit(1); + } + } + else + { + fprintf(stderr, _usage_gen, argv[0], argv[0]); + exit(1); + } + + ret = oesign(enclave, conffile, keyfile); + + return ret; +} + +int arg_handler(int argc, const char* argv[]) +{ + int ret = 1; + if ((strcmp(argv[1], "dump") == 0)) + ret = dump_parser(argv); + else if ((strcmp(argv[1], "sign") == 0)) + ret = sign_parser(argc, argv); + else + { + fprintf(stderr, _usage_gen, argv[0], argv[0]); + exit(1); + } + return ret; +} + +int main(int argc, const char* argv[]) +{ + arg0 = argv[0]; + int ret = 1; + + if (argc <= 2) + { + fprintf(stderr, _usage_gen, argv[0], argv[0]); + exit(1); + } + + ret = arg_handler(argc, argv); + return ret; +} diff --git a/tools/oesign/oedump.c b/tools/oesign/oedump.c new file mode 100644 index 0000000000..d2febe7b67 --- /dev/null +++ b/tools/oesign/oedump.c @@ -0,0 +1,324 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +size_t errors = 0; + +static bool verbose_opt = false; + +/* Find enclave property struct within an .oeinfo section */ +static oe_result_t _find_enclave_properties( + uint8_t* section_data, + size_t section_size, + oe_enclave_type_t enclave_type, + size_t struct_size, + oe_sgx_enclave_properties_t** enclave_properties) +{ + oe_result_t result = OE_UNEXPECTED; + uint8_t* ptr = section_data; + size_t bytes_remaining = section_size; + + *enclave_properties = NULL; + + /* While there are more enclave property structures */ + while (bytes_remaining >= struct_size) + { + oe_sgx_enclave_properties_t* p = (oe_sgx_enclave_properties_t*)ptr; + + if (p->header.enclave_type == enclave_type) + { + if (p->header.size != struct_size) + { + result = OE_FAILURE; + goto done; + } + + /* Found it! */ + *enclave_properties = p; + break; + } + + /* If size of structure extends beyond end of section */ + if (p->header.size > bytes_remaining) + break; + + ptr += p->header.size; + bytes_remaining -= p->header.size; + } + + if (*enclave_properties == NULL) + { + result = OE_NOT_FOUND; + goto done; + } + + result = OE_OK; + +done: + return result; +} + +oe_result_t oe_sgx_load_properties( + const elf64_t* elf, + const char* section_name, + oe_sgx_enclave_properties_t* properties) +{ + oe_result_t result = OE_UNEXPECTED; + uint8_t* section_data; + size_t section_size; + + if (properties) + memset(properties, 0, sizeof(*properties)); + + /* Check for null parameter */ + if (!elf || !section_name || !properties) + { + result = OE_INVALID_PARAMETER; + goto done; + } + + /* Get pointer to and size of the given section */ + if (elf64_find_section(elf, section_name, §ion_data, §ion_size) != + 0) + { + result = OE_NOT_FOUND; + goto done; + } + + /* Find SGX enclave property struct */ + { + oe_sgx_enclave_properties_t* enclave_properties; + + if ((result = _find_enclave_properties( + section_data, + section_size, + OE_ENCLAVE_TYPE_SGX, + sizeof(oe_sgx_enclave_properties_t), + &enclave_properties)) != OE_OK) + { + result = OE_NOT_FOUND; + goto done; + } + + OE_CHECK( + oe_memcpy_s( + properties, + sizeof(*properties), + enclave_properties, + sizeof(*enclave_properties))); + } + + result = OE_OK; + +done: + return result; +} + +OE_PRINTF_FORMAT(1, 2) +void err(const char* fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + fprintf(stderr, "*** Error: "); + vfprintf(stderr, fmt, ap); + fprintf(stderr, "\n"); + va_end(ap); + errors++; +} + +void dump_entry_point(elf64_t* elf) +{ + elf64_sym_t sym; + const char* name; + + if (elf64_find_dynamic_symbol_by_address( + elf, elf64_get_header(elf)->e_entry, STT_FUNC, &sym) != 0) + { + err("cannot find entry point symbol"); + return; + } + + if (!(name = elf64_get_string_from_dynstr(elf, sym.st_name))) + { + err("cannot resolve entry point name"); + return; + } + + if (strcmp(name, "_start") != 0) + { + err("invalid entry point name: %s", name); + return; + } + + printf("=== Entry point: \n"); + printf("name=%s\n", name); + printf("address=%016llx\n", OE_LLX(sym.st_value)); + printf("\n"); +} + +void dump_enclave_properties(const oe_sgx_enclave_properties_t* props) +{ + const sgx_sigstruct_t* sigstruct; + + printf("=== SGX Enclave Properties:\n"); + + printf("product_id=%u\n", props->config.product_id); + + printf("security_version=%u\n", props->config.security_version); + + bool debug = props->config.attributes & OE_SGX_FLAGS_DEBUG; + printf("debug=%u\n", debug); + + printf( + "num_heap_pages=%llu\n", + OE_LLU(props->header.size_settings.num_heap_pages)); + + printf( + "num_stack_pages=%llu\n", + OE_LLU(props->header.size_settings.num_stack_pages)); + + printf("num_tcs=%llu\n", OE_LLU(props->header.size_settings.num_tcs)); + + sigstruct = (const sgx_sigstruct_t*)props->sigstruct; + + printf("mrenclave="); + oe_hex_dump(sigstruct->enclavehash, sizeof(sigstruct->enclavehash)); + + printf("signature="); + oe_hex_dump(sigstruct->signature, sizeof(sigstruct->signature)); + + printf("\n"); + + if (verbose_opt) + __sgx_dump_sigstruct(sigstruct); +} + +typedef struct _visit_sym_data +{ + const elf64_t* elf; + const elf64_shdr_t* shdr; + oe_result_t result; +} visit_sym_data_t; + +static int _visit_sym(const elf64_sym_t* sym, void* data_) +{ + int rc = -1; + visit_sym_data_t* data = (visit_sym_data_t*)data_; + const elf64_shdr_t* shdr = data->shdr; + const char* name; + + data->result = OE_UNEXPECTED; + + /* Skip symbol if not a function */ + if ((sym->st_info & 0x0F) != STT_FUNC) + { + rc = 0; + goto done; + } + + /* Skip symbol if not in the ".ecall" section */ + if (sym->st_value < shdr->sh_addr || + sym->st_value + sym->st_size > shdr->sh_addr + shdr->sh_size) + { + rc = 0; + goto done; + } + + /* Skip null names */ + if (!(name = elf64_get_string_from_dynstr(data->elf, sym->st_name))) + { + rc = 0; + goto done; + } + + /* Dump the ECALL name */ + printf("%s (%016llx)\n", name, OE_LLX(sym->st_value)); + + rc = 0; + +done: + return rc; +} + +void dump_ecall_section(elf64_t* elf) +{ + elf64_shdr_t shdr; + + printf("=== ECALLs:\n"); + + /* Find the .ecall section */ + if (elf64_find_section_header(elf, ".ecall", &shdr) != 0) + { + err("missing .ecall section"); + return; + } + + /* Dump all the ECALLs */ + { + visit_sym_data_t data; + data.elf = elf; + data.shdr = &shdr; + + if (elf64_visit_symbols(elf, _visit_sym, &data) != 0) + { + err("failed to find ECALLs in .ecall section"); + return; + } + } + + printf("\n"); +} + +int oedump(const char* enc_bin) +{ + int ret = 1; + elf64_t elf; + oe_sgx_enclave_properties_t props; + + /* Load the ELF-64 object */ + if (elf64_load(enc_bin, &elf) != 0) + { + fprintf(stderr, "failed to load %s\n", enc_bin); + goto done; + } + + /* Load the SGX enclave properties */ + if (oe_sgx_load_properties(&elf, OE_INFO_SECTION_NAME, &props) != OE_OK) + { + err("failed to load SGX enclave properties from %s section", + OE_INFO_SECTION_NAME); + } + + printf("\n"); + + /* Dump the entry point */ + dump_entry_point(&elf); + + /* Dump the signature section */ + dump_enclave_properties(&props); + + /* Dump the ECALL section */ + dump_ecall_section(&elf); + + if (errors) + { + fprintf(stderr, "*** Found %zu errors\n", errors); + goto done; + } + + ret = 0; + +done: + elf64_unload(&elf); + return ret; +}