ProtobufLAInitiator.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  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"PostLAMessages.pb.h"
  9. #include<google/protobuf/io/coded_stream.h>
  10. #include<google/protobuf/io/zero_copy_stream_impl.h>
  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. #include<queue>
  18. using namespace google::protobuf::io;
  19. int global_decryptor_fd;
  20. #define TOKEN_H_MAX_LENGTH 300
  21. uint8_t ciphertext_to_decryptor[4092];
  22. // TODO: Make these private functions
  23. // TODO: Rewrite read, write calls for protobuf msgs to and from fds to use message.SerializeToFileDescriptor and ParseFromFileDescriptor
  24. bool read_protobuf_msg_from_fd(int accept_fd, google::protobuf::MessageLite& message)
  25. {
  26. //message.SerializeToFileDescriptor(accept_fd);
  27. ZeroCopyInputStream* raw_input;
  28. CodedInputStream* coded_input;
  29. uint32_t size;
  30. CodedInputStream::Limit limit;
  31. raw_input = new FileInputStream(accept_fd);
  32. coded_input = new CodedInputStream(raw_input);
  33. if(!coded_input->ReadVarint32(&size))
  34. {
  35. printf("Error in reading size of msg\n");
  36. fflush(stdout);
  37. return false;
  38. }
  39. // printf("size of msg was read to be %d \n", size);
  40. // fflush(stdout);
  41. limit = coded_input->PushLimit(size);
  42. if(!message.ParseFromCodedStream(coded_input))
  43. {
  44. printf("Error in parsing msg\n");
  45. fflush(stdout);
  46. return false;
  47. }
  48. // printf("Done parsing msg\n"); fflush(stdout);
  49. coded_input->PopLimit(limit);
  50. return true;
  51. }
  52. // TODO: private functions
  53. bool write_protobuf_msg_to_fd(int accept_fd, google::protobuf::MessageLite& message)
  54. {
  55. //return message.ParseFromFileDescriptor(accept_fd);
  56. ZeroCopyOutputStream* raw_output = new FileOutputStream(accept_fd);
  57. CodedOutputStream* coded_output = new CodedOutputStream(raw_output);
  58. coded_output->WriteVarint32(message.ByteSize());
  59. if(!message.SerializeToCodedStream(coded_output))
  60. {
  61. printf("SerializeToCodedStream failed\n");
  62. fflush(stdout);
  63. return false;
  64. }
  65. // As per this - https://stackoverflow.com/questions/22881876/protocol-buffers-how-to-serialize-and-deserialize-multiple-messages-into-a-file?noredirect=1&lq=1
  66. // 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)
  67. delete coded_output;
  68. delete raw_output;
  69. // fflush(stdout);
  70. return true;
  71. }
  72. void create_vector_from_protobuf(extension_to_decryptor_enclosed_msg &protobuf_ext_to_decryptor,
  73. std::vector<std::string> &binary_ciphertext_client_data)
  74. {
  75. uint32_t temp_size, counter;
  76. binary_ciphertext_client_data.push_back(protobuf_ext_to_decryptor.ciphertext_client_public_key());
  77. temp_size=protobuf_ext_to_decryptor.ciphertext_fields_size();
  78. for(counter=0; counter<temp_size; counter++)
  79. binary_ciphertext_client_data.push_back(protobuf_ext_to_decryptor.ciphertext_fields(counter).field());
  80. }
  81. void create_protobuf_from_vector(std::vector<std::string> &double_ciphertext_client_data,
  82. extension_to_decryptor_enclosed_msg &protobuf_ext_decryptor_msg)
  83. {
  84. uint32_t counter, temp_size;
  85. protobuf_ext_decryptor_msg.set_ciphertext_client_public_key(double_ciphertext_client_data[0]);
  86. temp_size=double_ciphertext_client_data.size()-1; // 1 for the public key.
  87. for(counter=0; counter<temp_size; counter++)
  88. protobuf_ext_decryptor_msg.mutable_ciphertext_fields(counter)->set_field(double_ciphertext_client_data[counter]);
  89. }
  90. // Sets up a socket connected to the port passed as input - returns the socket FD on success and -1 on error.
  91. // Also prints the errno on error.
  92. int set_up_socket_connect(int port)
  93. {
  94. int sock = 0;
  95. if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  96. {
  97. printf("\n Error in socket call - errno is %d \n", errno);
  98. return -1;
  99. }
  100. struct sockaddr_in serv_addr;
  101. memset(&serv_addr, '0', sizeof(serv_addr));
  102. serv_addr.sin_family = AF_INET;
  103. serv_addr.sin_port = htons(port);
  104. // Convert IPv4 and IPv6 addresses from text to binary form
  105. if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
  106. {
  107. printf("\nError in inet_pton - errno is %d\n", errno);
  108. return -1;
  109. }
  110. if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
  111. {
  112. printf("\nError in connect - errno is %d \n", errno);
  113. return -1;
  114. }
  115. return sock;
  116. }
  117. int local_attestation_initiator(int port)
  118. {
  119. // declare msg1, msg2, msg3 protobuf objects
  120. protobuf_sgx_dh_msg1_t protobuf_msg1;
  121. protobuf_sgx_dh_msg2_t protobuf_msg2;
  122. protobuf_sgx_dh_msg3_t protobuf_msg3;
  123. uint32_t protobuf_sgx_ret;
  124. uint32_t session_id;
  125. int decryptor_fd;
  126. setbuf(stdout,NULL);
  127. decryptor_fd=set_up_socket_connect(port);
  128. if(decryptor_fd == -1)
  129. {
  130. perror("\nCould not set up the socket: had the following error: ");
  131. fflush(stderr);
  132. }
  133. global_decryptor_fd=decryptor_fd;
  134. // Reading msg 1 from decryptor enclave.
  135. if(! read_protobuf_msg_from_fd(decryptor_fd, protobuf_msg1))
  136. return -1;
  137. // Generating message 2 given message 1 as input
  138. protobuf_sgx_ret = process_protobuf_dh_msg1_generate_protobuf_dh_msg2(protobuf_msg1, protobuf_msg2, &session_id);
  139. if(protobuf_sgx_ret != 0)
  140. {
  141. printf("Error in process_protobuf_dh_msg1_generate_protobuf_dh_msg2: 0x%x", protobuf_sgx_ret); fflush(stdout); return protobuf_sgx_ret;
  142. }
  143. // Writing msg 2 to decryptor enclave.
  144. if(!write_protobuf_msg_to_fd(decryptor_fd, protobuf_msg2))
  145. return -1;
  146. // Reading msg3 from decryptor enclave
  147. if(!read_protobuf_msg_from_fd(decryptor_fd, protobuf_msg3))
  148. return -1;
  149. // Process message 3
  150. protobuf_sgx_ret = process_protobuf_dh_msg3(protobuf_msg3, &session_id);
  151. if(protobuf_sgx_ret != 0)
  152. {
  153. printf("Error in process_protobuf_dh_msg3: 0x%x", protobuf_sgx_ret); fflush(stdout); return protobuf_sgx_ret;
  154. }
  155. return 0;
  156. }
  157. uint32_t post_local_attestation_get_mitigator_header(unsigned char* base64_encoded_token_H, uint32_t* base64_encoded_token_H_length)
  158. {
  159. unsigned char* encrypted_token_H_and_tag, *plaintext_token_H;
  160. uint32_t encrypted_token_H_and_tag_length, plaintext_token_H_length;
  161. protobuf_post_LA_encrypted_msg_t protobuf_encrypted_msg;
  162. uint32_t count;
  163. uint32_t internal_return_status;
  164. // Reading the encrypted token H from the
  165. if(!read_protobuf_msg_from_fd(global_decryptor_fd, protobuf_encrypted_msg))
  166. {
  167. printf("Not all of the post-LA message was read\n"); fflush(stdout); return 0xfe;
  168. }
  169. std::string protobuf_encrypted_msg_string(protobuf_encrypted_msg.msg());
  170. encrypted_token_H_and_tag_length=protobuf_encrypted_msg_string.length();
  171. encrypted_token_H_and_tag = (unsigned char*) malloc(encrypted_token_H_and_tag_length);
  172. memcpy(encrypted_token_H_and_tag, protobuf_encrypted_msg_string.c_str(), protobuf_encrypted_msg_string.length());
  173. printf("Read the following encrypted token T and tag from the decryptor socket.\n"); fflush(stdout);
  174. printf("Encrypted data:\n");
  175. for(count=0; count<encrypted_token_H_and_tag_length; count++)
  176. printf("0x%02x ", encrypted_token_H_and_tag[count]);
  177. printf("\n"); fflush(stdout);
  178. plaintext_token_H=(unsigned char*) malloc(encrypted_token_H_and_tag_length);
  179. internal_return_status = aes_gcm_wrapper(0, encrypted_token_H_and_tag, encrypted_token_H_and_tag_length, plaintext_token_H, &plaintext_token_H_length);
  180. if(internal_return_status != 0)
  181. {
  182. free(encrypted_token_H_and_tag);
  183. free(plaintext_token_H);
  184. printf("Error in decryption 0x%x", internal_return_status); fflush(stdout); return internal_return_status;
  185. }
  186. printf("Decryptor's short-term public key\n");
  187. for(count=0;count<64;count++)
  188. printf("0x%02x ", plaintext_token_H[count]);
  189. printf("\n"); fflush(stdout);
  190. printf("Verifier mrenclave\n");
  191. for(count=64;count<96;count++)
  192. printf("0x%02x ", plaintext_token_H[count]);
  193. printf("\n"); fflush(stdout);
  194. *base64_encoded_token_H_length=base64_encoding_wrapper(base64_encoded_token_H, plaintext_token_H, plaintext_token_H_length);
  195. // TODO: Better return value handling.
  196. //if(!(base64_encoded_token_H_length <= 4 * Math.ceil(plaintext_token_H_length/3) && base64_encoded_token_H_length > 4 * (Math.ceil(plaintext_token_H_length/3) - 1)))
  197. //{
  198. // printf("Somehow not the entire token was encoded in base64:0x%x\n", base64_encoded_token_H_length); fflush(stdout); return 0x55;
  199. //}
  200. free(encrypted_token_H_and_tag);
  201. free(plaintext_token_H);
  202. fflush(stdout);
  203. return 0;
  204. }
  205. uint32_t base64_decoding_on_all_client_data(unsigned char* ip_base64_client_public_key_ciphertext,
  206. uint32_t ip_base64_client_public_key_ciphertext_length,
  207. unsigned char* op_client_public_key_ciphertext,
  208. uint32_t* op_client_public_key_ciphertext_length
  209. )
  210. {
  211. /* uint32_t openssl_ret_status;
  212. openssl_ret_status=base64_decoding_wrapper(ip_base64_client_public_key_ciphertext, op_client_public_key_ciphertext, ip_base64_client_public_key_ciphertext_length);
  213. if(openssl_ret_status == -1)
  214. return 0xfe;
  215. *op_client_public_key_ciphertext_length = openssl_ret_status;
  216. */
  217. return 0;
  218. }
  219. int encrypt_decrypt_ciphertexts(int encrypt_decrypt, std::vector<std::string> &binary_ciphertext_client_data,
  220. std::vector<std::string> &double_ciphertext_client_data)
  221. {
  222. unsigned char *ciphertext; unsigned char *double_ciphertext;
  223. uint32_t ciphertext_size, double_ciphertext_size, ret;
  224. double_ciphertext=NULL;
  225. for (std::string ciphertext_from_client:binary_ciphertext_client_data)
  226. {
  227. ciphertext_size = ciphertext_from_client.length();
  228. ciphertext = (unsigned char*) ciphertext_from_client.c_str();
  229. double_ciphertext=(unsigned char*) realloc(double_ciphertext, ciphertext_size + 28); // 16 for tag, 12 for IV
  230. ret = aes_gcm_wrapper(encrypt_decrypt, ciphertext, ciphertext_size, double_ciphertext, &double_ciphertext_size );
  231. if(ret!=0)
  232. {
  233. free(double_ciphertext);
  234. printf("Failed to encrypt a ciphertext field.\n"); fflush(stdout);
  235. return 0x2;
  236. }
  237. double_ciphertext_client_data.push_back(std::string(reinterpret_cast<const char *> (double_ciphertext), double_ciphertext_size));
  238. }
  239. free(double_ciphertext);
  240. return 0;
  241. }
  242. int decrypt_client_data_through_decryptor( std::vector<std::string> &binary_ciphertext_client_data,
  243. std::vector<std::string> &plaintext_client_data)
  244. {
  245. uint32_t ret;
  246. std::vector<std::string> double_ciphertext_client_data;
  247. std::vector<std::string> received_ciphertext_client_data;
  248. extension_to_decryptor_enclosed_msg protobuf_extension_decryptor_msg;
  249. ret=encrypt_decrypt_ciphertexts(1, binary_ciphertext_client_data, double_ciphertext_client_data);
  250. if(ret!=0)
  251. return ret;
  252. create_protobuf_from_vector(double_ciphertext_client_data,
  253. protobuf_extension_decryptor_msg);
  254. // write message to decryptor
  255. if(!write_protobuf_msg_to_fd(global_decryptor_fd, protobuf_extension_decryptor_msg))
  256. {
  257. printf("Not all of the client's pub key and ciphertext data was written\n"); fflush(stdout);
  258. return 0xfe;
  259. }
  260. protobuf_extension_decryptor_msg.clear_ciphertext_fields();
  261. protobuf_extension_decryptor_msg.clear_ciphertext_client_public_key(); // not necessary.
  262. // read encrypted data
  263. if(!read_protobuf_msg_from_fd(global_decryptor_fd, protobuf_extension_decryptor_msg))
  264. {
  265. printf("Not all of the decryptor's message was read\n"); fflush(stdout);
  266. return 0xf3;
  267. }
  268. create_vector_from_protobuf(protobuf_extension_decryptor_msg, received_ciphertext_client_data);
  269. ret=encrypt_decrypt_ciphertexts(0, received_ciphertext_client_data,
  270. plaintext_client_data);
  271. return ret;
  272. }