| /* |
| * Copyright (C) 2011-2016 2017 Baidu, Inc. All Rights Reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in |
| * the documentation and/or other materials provided with the |
| * distribution. |
| * * Neither the name of Baidu, Inc., nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT |
| * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| */ |
| #include <stdio.h> |
| #include <string.h> |
| #include <assert.h> |
| |
| #include <unistd.h> |
| #include <pwd.h> |
| #define MAX_PATH FILENAME_MAX |
| |
| #include "sgx_urts.h" |
| #include "sgx_tseal.h" |
| #include "app.h" |
| #include "Enclave_u.h" |
| |
| |
| sgx_enclave_id_t global_eid = 0; |
| |
| typedef struct _sgx_errlist_t { |
| sgx_status_t err; |
| const char *msg; |
| const char *sug; /* Suggestion */ |
| } sgx_errlist_t; |
| |
| /* Error code returned by sgx_create_enclave */ |
| static sgx_errlist_t sgx_errlist[] = { |
| { |
| SGX_ERROR_UNEXPECTED, |
| "Unexpected error occurred.", |
| NULL |
| }, |
| { |
| SGX_ERROR_INVALID_PARAMETER, |
| "Invalid parameter.", |
| NULL |
| }, |
| { |
| SGX_ERROR_OUT_OF_MEMORY, |
| "Out of memory.", |
| NULL |
| }, |
| { |
| SGX_ERROR_ENCLAVE_LOST, |
| "Power transition occurred.", |
| "Please refer to the sample \"PowerTransition\" for details." |
| }, |
| { |
| SGX_ERROR_INVALID_ENCLAVE, |
| "Invalid enclave image.", |
| NULL |
| }, |
| { |
| SGX_ERROR_INVALID_ENCLAVE_ID, |
| "Invalid enclave identification.", |
| NULL |
| }, |
| { |
| SGX_ERROR_INVALID_SIGNATURE, |
| "Invalid enclave signature.", |
| NULL |
| }, |
| { |
| SGX_ERROR_OUT_OF_EPC, |
| "Out of EPC memory.", |
| NULL |
| }, |
| { |
| SGX_ERROR_NO_DEVICE, |
| "Invalid SGX device.", |
| "Please make sure SGX module is enabled in the BIOS, and install SGX driver afterwards." |
| }, |
| { |
| SGX_ERROR_MEMORY_MAP_CONFLICT, |
| "Memory map conflicted.", |
| NULL |
| }, |
| { |
| SGX_ERROR_INVALID_METADATA, |
| "Invalid enclave metadata.", |
| NULL |
| }, |
| { |
| SGX_ERROR_DEVICE_BUSY, |
| "SGX device was busy.", |
| NULL |
| }, |
| { |
| SGX_ERROR_INVALID_VERSION, |
| "Enclave version was invalid.", |
| NULL |
| }, |
| { |
| SGX_ERROR_INVALID_ATTRIBUTE, |
| "Enclave was not authorized.", |
| NULL |
| }, |
| { |
| SGX_ERROR_ENCLAVE_FILE_ACCESS, |
| "Can't open enclave file.", |
| NULL |
| }, |
| }; |
| |
| /* Check error conditions for loading enclave */ |
| void print_error_message(sgx_status_t ret) |
| { |
| size_t idx = 0; |
| size_t ttl = sizeof sgx_errlist/sizeof sgx_errlist[0]; |
| |
| for (idx = 0; idx < ttl; idx++) { |
| if(ret == sgx_errlist[idx].err) { |
| if(NULL != sgx_errlist[idx].sug) |
| printf("Info: %s\n", sgx_errlist[idx].sug); |
| printf("Error: %s\n", sgx_errlist[idx].msg); |
| break; |
| } |
| } |
| |
| if (idx == ttl) |
| printf("Error: Unexpected error occurred.\n"); |
| } |
| |
| /* Initialize the enclave: |
| * Step 1: try to retrieve the launch token saved by last transaction |
| * Step 2: call sgx_create_enclave to initialize an enclave instance |
| * Step 3: save the launch token if it is updated |
| */ |
| int initialize_enclave(void) |
| { |
| char token_path[MAX_PATH] = {'\0'}; |
| sgx_launch_token_t token = {0}; |
| sgx_status_t ret = SGX_ERROR_UNEXPECTED; |
| int updated = 0; |
| |
| /* Step 1: try to retrieve the launch token saved by last transaction |
| * if there is no token, then create a new one. |
| */ |
| /* try to get the token saved in $HOME */ |
| const char *home_dir = getpwuid(getuid())->pw_dir; |
| |
| if (home_dir != NULL && |
| (strlen(home_dir)+strlen("/")+sizeof(TOKEN_FILENAME)+1) <= MAX_PATH) { |
| /* compose the token path */ |
| strncpy(token_path, home_dir, strlen(home_dir)); |
| strncat(token_path, "/", strlen("/")); |
| strncat(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)+1); |
| } else { |
| /* if token path is too long or $HOME is NULL */ |
| strncpy(token_path, TOKEN_FILENAME, sizeof(TOKEN_FILENAME)); |
| } |
| |
| FILE *fp = fopen(token_path, "rb"); |
| if (fp == NULL && (fp = fopen(token_path, "wb")) == NULL) { |
| printf("Warning: Failed to create/open the launch token file \"%s\".\n", token_path); |
| } |
| |
| if (fp != NULL) { |
| /* read the token from saved file */ |
| size_t read_num = fread(token, 1, sizeof(sgx_launch_token_t), fp); |
| if (read_num != 0 && read_num != sizeof(sgx_launch_token_t)) { |
| /* if token is invalid, clear the buffer */ |
| memset(&token, 0x0, sizeof(sgx_launch_token_t)); |
| printf("Warning: Invalid launch token read from \"%s\".\n", token_path); |
| } |
| } |
| /* Step 2: call sgx_create_enclave to initialize an enclave instance */ |
| /* Debug Support: set 2nd parameter to 1 */ |
| ret = sgx_create_enclave(ENCLAVE_FILENAME, SGX_DEBUG_FLAG, &token, &updated, &global_eid, NULL); |
| if (ret != SGX_SUCCESS) { |
| print_error_message(ret); |
| if (fp != NULL) fclose(fp); |
| return -1; |
| } |
| printf("global_eid: %ld\n", global_eid); |
| |
| /* Step 3: save the launch token if it is updated */ |
| if (updated == FALSE || fp == NULL) { |
| /* if the token is not updated, or file handler is invalid, do not perform saving */ |
| if (fp != NULL) fclose(fp); |
| return 0; |
| } |
| |
| /* reopen the file with write capablity */ |
| fp = freopen(token_path, "wb", fp); |
| if (fp == NULL) return 0; |
| size_t write_num = fwrite(token, 1, sizeof(sgx_launch_token_t), fp); |
| if (write_num != sizeof(sgx_launch_token_t)) |
| printf("Warning: Failed to save launch token to \"%s\".\n", token_path); |
| fclose(fp); |
| return 0; |
| } |
| |
| /* Application entry */ |
| int SGX_CDECL main(int argc, char *argv[]) |
| { |
| sgx_status_t sgx_ret = SGX_SUCCESS; |
| sgx_status_t enclave_ret = SGX_SUCCESS; |
| uint32_t sealed_log_size = 1024; |
| uint8_t sealed_log[1024] = {0}; |
| sgx_sealed_data_t * sealed_data = 0; |
| |
| (void)(argc); |
| (void)(argv); |
| |
| /* Initialize the enclave */ |
| if(initialize_enclave() < 0){ |
| printf("Enter a character before exit ...\n"); |
| getchar(); |
| return -1; |
| } |
| |
| sgx_ret = create_sealeddata(global_eid, &enclave_ret, sealed_log, sealed_log_size); |
| if(sgx_ret != SGX_SUCCESS) { |
| print_error_message(sgx_ret); |
| return -1; |
| } |
| if(enclave_ret != SGX_SUCCESS) { |
| print_error_message(enclave_ret); |
| return -1; |
| } |
| printf("create_sealeddata success ...\n"); |
| |
| sealed_data = (sgx_sealed_data_t *)sealed_log; |
| printf("sealed_data.key_request.key_name 0x%x\n", sealed_data->key_request.key_name); |
| printf("sealed_data.key_request.key_policy 0x%x\n", sealed_data->key_request.key_policy); |
| printf("sealed_data.plain_text_offset 0x%x\n", sealed_data->plain_text_offset); |
| printf("sealed_data.aes_data.payload_size 0x%x\n", sealed_data->aes_data.payload_size); |
| |
| sgx_ret = verify_sealeddata(global_eid, &enclave_ret, sealed_log, sealed_log_size); |
| if(sgx_ret != SGX_SUCCESS) { |
| print_error_message(sgx_ret); |
| return -1; |
| } |
| if(enclave_ret != SGX_SUCCESS) { |
| print_error_message(sgx_ret); |
| return -1; |
| } |
| |
| printf("verify_sealeddata success ...\n"); |
| |
| /* Destroy the enclave */ |
| sgx_destroy_enclave(global_eid); |
| |
| printf("Enter a character before exit ...\n"); |
| getchar(); |
| return 0; |
| } |
| |
| void ocall_print_string(const char *str, size_t len) |
| { |
| char * string = (char *)malloc(len + (size_t)sizeof(char)); |
| if (string == NULL) { |
| printf("malloc failed\n"); |
| return; |
| } |
| |
| memcpy(string, str, len); |
| char * ptr = string + len; |
| * ptr = 0; |
| printf("%s\n", string); |
| free(string); |
| } |