123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308 |
- // Knows only protobuf_sgx objects, protobuf header.
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include<unistd.h>
- #include <stdio.h>
- #include "ProtobufLAMessages.pb.h"
- #include <google/protobuf/io/coded_stream.h>
- #include <google/protobuf/io/zero_copy_stream_impl.h>
- using namespace google::protobuf::io;
- #include "SgxProtobufLAInitiator.h"
- #include "crypto.h"
- // For socket programming
- #include <arpa/inet.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- int global_decryptor_fd;
- // TODO: Make these private functions
- 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\n");
- fflush(stdout);
- return -1;
- }
- printf("size of msg was read to be %d \n", size);
- fflush(stdout);
- limit = coded_input->PushLimit(size);
- if(!message.ParseFromCodedStream(coded_input))
- {
- printf("Error in parsing msg\n");
- fflush(stdout);
- return -1;
- }
- printf("Done parsing msg\n"); fflush(stdout);
- coded_input->PopLimit(limit);
- return 0;
- }
- // TODO: private functions
- 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\n");
- 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;
- }
- // Sets up a socket connected to the port passed as input - returns the socket FD on success and -1 on error.
- // Also prints the errno on error.
- int set_up_socket_connect(int port)
- {
- int sock = 0;
- if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
- {
- printf("\n Error in socket call - errno is %d \n", errno);
- return -1;
- }
- struct sockaddr_in serv_addr;
- memset(&serv_addr, '0', sizeof(serv_addr));
- serv_addr.sin_family = AF_INET;
- serv_addr.sin_port = htons(port);
- // Convert IPv4 and IPv6 addresses from text to binary form
- if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
- {
- printf("\nError in inet_pton - errno is %d\n", errno);
- return -1;
- }
- if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
- {
- printf("\nError in connect - errno is %d \n", errno);
- return -1;
- }
- return sock;
- }
- int local_attestation_initiator(int port, unsigned char* base64_encoded_token)
- {
- // declare msg1, msg2, msg3 protobuf objects
- protobuf_sgx_dh_msg1_t protobuf_msg1;
- protobuf_sgx_dh_msg2_t protobuf_msg2;
- protobuf_sgx_dh_msg3_t protobuf_msg3;
- uint32_t protobuf_sgx_ret;
- // uint8_t encrypted_hash[32]; uint8_t encrypted_tag[16]; size_t post_la_bytes_written;
- // uint8_t tokenT_and_tag[176]; size_t bytes_read;
- // For socket to listen to the Apache enclave.
- // int server_fd=0; int accept_fd = 0;
- // std::string protobuf_encrypted_msg_string(protobuf_encrypted_msg.msg());
- // memcpy(tokenT_and_tag, protobuf_encrypted_msg_string.c_str(), 176);
- // struct sockaddr_in own_addr;
- // struct sockaddr_storage apache_addr; socklen_t apache_addr_size = sizeof(apache_addr);
- uint32_t session_id;
- // int counter;
- int decryptor_fd;
- setbuf(stdout,NULL);
- decryptor_fd=set_up_socket_connect(port);
- if(decryptor_fd == -1)
- {
- perror("\nCould not set up the socket: had the following error: ");
- fflush(stderr);
- }
- // printf("");
- if(read_protobuf_msg_from_fd(decryptor_fd, protobuf_msg1)!=0)
- return -1;
- protobuf_sgx_ret = process_protobuf_dh_msg1_generate_protobuf_dh_msg2(protobuf_msg1, protobuf_msg2, &session_id);
- if(protobuf_sgx_ret != 0)
- {
- printf("Error in process_protobuf_dh_msg1_generate_protobuf_dh_msg2: 0x%x", protobuf_sgx_ret); fflush(stdout); return protobuf_sgx_ret;
- }
- if(write_protobuf_msg_to_fd(decryptor_fd, protobuf_msg2)!=0)
- return -1;
- if(read_protobuf_msg_from_fd(decryptor_fd, protobuf_msg3)!=0)
- return -1;
- protobuf_sgx_ret = process_protobuf_dh_msg3(protobuf_msg3, &session_id);
- if(protobuf_sgx_ret != 0)
- {
- printf("Error in process_protobuf_dh_msg3: 0x%x", protobuf_sgx_ret); fflush(stdout); return protobuf_sgx_ret;
- }
- unsigned char tokenT_and_tag[176]; int protobuf_encrypted_msg_size;
- protobuf_post_LA_encrypted_msg_t protobuf_encrypted_msg;
- if(read_protobuf_msg_from_fd(decryptor_fd, protobuf_encrypted_msg)!=0)
- {
- printf("Not all of the post-LA message was read\n"); fflush(stdout); return 0xfe;
- }
- std::string protobuf_encrypted_msg_string(protobuf_encrypted_msg.msg());
- memcpy(tokenT_and_tag, protobuf_encrypted_msg_string.c_str(), 176);
- printf("Read encrypted signature and tag from the decryptor socket.\n"); fflush(stdout);
- uint32_t count;
- printf("Encrypted data:\n");
- for(count=0;count<176;count++)
- printf("0x%02x ", tokenT_and_tag[count]);
- printf("\n"); fflush(stdout);
- uint8_t plaintext_token[160]; int plaintext_length=0;
- uint32_t ret_decrypt=aes_gcm_wrapper(0, tokenT_and_tag, 160, plaintext_token, &plaintext_length, tokenT_and_tag+160);
- //int aes_cipher(int enc, unsigned char *key, unsigned char *iv, unsigned char* plaintext, int plaintext_len, unsigned char *ciphertext, int* op_ciphertext_len, unsigned char* tag);
- if(ret_decrypt!=0)
- {
- printf("Errorin decryption 0x%x", ret_decrypt); fflush(stdout); return 0xed;
- }
- printf("Decryption keypair\n");
- for(count=0;count<64;count++)
- printf("0x%02x ", plaintext_token[count]);
- printf("\n"); fflush(stdout);
- printf("Decryption verifier mrenclave\n");
- for(count=64;count<96;count++)
- printf("0x%02x ", plaintext_token[count]);
- printf("\n"); fflush(stdout);
- count=base64_encoding_wrapper(plaintext_token, base64_encoded_token, 160);
- if(count != 216)
- {
- printf("Somehow not the entire token was encoded in base64:0x%x\n", count); fflush(stdout); return 0x55;
- }
- global_decryptor_fd=decryptor_fd;
- printf("Successfully done Local attestation\n");
- fflush(stdout);
- return 0;
- }
- int extract_binary_key_and_client_ciphertext_data_from_base64(unsigned char* base64_encoded_client_pub_key, unsigned char* base64_ciphertext, uint32_t base64_ciphertext_length, unsigned char* op_client_public_key_and_ciphertext, uint32_t* op_ciphertext_length)
- {
- int openssl_ret_status;
- openssl_ret_status=base64_decoding_wrapper(base64_encoded_client_pub_key, op_client_public_key_and_ciphertext, 88);
- if(openssl_ret_status == -1)
- return 0xfe;
- *op_ciphertext_length = base64_decoding_wrapper(base64_ciphertext, op_client_public_key_and_ciphertext + 64, base64_ciphertext_length);
- if(*op_ciphertext_length == -1)
- {
- return 0x33;
- }
- return 0;
- }
- // should be called with the base64encoded public key and data to be decrypted
- // base64 encoded public key should be of length 4*(ceil(64/3)) = 88 (at least)
- int decrypt_client_data_through_decryptor(unsigned char* base64_client_public_key, unsigned char* base64_ciphertext_client_data, uint32_t base64_ciphertext_client_data_length, unsigned char* plaintext_client_data, uint32_t* op_plaintext_client_data_length)
- {
- int ret_status;
- uint32_t count;
- unsigned char* client_data_to_decryptor;
- unsigned char* client_data_encrypted_to_decryptor;
- unsigned char* client_data_from_decryptor;
- unsigned char tag[16];
- const char* msg;
- protobuf_post_LA_encrypted_msg_t protobuf_encrypted_msg;
- int output_length;
- int input_length;
- uint32_t ciphertext_length;
- for(count=0; count<base64_ciphertext_client_data_length; count++)
- plaintext_client_data[count] = base64_ciphertext_client_data[count];
- *op_plaintext_client_data_length = base64_ciphertext_client_data_length;
- client_data_to_decryptor = (unsigned char*) malloc(64 + (base64_ciphertext_client_data_length * 3/4));
- // If ciphertext_length != base64_ciphertext_client_data_length * 3/4 then it will write outside the allocated memory
- ret_status = extract_binary_key_and_client_ciphertext_data_from_base64(base64_client_public_key, base64_ciphertext_client_data, base64_ciphertext_client_data_length, client_data_to_decryptor, &ciphertext_length);
- if(ret_status != 0)
- return ret_status;
- input_length = ciphertext_length + 64; // normal case - no writing outside the allocated memory.
- printf("Public key and ciphertext:\n"); fflush(stdout);
- for(count = 0; count<input_length; count++)
- printf("0x%02x ", client_data_to_decryptor[count]);
- printf("\n"); fflush(stdout);
- /* client_data_encrypted_to_decryptor = (unsigned char*) malloc(input_length + 16);
- // TODO: try to call aes_gcm *in encryption mode* on ciphertext data of ciphertext_length (where is the iv?)
- // if output_length != ciphertext_length + 64 then tag will be overwritten.
- ret_status = aes_gcm_wrapper(1, client_data_to_decryptor, input_length, client_data_encrypted_to_decryptor, &output_length, tag);
- if(ret_status != 0 || output_length != input_length)
- {
- free(client_data_to_decryptor);
- free(client_data_encrypted_to_decryptor);
- return ret_status;
- }
- for(count=0; count<16; count++)
- client_data_encrypted_to_decryptor[output_length+count]=tag[count];
- // TODO: Increment AESGCM IV here.
- */
- protobuf_encrypted_msg.set_msg((void*)client_data_to_decryptor, input_length);
- free(client_data_to_decryptor);
- // free(client_data_encrypted_to_decryptor);
- /*
- printf("Writing this to the decryptor: \n"); fflush(stdout);
- for(count=8;count<output_length+16+8;count++)
- printf("0x%02x ", client_data_to_decryptor[count]);
- printf("\n"); fflush(stdout);
- */
- // write message to decryptor
- if(write_protobuf_msg_to_fd(global_decryptor_fd, protobuf_encrypted_msg)!=0)
- {
- printf("Not all of the client's pub key and ciphertext data was written\n"); fflush(stdout); return 0xfe;
- }
- // clear the message before setting it again
- protobuf_encrypted_msg.clear_msg();
- // read encrypted data
- printf("Reading msg from decryptor"); fflush(stdout);
- if(read_protobuf_msg_from_fd(global_decryptor_fd, protobuf_encrypted_msg)!=0)
- {
- printf("Not all of the decryptor's message was read\n"); fflush(stdout); return 0xf3;
- }
- printf("Done reading msg from decryptor\n"); fflush(stdout);
- // define plaintext array
- input_length = protobuf_encrypted_msg.msg().length();
- msg = protobuf_encrypted_msg.msg().c_str();
- for(count=0; count<input_length; count++)
- plaintext_client_data[count] = msg[count];
- *op_plaintext_client_data_length = input_length;
- /* client_data_from_decryptor=(unsigned char*)malloc(input_length);
- memcpy(client_data_from_decryptor, protobuf_encrypted_msg.msg().c_str(), input_length); //TODO: THIS might be a problem - c_str might terminate at null bytes?
- // TODO: decrypt data received in the protobuf_encrypted_msg, set bytes at plaintext_client_data to it.
- for(count=0;count<input_length;count++)
- {
- plaintext_client_data[count]=client_data_from_decryptor[count];
- printf("0x%02x ", client_data_from_decryptor[count]);
- }
- printf("\n"); fflush(stdout);
- *op_plaintext_client_data_length=input_length;
- ret_status = aes_gcm_wrapper(0, client_data_from_decryptor, input_length, plaintext_client_data, &output_length, client_data_from_decryptor + input_length - 16);
- if(ret_status == 0)
- *op_plaintext_client_data_length = output_length;
- free(client_data_from_decryptor);
- */
- return 0;
- }
|