/* * 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.challa * */ #define SGX_DH_MAC_SIZE 16 #define SGX_TARGET_INFO_RESERVED1_BYTES 4 #define SGX_TARGET_INFO_RESERVED2_BYTES 456 #define SGX_ECP256_KEY_SIZE 32 #define SGX_CPUSVN_SIZE 16 #define SGX_REPORT_DATA_SIZE 64 #define SGX_MAC_SIZE 16 /* Message Authentication Code - 16 bytes */ #define SGX_KEYID_SIZE 32 #define SGX_HASH_SIZE 32 /* SHA256 */ #define SGX_REPORT_BODY_RESERVED1 28 #define SGX_REPORT_BODY_RESERVED2 32 #define SGX_REPORT_BODY_RESERVED3 96 #define SGX_REPORT_BODY_RESERVED4 60 // App.cpp : Defines the entry point for the console application. #include #include #include "../Decryptor/Decryptor_u.h" #include "sgx_eid.h" #include "sgx_urts.h" #define __STDC_FORMAT_MACROS #include #include // For ecdsa signing key generation #include "sgx_tcrypto.h" // For socket programming #include #include #include #include #include #include // For google proto buffers #include "dhmsgs.pb.h" #include #include #include using namespace google::protobuf::io; #define UNUSED(val) (void)(val) #define TCHAR char #define _TCHAR char #define _T(str) str #define scanf_s scanf #define _tmain main // Not sure if I need this later - as such, I (decryptor app) will only ever need to talk to 1 enclave at a time - verifier enclave first and then the apache enclave. //extern std::mapg_enclave_id_map; sgx_enclave_id_t e2_enclave_id = 0; #define Decryptor_PATH "libDecryptor.so" int fit_32_into_uint8_t(google::protobuf::uint32 temp32, uint8_t* temp8) { if(temp32 > UINT8_MAX) return -1; else { // *temp8 = *(uint8_t*)&temp32; // Probably works irrespective of endianness but not sure. *temp8 = (uint8_t)temp32; return 0; } } int fit_32_into_uint16_t(google::protobuf::uint32 temp32, uint16_t* temp16) { if(temp32 > UINT16_MAX) return -1; else { // *temp8 = *(uint8_t*)&temp32; // Probably works irrespective of endianness but not sure. *temp16 = (uint16_t)temp32; return 0; } } // Sets up a socket to bind and listen to the given port. Returns FD of the socket on success, -1 on failure (and prints a msg to stdout with the errno) int set_up_socket(int port, sockaddr_in* address) { int server_fd = 0; // Creating socket file descriptor for listening for attestation requests. server_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0); if (server_fd == -1) { printf("Error in creating a socket - %d", errno); return -1; } // Preparing the address struct for binding address->sin_family = AF_INET; address->sin_addr.s_addr = INADDR_ANY; // Todo: should this be localhost? address->sin_port = htons(port); // memset(address->sin_zero,0,sizeof(address->sin_zero)); socklen_t addrlen = sizeof(*address); // Binding if (bind(server_fd, (sockaddr*)address, addrlen)<0) { printf("Error in binding %d - port was %d - ", errno, port); return -1; } // Listening if (listen(server_fd, 128) < 0) { printf("Error in listening %d", errno); return -1; } return server_fd; } void encode_ec256_public_key_to_protobuf(protobuf_sgx_ec256_public_t* protobuf_g_a , sgx_ec256_public_t* g_a) { int counter; google::protobuf::uint32 temp32; for(counter=0;countergx[counter]; protobuf_g_a->add_gx(temp32); temp32 = g_a->gy[counter]; protobuf_g_a->add_gy(temp32); } } int decode_ec256_public_key_from_protobuf(protobuf_sgx_ec256_public_t* protobuf_g_a , sgx_ec256_public_t* g_a) { printf("\n ec256 pub key\n"); int counter; google::protobuf::uint32 temp32; for(counter=0;countergx(counter); if(fit_32_into_uint8_t(temp32, &(g_a->gx[counter]))!=0) return -1; printf("%d ",g_a->gx[counter]); temp32 = protobuf_g_a->gy(counter); if(fit_32_into_uint8_t(temp32, &(g_a->gy[counter]))!=0) return -1; printf("%d ",g_a->gy[counter]); } return 0; } void encode_attributes_to_protobuf(protobuf_sgx_attributes_t* protobuf_attributes, sgx_attributes_t* attributes) { protobuf_attributes->set_flags(attributes->flags); // 64 bit protobuf_attributes->set_xfrm(attributes->xfrm); // 64 bit } int decode_attributes_from_protobuf(protobuf_sgx_attributes_t* protobuf_attributes, sgx_attributes_t* attributes) { attributes->flags = protobuf_attributes->flags(); printf("\n flags %" PRIu64 " \n", attributes->flags); attributes->xfrm = protobuf_attributes->xfrm(); printf("\n xfrm %" PRIu64 " \n", attributes->xfrm); return 0; } void encode_report_to_protobuf(protobuf_sgx_report_t* protobuf_report, sgx_report_t* report) { int counter; google::protobuf::uint32 temp32; for(counter=0;counterkey_id.id[counter]; protobuf_report->add_key_id(temp32); } for(counter=0;countermac[counter]; protobuf_report->add_mac(temp32); } protobuf_report->mutable_body()->set_misc_select(report->body.misc_select); // 32 bit protobuf_report->mutable_body()->set_isv_svn(report->body.isv_svn); // 16 bit protobuf_report->mutable_body()->set_isv_prod_id(report->body.isv_prod_id); // 16 bit encode_attributes_to_protobuf(protobuf_report->mutable_body()->mutable_attributes(), &(report->body.attributes)); for(counter=0;counterbody.cpu_svn.svn[counter]; protobuf_report->mutable_body()->add_cpu_svn(temp32); } for(counter=0;counterbody.reserved1[counter]; // TODO: Could be optimized out - if these are determined to be 0s. protobuf_report->mutable_body()->add_reserved1(temp32); } for(counter=0;counterbody.reserved2[counter]; // TODO: Could be optimized out - if these are determined to be 0s. protobuf_report->mutable_body()->add_reserved2(temp32); } for(counter=0;counterbody.reserved3[counter]; // TODO: Could be optimized out - if these are determined to be 0s. protobuf_report->mutable_body()->add_reserved3(temp32); } for(counter=0;counterbody.reserved4[counter]; // TODO: Could be optimized out - if these are determined to be 0s. protobuf_report->mutable_body()->add_reserved4(temp32); } for(counter=0;counterbody.mr_enclave.m[counter]; protobuf_report->mutable_body()->add_mr_enclave(temp32); } for(counter=0;counterbody.mr_signer.m[counter]; protobuf_report->mutable_body()->add_mr_signer(temp32); } for(counter=0;counterbody.report_data.d[counter]; protobuf_report->mutable_body()->add_report_data(temp32); } } int decode_report_from_protobuf(protobuf_sgx_report_t* protobuf_report, sgx_report_t* report) { int counter; google::protobuf::uint32 temp32; printf("\nreport body keyid\n"); for(counter=0;counterkey_id(counter); if(fit_32_into_uint8_t(temp32, &(report->key_id.id[counter]))!=0) return -1; printf("%d ", report->key_id.id[counter]); } printf("\nreport mac\n"); for(counter=0;countermac(counter); if(fit_32_into_uint8_t(temp32, &(report->mac[counter]))!=0) return -1; printf("%d ", report->mac[counter]); } report->body.misc_select=protobuf_report->mutable_body()->misc_select(); // 32 bit temp32=protobuf_report->mutable_body()->isv_svn(); if(fit_32_into_uint16_t(temp32, &(report->body.isv_svn))!=0) return -1; printf("\nmisc select %d \n", report->body.misc_select); temp32=protobuf_report->mutable_body()->isv_prod_id(); if(fit_32_into_uint16_t(temp32, &(report->body.isv_prod_id))!=0) return -1; printf("\nprod id %d \n", report->body.isv_prod_id); decode_attributes_from_protobuf(protobuf_report->mutable_body()->mutable_attributes(), &(report->body.attributes)); printf("\n cpu svn\n"); for(counter=0;countermutable_body()->cpu_svn(counter); if(fit_32_into_uint8_t(temp32, &(report->body.cpu_svn.svn[counter]))!=0) return -1; printf("%d ", report->body.cpu_svn.svn[counter]); } printf("\n reserved1 \n"); for(counter=0;countermutable_body()->reserved1(counter); if(fit_32_into_uint8_t(temp32, &(report->body.reserved1[counter]))!=0) return -1; printf("%d ", report->body.reserved1[counter]); } printf("\n reserved2 \n"); for(counter=0;countermutable_body()->reserved2(counter); if(fit_32_into_uint8_t(temp32, &(report->body.reserved2[counter]))!=0) return -1; printf("%d ", report->body.reserved2[counter]); } printf("\n reserved3 \n"); for(counter=0;countermutable_body()->reserved3(counter); if(fit_32_into_uint8_t(temp32, &(report->body.reserved3[counter]))!=0) return -1; printf("%d ", report->body.reserved3[counter]); } printf("\n reserved4 \n"); for(counter=0;countermutable_body()->reserved4(counter); if(fit_32_into_uint8_t(temp32, &(report->body.reserved4[counter]))!=0) return -1; printf("%d ", report->body.reserved4[counter]); } printf("\n mrenclave \n"); for(counter=0;countermutable_body()->mr_enclave(counter); if(fit_32_into_uint8_t(temp32, &(report->body.mr_enclave.m[counter]))!=0) return -1; printf("%x ", report->body.mr_enclave.m[counter]); } printf("\n mrsigner \n"); for(counter=0;countermutable_body()->mr_signer(counter); if(fit_32_into_uint8_t(temp32, &(report->body.mr_signer.m[counter]))!=0) return -1; printf("%x ", report->body.mr_signer.m[counter]); } printf("\n report data\n"); for(counter=0;countermutable_body()->report_data(counter); if(fit_32_into_uint8_t(temp32, &(report->body.report_data.d[counter]))!=0) return -1; printf("%d ", report->body.report_data.d[counter]); } return 0; } void encode_msg1_to_protobuf( protobuf_sgx_dh_msg1_t& protobuf_dhmsg1, sgx_dh_msg1_t* native_dhmsg1) { int counter; google::protobuf::uint32 temp32; // google::protobuf::uint64 temp64; encode_ec256_public_key_to_protobuf(protobuf_dhmsg1.mutable_g_a(), &(native_dhmsg1->g_a)); for(counter=0;countertarget.mr_enclave.m[counter]; protobuf_dhmsg1.mutable_target()->add_mr_enclave(temp32); } for(counter=0;countertarget.reserved1[counter]; protobuf_dhmsg1.mutable_target()->add_reserved1(temp32); } for(counter=0;countertarget.reserved2[counter]; protobuf_dhmsg1.mutable_target()->add_reserved2(temp32); } encode_attributes_to_protobuf(protobuf_dhmsg1.mutable_target()->mutable_attributes(), &(native_dhmsg1->target.attributes)); temp32=native_dhmsg1->target.misc_select ; protobuf_dhmsg1.mutable_target()->set_misc_select(temp32); } void encode_msg3_to_protobuf(protobuf_sgx_dh_msg3_t& protobuf_dhmsg3, sgx_dh_msg3_t* native_dhmsg3) { int counter; google::protobuf::uint32 temp32; for(counter=0;countercmac[counter]; protobuf_dhmsg3.add_cmac(temp32); } encode_report_to_protobuf(protobuf_dhmsg3.mutable_msg3_body()->mutable_report(), &(native_dhmsg3->msg3_body.report)); int max_counter=native_dhmsg3->msg3_body.additional_prop_length; unsigned char*temp; for(counter=0,temp=native_dhmsg3->msg3_body.additional_prop;counteradd_additional_prop(*temp); } } int decode_msg2_from_protobuf(protobuf_sgx_dh_msg2_t& protobuf_dhmsg2, sgx_dh_msg2_t* native_dhmsg2) { int counter; google::protobuf::uint32 temp32; //google::protobuf::uint64 temp64; printf("\ncmac\n"); for(counter=0;countercmac[counter]))!=0) return -1; printf("%d ",native_dhmsg2->cmac[counter]); } if(decode_ec256_public_key_from_protobuf(protobuf_dhmsg2.mutable_g_b(), &(native_dhmsg2->g_b)) !=0) return -1; if(decode_report_from_protobuf(protobuf_dhmsg2.mutable_report(), &(native_dhmsg2->report)) !=0) return -1; return 0; } int print_initialized_msg1( protobuf_sgx_dh_msg1_t& protobuf_dhmsg1, sgx_dh_msg1_t* native_dhmsg1) { int counter; printf("gx\n"); for(counter=0;counterg_a.gx[counter]); } printf("\ngy\n"); for(counter=0;counterg_a.gy[counter]); } printf("\nmrenclave in target\n"); for(counter=0;countertarget.mr_enclave.m[counter]); } printf("\nreserved1 in target\n"); for(counter=0;countertarget.reserved1[counter]); } printf("\nreserved2 in target\n"); for(counter=0;countertarget.reserved2[counter]); } printf("\n %" PRIu64 "\n", native_dhmsg1->target.attributes.flags); printf("\n %" PRIu64 "\n", protobuf_dhmsg1.target().attributes().flags()); printf("\n %" PRIu64 "\n", native_dhmsg1->target.attributes.xfrm); printf("\n %" PRIu64 "\n", protobuf_dhmsg1.target().attributes().xfrm()); printf("\n %" PRIu32 "\n", native_dhmsg1->target.misc_select); printf("\n %" PRIu32 "\n", protobuf_dhmsg1.target().misc_select()); return 0; } int read_protobuf_msg_from_fd(int accept_fd, google::protobuf::MessageLite& message) { ZeroCopyInputStream* raw_input; CodedInputStream* coded_input; uint32_t size; CodedInputStream::Limit limit; raw_input = new FileInputStream(accept_fd); coded_input = new CodedInputStream(raw_input); if(!coded_input->ReadVarint32(&size)) { printf("Error in reading size of msg"); fflush(stdout); return -1; } //printf("size of msg was read to be %" PRIu32 " \n", size); fflush(stdout); limit = coded_input->PushLimit(size); if(!message.ParseFromCodedStream(coded_input)) { printf("Error in parsing msg"); fflush(stdout); return -1; } coded_input->PopLimit(limit); return 0; } int write_protobuf_msg_to_fd(int accept_fd, google::protobuf::MessageLite& message) { ZeroCopyOutputStream* raw_output = new FileOutputStream(accept_fd); CodedOutputStream* coded_output = new CodedOutputStream(raw_output); coded_output->WriteVarint32(message.ByteSize()); if(!message.SerializeToCodedStream(coded_output)) { printf("SerializeToCodedStream failed"); fflush(stdout); return -1; } // As per this - https://stackoverflow.com/questions/22881876/protocol-buffers-how-to-serialize-and-deserialize-multiple-messages-into-a-file?noredirect=1&lq=1 // TODO: There may be a better way to do this - 1) this happens with every accept now and 2) make it happen on the stack vs heap - destructor will be called on return from this function (main) and the items will then be written out. (We probably don't want that, actually) delete coded_output; delete raw_output; fflush(stdout); return 0; } int _tmain(int argc, _TCHAR* argv[]) { uint32_t ret_status; sgx_status_t status; // For sgx setup int launch_token_updated; sgx_launch_token_t launch_token; // declare msg1, msg2, msg3 protobuf objects and native SGX structs protobuf_sgx_dh_msg1_t protobuf_msg1; protobuf_sgx_dh_msg2_t protobuf_msg2; protobuf_sgx_dh_msg3_t protobuf_msg3; // For sgx - ecalls and storing msgs rcvd from pipes for processing. uint32_t session_id; sgx_dh_msg1_t dh_msg1; //Diffie-Hellman Message 1 sgx_dh_msg2_t dh_msg2; //Diffie-Hellman Message 2 sgx_dh_msg3_t dh_msg3; //Diffie-Hellman Message 3 sgx_key_128bit_t dh_aek; // Session Key // initializing native sgx structs memset(&dh_aek,0, sizeof(sgx_key_128bit_t)); memset(&dh_msg1, 0, sizeof(sgx_dh_msg1_t)); memset(&dh_msg2, 0, sizeof(sgx_dh_msg2_t)); memset(&dh_msg3, 0, sizeof(sgx_dh_msg3_t)); // For socket to listen to the Apache enclave. int apache_port = 3825; int server_fd=0; int accept_fd = 0; struct sockaddr_in own_addr; struct sockaddr_storage apache_addr; socklen_t apache_addr_size = sizeof(apache_addr); int counter; UNUSED(argc); UNUSED(argv); server_fd=set_up_socket(apache_port, &own_addr); if(server_fd==-1) return -1; printf("Successfully set up a socket to communicate with the Apache enclave."); fflush(stdout); status = sgx_create_enclave(Decryptor_PATH, SGX_DEBUG_FLAG, &launch_token, &launch_token_updated, &e2_enclave_id, NULL); if(status != SGX_SUCCESS) { printf("\nLoad Enclave Failure"); close(server_fd); return -1; } printf("\nDecryptor - EnclaveID %" PRIx64, e2_enclave_id); fflush(stdout); // Generating a signing ECDSA key to sign the encryption key. sgx_ec256_public_t pub_key; Decryptor_create_ecdsa_signing_key_pair(e2_enclave_id, &ret_status, &pub_key); if(ret_status != SGX_SUCCESS) { printf("\n error in generating the ecdsa signing key pair \n"); fflush(stdout); return 0xFFFFFFFF; } printf("\n Generated the ecdsa key pair successfully - gx, gy\n"); fflush(stdout); for(counter=0; counter