ProtobufLAInitiator.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288
  1. // Knows only protobuf_sgx objects, protobuf header.
  2. #include <stdlib.h>
  3. #include <string.h>
  4. #include <errno.h>
  5. #include<unistd.h>
  6. #include <stdio.h>
  7. #include "ProtobufLAMessages.pb.h"
  8. #include <google/protobuf/io/coded_stream.h>
  9. #include <google/protobuf/io/zero_copy_stream_impl.h>
  10. using namespace google::protobuf::io;
  11. #include "SgxProtobufLAInitiator.h"
  12. #include "crypto.h"
  13. // For socket programming
  14. #include <arpa/inet.h>
  15. #include <sys/socket.h>
  16. #include <netinet/in.h>
  17. int global_decryptor_fd;
  18. // TODO: Make these private functions
  19. int read_protobuf_msg_from_fd(int accept_fd, google::protobuf::MessageLite& message)
  20. {
  21. ZeroCopyInputStream* raw_input;
  22. CodedInputStream* coded_input;
  23. uint32_t size;
  24. CodedInputStream::Limit limit;
  25. raw_input = new FileInputStream(accept_fd);
  26. coded_input = new CodedInputStream(raw_input);
  27. if(!coded_input->ReadVarint32(&size))
  28. {
  29. printf("Error in reading size of msg\n");
  30. fflush(stdout);
  31. return -1;
  32. }
  33. printf("size of msg was read to be %d \n", size);
  34. fflush(stdout);
  35. limit = coded_input->PushLimit(size);
  36. if(!message.ParseFromCodedStream(coded_input))
  37. {
  38. printf("Error in parsing msg\n");
  39. fflush(stdout);
  40. return -1;
  41. }
  42. printf("Done parsing msg\n"); fflush(stdout);
  43. coded_input->PopLimit(limit);
  44. return 0;
  45. }
  46. // TODO: private functions
  47. int write_protobuf_msg_to_fd(int accept_fd, google::protobuf::MessageLite& message)
  48. {
  49. ZeroCopyOutputStream* raw_output = new FileOutputStream(accept_fd);
  50. CodedOutputStream* coded_output = new CodedOutputStream(raw_output);
  51. coded_output->WriteVarint32(message.ByteSize());
  52. if(!message.SerializeToCodedStream(coded_output))
  53. {
  54. printf("SerializeToCodedStream failed\n");
  55. fflush(stdout);
  56. return -1;
  57. }
  58. // As per this - https://stackoverflow.com/questions/22881876/protocol-buffers-how-to-serialize-and-deserialize-multiple-messages-into-a-file?noredirect=1&lq=1
  59. // 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)
  60. delete coded_output;
  61. delete raw_output;
  62. fflush(stdout);
  63. return 0;
  64. }
  65. // Sets up a socket connected to the port passed as input - returns the socket FD on success and -1 on error.
  66. // Also prints the errno on error.
  67. int set_up_socket_connect(int port)
  68. {
  69. int sock = 0;
  70. if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  71. {
  72. printf("\n Error in socket call - errno is %d \n", errno);
  73. return -1;
  74. }
  75. struct sockaddr_in serv_addr;
  76. memset(&serv_addr, '0', sizeof(serv_addr));
  77. serv_addr.sin_family = AF_INET;
  78. serv_addr.sin_port = htons(port);
  79. // Convert IPv4 and IPv6 addresses from text to binary form
  80. if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
  81. {
  82. printf("\nError in inet_pton - errno is %d\n", errno);
  83. return -1;
  84. }
  85. if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
  86. {
  87. printf("\nError in connect - errno is %d \n", errno);
  88. return -1;
  89. }
  90. return sock;
  91. }
  92. int local_attestation_initiator(int port, unsigned char* base64_encoded_token)
  93. {
  94. // declare msg1, msg2, msg3 protobuf objects
  95. protobuf_sgx_dh_msg1_t protobuf_msg1;
  96. protobuf_sgx_dh_msg2_t protobuf_msg2;
  97. protobuf_sgx_dh_msg3_t protobuf_msg3;
  98. uint32_t protobuf_sgx_ret;
  99. // uint8_t encrypted_hash[32]; uint8_t encrypted_tag[16]; size_t post_la_bytes_written;
  100. // uint8_t tokenT_and_tag[176]; size_t bytes_read;
  101. // For socket to listen to the Apache enclave.
  102. // int server_fd=0; int accept_fd = 0;
  103. // std::string protobuf_encrypted_msg_string(protobuf_encrypted_msg.msg());
  104. // memcpy(tokenT_and_tag, protobuf_encrypted_msg_string.c_str(), 176);
  105. // struct sockaddr_in own_addr;
  106. // struct sockaddr_storage apache_addr; socklen_t apache_addr_size = sizeof(apache_addr);
  107. uint32_t session_id;
  108. // int counter;
  109. int decryptor_fd;
  110. setbuf(stdout,NULL);
  111. decryptor_fd=set_up_socket_connect(port);
  112. if(decryptor_fd == -1)
  113. {
  114. perror("\nCould not set up the socket: had the following error: ");
  115. fflush(stderr);
  116. }
  117. // printf("");
  118. if(read_protobuf_msg_from_fd(decryptor_fd, protobuf_msg1)!=0)
  119. return -1;
  120. protobuf_sgx_ret = process_protobuf_dh_msg1_generate_protobuf_dh_msg2(protobuf_msg1, protobuf_msg2, &session_id);
  121. if(protobuf_sgx_ret != 0)
  122. {
  123. printf("Error in process_protobuf_dh_msg1_generate_protobuf_dh_msg2: 0x%x", protobuf_sgx_ret); fflush(stdout); return protobuf_sgx_ret;
  124. }
  125. if(write_protobuf_msg_to_fd(decryptor_fd, protobuf_msg2)!=0)
  126. return -1;
  127. if(read_protobuf_msg_from_fd(decryptor_fd, protobuf_msg3)!=0)
  128. return -1;
  129. protobuf_sgx_ret = process_protobuf_dh_msg3(protobuf_msg3, &session_id);
  130. if(protobuf_sgx_ret != 0)
  131. {
  132. printf("Error in process_protobuf_dh_msg3: 0x%x", protobuf_sgx_ret); fflush(stdout); return protobuf_sgx_ret;
  133. }
  134. unsigned char tokenT_and_tag[176]; int protobuf_encrypted_msg_size;
  135. protobuf_post_LA_encrypted_msg_t protobuf_encrypted_msg;
  136. if(read_protobuf_msg_from_fd(decryptor_fd, protobuf_encrypted_msg)!=0)
  137. {
  138. printf("Not all of the post-LA message was read\n"); fflush(stdout); return 0xfe;
  139. }
  140. std::string protobuf_encrypted_msg_string(protobuf_encrypted_msg.msg());
  141. memcpy(tokenT_and_tag, protobuf_encrypted_msg_string.c_str(), 176);
  142. printf("Read encrypted signature and tag from the decryptor socket.\n"); fflush(stdout);
  143. uint32_t count;
  144. printf("Encrypted data:\n");
  145. for(count=0;count<176;count++)
  146. printf("0x%02x ", tokenT_and_tag[count]);
  147. printf("\n"); fflush(stdout);
  148. uint8_t plaintext_token[160]; int plaintext_length=0;
  149. uint32_t ret_decrypt=aes_gcm_wrapper(0, tokenT_and_tag, 160, plaintext_token, &plaintext_length, tokenT_and_tag+160);
  150. //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);
  151. if(ret_decrypt!=0)
  152. {
  153. printf("Errorin decryption 0x%x", ret_decrypt); fflush(stdout); return 0xed;
  154. }
  155. printf("Decryption keypair\n");
  156. for(count=0;count<64;count++)
  157. printf("0x%02x ", plaintext_token[count]);
  158. printf("\n"); fflush(stdout);
  159. printf("Decryption verifier mrenclave\n");
  160. for(count=64;count<96;count++)
  161. printf("0x%02x ", plaintext_token[count]);
  162. printf("\n"); fflush(stdout);
  163. count=base64_encoding_wrapper(plaintext_token, base64_encoded_token, 160);
  164. if(count != 216)
  165. {
  166. printf("Somehow not the entire token was encoded in base64:0x%x\n", count); fflush(stdout); return 0x55;
  167. }
  168. global_decryptor_fd=decryptor_fd;
  169. printf("Successfully done Local attestation\n");
  170. fflush(stdout);
  171. return 0;
  172. }
  173. // should be called with the base64encoded public key and data to be decrypted
  174. // base64 encoded public key should be of length 4*(ceil(64/3)) = 88 (at least)
  175. int decrypt_client_data_through_decryptor(unsigned char* base64_encoded_client_pub_key, unsigned char* ciphertext, uint32_t ciphertext_length, unsigned char* plaintext_user_data, uint32_t* op_plaintext_user_data_length)
  176. {
  177. int openssl_ret_status;
  178. unsigned char client_pub_key[64];
  179. uint32_t count;
  180. uint32_t length;
  181. unsigned char* client_data_to_decryptor;
  182. unsigned char* client_data_encrypted_to_decryptor;
  183. unsigned char* client_data_from_decryptor;
  184. int encryption_result;
  185. protobuf_post_LA_encrypted_msg_t protobuf_encrypted_msg;
  186. int output_length;
  187. for(count=0; count<ciphertext_length; count++)
  188. plaintext_user_data[count] = ciphertext[count];
  189. *op_plaintext_user_data_length = ciphertext_length;
  190. client_data_to_decryptor = (unsigned char*) malloc(64 + (ciphertext_length * 3/4));
  191. openssl_ret_status=base64_decoding_wrapper(base64_encoded_client_pub_key, client_data_to_decryptor, 88);
  192. if(openssl_ret_status == -1)
  193. {
  194. free(client_data_to_decryptor);
  195. return 0xfe;
  196. }
  197. printf("Received the following key from the client:\n");
  198. for(count=0;count<64;count++)
  199. printf("0x%02x ", client_data_to_decryptor[count]);
  200. printf("\n"); fflush(stdout);
  201. // // TODO: call aes_gcm_wrapper or aes_gcm *in encryption mode* on ciphertext data of ciphertext_length (where is the iv?)
  202. length = base64_decoding_wrapper(ciphertext, client_data_to_decryptor + 64, ciphertext_length);
  203. if(length == -1)
  204. {
  205. free(client_data_to_decryptor);
  206. return 0x33;
  207. }
  208. for(count = 0; count<64 + length; count++)
  209. printf("0x%02x ", client_data_to_decryptor[count]);
  210. printf("\n"); fflush(stdout);
  211. client_data_encrypted_to_decryptor = (unsigned char*) malloc(length + 64 + 16);
  212. // TODO: try to call aes_gcm *in encryption mode* on ciphertext data of ciphertext_length (where is the iv?)
  213. // if output_length != length + 64 then problems
  214. encryption_result = aes_gcm_wrapper(1, client_data_to_decryptor, length + 64, client_data_encrypted_to_decryptor, &output_length, client_data_encrypted_to_decryptor + length + 80);
  215. if(encryption_result != 0)
  216. {
  217. free(client_data_to_decryptor);
  218. free(client_data_encrypted_to_decryptor);
  219. return encryption_result;
  220. }
  221. // TODO: Increment AESGCM IV here.
  222. protobuf_encrypted_msg.set_msg((void*)client_data_encrypted_to_decryptor, output_length);
  223. free(client_data_to_decryptor);
  224. free(client_data_encrypted_to_decryptor);
  225. // write message to decryptor
  226. if(write_protobuf_msg_to_fd(global_decryptor_fd, protobuf_encrypted_msg)!=0)
  227. {
  228. printf("Not all of the client's pub key and ciphertext data was written\n"); fflush(stdout); return 0xfe;
  229. }
  230. // clear the message before setting it again
  231. protobuf_encrypted_msg.clear_msg();
  232. // read encrypted data
  233. printf("Reading msg from decryptor"); fflush(stdout);
  234. if(read_protobuf_msg_from_fd(global_decryptor_fd, protobuf_encrypted_msg)!=0)
  235. {
  236. printf("Not all of the decryptor's message was read\n"); fflush(stdout); return 0xfe;
  237. }
  238. printf("Done reading msg from decryptor\n"); fflush(stdout);
  239. // define plaintext array
  240. length = protobuf_encrypted_msg.msg().length();
  241. client_data_from_decryptor=(unsigned char*)malloc(length);
  242. memcpy(client_data_from_decryptor, protobuf_encrypted_msg.msg().c_str(), length); //TODO: THIS might be a problem - c_str might terminate at null bytes?
  243. // TODO: decrypt data received in the protobuf_encrypted_msg, set bytes at plaintext_user_data to it.
  244. for(count=0;count<length;count++)
  245. printf("0x%02x ", client_data_from_decryptor[count]);
  246. printf("\n"); fflush(stdout);
  247. encryption_result = aes_gcm_wrapper(0, client_data_from_decryptor, length, plaintext_user_data, &output_length, client_data_from_decryptor + length - 16);
  248. if(encryption_result == 0)
  249. *op_plaintext_user_data_length = output_length;
  250. free(client_data_from_decryptor);
  251. return encryption_result;
  252. }