/* * Copyright (C) 2011-2017 Intel Corporation. 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 Intel Corporation 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 "sgx.h" #include "sgx_tseal.h" // For sgx_seal_data, sgx_calc_sealed_data_size, sgx_get_encrypt_txt_len, sgx_unseal_data #include "sgx_tae_service.h" // For create, read counters and pse_session. Also exports SGX_MC_UUID_NONCE_SIZE and SGX_MC_UUID_COUNTER_ID_SIZE, TODO: apparently also ne$ #include "sgx_uae_service.h" // for sgx_ps_get_cap and SGX_IS_MONOTONIC_COUNTER_AVAILABLE #include #include #include #include #include //#include "ProtobufSgxTransforms.h" #include "ProtobufSgxSealerTransforms.h" //class Sealer { // namespace { uint32_t verify_sgx_monotonic_counter_value(sgx_mc_uuid_t* sgx_monotonic_counter_id, uint32_t* sgx_monotonic_counter_value) { /* uint32_t ret = 0; uint32_t expected_counter_value; int busy_retry_times = 2; do{ ret = sgx_create_pse_session(); }while (ret == SGX_ERROR_BUSY && busy_retry_times--); if (ret != SGX_SUCCESS) return ret; ret = sgx_read_monotonic_counter(sgx_monotonic_counter_id,&expected_counter_value); if(ret != SGX_SUCCESS) { switch(ret) { case SGX_ERROR_SERVICE_UNAVAILABLE: // Architecture Enclave Service Manager is not installed or not working properly. break; case SGX_ERROR_SERVICE_TIMEOUT: // retry the operation later break; case SGX_ERROR_BUSY: // retry the operation later break; case SGX_ERROR_MC_NOT_FOUND: // the the Monotonic Counter ID is invalid. break; default: // other errors break; } } else if(expected_counter_value!=*sgx_monotonic_counter_value) { ret = 3; //REPLAY_DETECTED; // This must be by the OS. } sgx_close_pse_session(); */ return SGX_SUCCESS; //ret; } uint32_t create_sgx_monotonic_counter_id_and_value(sgx_mc_uuid_t* sgx_counter_id, uint32_t* sgx_counter_value) { int counter=0; for(counter=0;counter<3;counter++) { sgx_counter_id->nonce[counter]=1; } for(counter=0;counter<13;counter++) { sgx_counter_id->counter_id[counter]=1; } //sgx_counter_id->nonce={0,0,0,0}; //sgx_counter_id->counter_id={0,0,0,0,0,0,0,0,0,0,0,0,0}; *sgx_counter_value=1; /* uint32_t ret = 0; int busy_retry_times = 2; do{ ret = sgx_create_pse_session(); }while (ret == SGX_ERROR_BUSY && busy_retry_times--); if (ret != SGX_SUCCESS) return ret; ret = sgx_create_monotonic_counter(sgx_counter_id,sgx_counter_value); if(ret != SGX_SUCCESS) { switch(ret) { case SGX_ERROR_SERVICE_UNAVAILABLE: // Architecture Enclave Service Manager is not installed or not working properly break; case SGX_ERROR_SERVICE_TIMEOUT: // retry the operation latersgx_create_monotonic_counter break; case SGX_ERROR_BUSY: // retry the operation later break; case SGX_ERROR_MC_OVER_QUOTA: // SGX Platform Service enforces a quota scheme on the Monotonic Counters a SGX app can maintain. the enclave has reached the quota. break; case SGX_ERROR_MC_USED_UP: // the Monotonic Counter has been used up and cannot create Monotonic Counter anymore. break; default: // other errors break; } } sgx_close_pse_session(); // TODO: Check that we should do it here. */ return SGX_SUCCESS; // ret; } uint32_t initialize_pse_and_counter() { /* sgx_status_t sgx_ret; sgx_ps_cap_t ps_cap; memset(&ps_cap, 0, sizeof(sgx_ps_cap_t)); sgx_ret = sgx_get_ps_cap(&ps_cap); if (sgx_ret) { // printf("cannot get platform service capability, error code = 0x%d", sgx_ret); return sgx_ret; } if (!SGX_IS_MONOTONIC_COUNTER_AVAILABLE(ps_cap)) { // printf("\nmonotonic counter is not supported\n"); return SGX_ERROR_SERVICE_UNAVAILABLE; }*/ return SGX_SUCCESS; } uint32_t seal_message(std::string& plaintext_str, std::string& sgx_sealed_msg_str) { // std::string protobuf_plaintext_str; uint32_t ret; // sgx_mc_uuid_t sgx_counter_id; // uint32_t sgx_counter_value; uint8_t* sgx_sealed_msg; uint32_t expected_sealed_msg_length; /* ret = create_sgx_monotonic_counter_id_and_value(&sgx_counter_id, &sgx_counter_value); if(ret!=SGX_SUCCESS) return ret; ProtobufSgxTransforms::encode_message_and_counter_to_protobuf_string(plaintext_str, &sgx_counter_id, &sgx_counter_value, protobuf_plaintext_str); */ expected_sealed_msg_length = sgx_calc_sealed_data_size(0, 9); if(expected_sealed_msg_length == 0xFFFFFFFF) return 1; sgx_sealed_msg = (uint8_t*)malloc(expected_sealed_msg_length); // Doesn't change with protobufs - convert the data here to protobuf format after it is initialized ret = sgx_seal_data(0, NULL, 9, (uint8_t*) plaintext_str.c_str(), expected_sealed_msg_length, (sgx_sealed_data_t*) sgx_sealed_msg); sgx_sealed_msg_str = std::string((char*)sgx_sealed_msg, expected_sealed_msg_length); // TODO: Fishy conversion. free(sgx_sealed_msg); return ret; } uint32_t unseal_and_verify_sealed_message(std::string& sgx_sealed_msg_str, std::string& plaintext) { uint32_t ret = 0; uint8_t* sgx_sealed_msg; uint8_t* temp_plaintext; std::string protobuf_encoded_str; std::string decoded_plaintext; sgx_mc_uuid_t sgx_counter_id; uint32_t sgx_counter_value; uint32_t expected_plaintext_msg_length; std::vector sgx_sealed_msg_vector(sgx_sealed_msg_str.begin(), sgx_sealed_msg_str.end());// TODO: Add null termination? sgx_sealed_msg = &sgx_sealed_msg_vector[0]; expected_plaintext_msg_length = sgx_get_encrypt_txt_len((sgx_sealed_data_t*)sgx_sealed_msg); if(expected_plaintext_msg_length == 0xffffffff) return 1; // return expected_plaintext_msg_length; temp_plaintext = (uint8_t*)malloc( expected_plaintext_msg_length ); ret = sgx_unseal_data((sgx_sealed_data_t*)sgx_sealed_msg, NULL, 0, temp_plaintext, &expected_plaintext_msg_length); if(ret != SGX_SUCCESS) { free(temp_plaintext); switch(ret) { case SGX_ERROR_MAC_MISMATCH: // MAC of the sealed data is incorrect. The sealed data has been tampered. break; case SGX_ERROR_INVALID_ATTRIBUTE: // Indicates attribute field of the sealed data is incorrect. break; case SGX_ERROR_INVALID_ISVSVN: // Indicates isv_svn field of the sealed data is greater than the enclave�s ISVSVN. This is a downgraded enclave. break; case SGX_ERROR_INVALID_CPUSVN: // Indicates cpu_svn field of the sealed data is greater than the platform�s cpu_svn. enclave is on a downgraded platform. break; case SGX_ERROR_INVALID_KEYNAME: // Indicates key_name field of the sealed data is incorrect. break; default: // other errors break; } return ret; } protobuf_encoded_str = std::string((char*)temp_plaintext, expected_plaintext_msg_length); // TODO: Fishy conversion. free(temp_plaintext); /* ProtobufSgxTransforms::decode_protobuf_message_to_counter_id_and_value(protobuf_encoded_str, &sgx_counter_id, &sgx_counter_value); ret = verify_sgx_monotonic_counter_value(&sgx_counter_id, &sgx_counter_value); if (ret == SGX_SUCCESS) { ProtobufSgxTransforms::decode_protobuf_message_to_plaintext(protobuf_encoded_str, decoded_plaintext); plaintext = decoded_plaintext; } */plaintext = protobuf_encoded_str; return ret; } //}