ProtobufLAInitiator.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342
  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. // Sets up a socket connected to the port passed as input - returns the socket FD on success and -1 on error.
  73. // Also prints the errno on error.
  74. int set_up_socket_connect(int port)
  75. {
  76. int sock = 0;
  77. if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  78. {
  79. printf("\n Error in socket call - errno is %d \n", errno);
  80. return -1;
  81. }
  82. struct sockaddr_in serv_addr;
  83. memset(&serv_addr, '0', sizeof(serv_addr));
  84. serv_addr.sin_family = AF_INET;
  85. serv_addr.sin_port = htons(port);
  86. // Convert IPv4 and IPv6 addresses from text to binary form
  87. if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
  88. {
  89. printf("\nError in inet_pton - errno is %d\n", errno);
  90. return -1;
  91. }
  92. if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
  93. {
  94. printf("\nError in connect - errno is %d \n", errno);
  95. return -1;
  96. }
  97. return sock;
  98. }
  99. int local_attestation_initiator(int port)
  100. {
  101. // declare msg1, msg2, msg3 protobuf objects
  102. protobuf_sgx_dh_msg1_t protobuf_msg1;
  103. protobuf_sgx_dh_msg2_t protobuf_msg2;
  104. protobuf_sgx_dh_msg3_t protobuf_msg3;
  105. uint32_t protobuf_sgx_ret;
  106. uint32_t session_id;
  107. int decryptor_fd;
  108. setbuf(stdout,NULL);
  109. decryptor_fd=set_up_socket_connect(port);
  110. if(decryptor_fd == -1)
  111. {
  112. perror("\nCould not set up the socket: had the following error: ");
  113. fflush(stderr);
  114. }
  115. global_decryptor_fd=decryptor_fd;
  116. // Reading msg 1 from decryptor enclave.
  117. if(! read_protobuf_msg_from_fd(decryptor_fd, protobuf_msg1))
  118. return -1;
  119. // Generating message 2 given message 1 as input
  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. // Writing msg 2 to decryptor enclave.
  126. if(!write_protobuf_msg_to_fd(decryptor_fd, protobuf_msg2))
  127. return -1;
  128. // Reading msg3 from decryptor enclave
  129. if(!read_protobuf_msg_from_fd(decryptor_fd, protobuf_msg3))
  130. return -1;
  131. // Process message 3
  132. protobuf_sgx_ret = process_protobuf_dh_msg3(protobuf_msg3, &session_id);
  133. if(protobuf_sgx_ret != 0)
  134. {
  135. printf("Error in process_protobuf_dh_msg3: 0x%x", protobuf_sgx_ret); fflush(stdout); return protobuf_sgx_ret;
  136. }
  137. return 0;
  138. }
  139. uint32_t post_local_attestation_get_mitigator_header(unsigned char* base64_encoded_token_H, uint32_t* base64_encoded_token_H_length)
  140. {
  141. unsigned char* encrypted_token_H_and_tag, *plaintext_token_H;
  142. uint32_t encrypted_token_H_and_tag_length, plaintext_token_H_length;
  143. protobuf_post_LA_encrypted_msg_t protobuf_encrypted_msg;
  144. uint32_t count;
  145. uint32_t internal_return_status;
  146. // Reading the encrypted token H from the
  147. if(!read_protobuf_msg_from_fd(global_decryptor_fd, protobuf_encrypted_msg))
  148. {
  149. printf("Not all of the post-LA message was read\n"); fflush(stdout); return 0xfe;
  150. }
  151. std::string protobuf_encrypted_msg_string(protobuf_encrypted_msg.msg());
  152. encrypted_token_H_and_tag_length=protobuf_encrypted_msg_string.length();
  153. encrypted_token_H_and_tag = (unsigned char*) malloc(encrypted_token_H_and_tag_length);
  154. memcpy(encrypted_token_H_and_tag, protobuf_encrypted_msg_string.c_str(), protobuf_encrypted_msg_string.length());
  155. printf("Read the following encrypted token T and tag from the decryptor socket.\n"); fflush(stdout);
  156. printf("Encrypted data:\n");
  157. for(count=0; count<encrypted_token_H_and_tag_length; count++)
  158. printf("0x%02x ", encrypted_token_H_and_tag[count]);
  159. printf("\n"); fflush(stdout);
  160. plaintext_token_H=(unsigned char*) malloc(encrypted_token_H_and_tag_length);
  161. 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);
  162. if(internal_return_status != 0)
  163. {
  164. free(encrypted_token_H_and_tag);
  165. free(plaintext_token_H);
  166. printf("Error in decryption 0x%x", internal_return_status); fflush(stdout); return internal_return_status;
  167. }
  168. printf("Decryptor's short-term public key\n");
  169. for(count=0;count<64;count++)
  170. printf("0x%02x ", plaintext_token_H[count]);
  171. printf("\n"); fflush(stdout);
  172. printf("Verifier mrenclave\n");
  173. for(count=64;count<96;count++)
  174. printf("0x%02x ", plaintext_token_H[count]);
  175. printf("\n"); fflush(stdout);
  176. *base64_encoded_token_H_length=base64_encoding_wrapper(base64_encoded_token_H, plaintext_token_H, plaintext_token_H_length);
  177. // TODO: Better return value handling.
  178. //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)))
  179. //{
  180. // printf("Somehow not the entire token was encoded in base64:0x%x\n", base64_encoded_token_H_length); fflush(stdout); return 0x55;
  181. //}
  182. free(encrypted_token_H_and_tag);
  183. free(plaintext_token_H);
  184. fflush(stdout);
  185. return 0;
  186. }
  187. uint32_t base64_decoding_on_all_client_data(unsigned char* ip_base64_client_public_key_ciphertext,
  188. uint32_t ip_base64_client_public_key_ciphertext_length,
  189. unsigned char* op_client_public_key_ciphertext,
  190. uint32_t* op_client_public_key_ciphertext_length
  191. )
  192. {
  193. /* uint32_t openssl_ret_status;
  194. openssl_ret_status=base64_decoding_wrapper(ip_base64_client_public_key_ciphertext, op_client_public_key_ciphertext, ip_base64_client_public_key_ciphertext_length);
  195. if(openssl_ret_status == -1)
  196. return 0xfe;
  197. *op_client_public_key_ciphertext_length = openssl_ret_status;
  198. */
  199. return 0;
  200. }
  201. int exchange_ciphertext_fields_with_decryptor(unsigned char* input, uint32_t input_size,
  202. unsigned char* output, uint32_t* output_size)
  203. {
  204. // TODO: Initialize the extension_to_decryptor_ciphertext_msg protobuf with ciphertext from above.
  205. extension_to_decryptor_ciphertext_msg protobuf_extension_to_decryptor_msg;
  206. bool bool_return;
  207. protobuf_extension_to_decryptor_msg.set_ciphertext_bytes(input, input_size);
  208. // Serialize that protobuf using the write_ call.
  209. // write message to decryptor
  210. if(!write_protobuf_msg_to_fd(global_decryptor_fd, protobuf_extension_to_decryptor_msg))
  211. {
  212. printf("Not all of the client's pub key and ciphertext data was written\n"); fflush(stdout);
  213. return 0xfe;
  214. }
  215. protobuf_extension_to_decryptor_msg.clear_ciphertext_bytes();
  216. // read encrypted data
  217. if(!read_protobuf_msg_from_fd(global_decryptor_fd, protobuf_extension_to_decryptor_msg))
  218. {
  219. printf("Not all of the decryptor's message was read\n"); fflush(stdout);
  220. return 0xf3;
  221. }
  222. // First parse to the extension_to_decryptor_ciphertext_msg protobuf
  223. bool_return=protobuf_extension_to_decryptor_msg.SerializeToArray(output, protobuf_extension_to_decryptor_msg.ByteSize());
  224. if(bool_return)
  225. {
  226. *output_size=protobuf_extension_to_decryptor_msg.ByteSize();
  227. return 0;
  228. }
  229. else
  230. return 0x55;
  231. }
  232. int decrypt_client_data_through_decryptor( std::vector<std::string> &binary_ciphertext_client_data,
  233. std::vector<std::string> &plaintext_client_data)
  234. {
  235. uint32_t counter, plaintext_size, ciphertext_size, size, double_ciphertext_size, ret;
  236. unsigned char* plaintext, *ciphertext, *double_ciphertext;
  237. extension_to_decryptor_enclosed_msg protobuf_client_to_decryptor_msg;
  238. protobuf_client_to_decryptor_msg.set_ciphertext_client_public_key(binary_ciphertext_client_data[0]);
  239. counter=0;
  240. for (std::string ciphertext_from_client:binary_ciphertext_client_data)
  241. {
  242. // Put all fields in the order in which they come, into the enclosed protobuf - first one is client pub key, rest are ciphertexts
  243. protobuf_client_to_decryptor_msg.mutable_ciphertext_fields(counter)->set_field(ciphertext_from_client);
  244. counter++;
  245. }
  246. // Serializing the protobuf with all ciphertext client data.
  247. ciphertext_size=protobuf_client_to_decryptor_msg.ByteSize();
  248. ciphertext = (unsigned char*) malloc(ciphertext_size);
  249. if(!protobuf_client_to_decryptor_msg.SerializeToArray(ciphertext, ciphertext_size))
  250. {
  251. free(ciphertext);
  252. return 0x32;
  253. }
  254. // Encrypting the serialized protobuf to the decryptor enclave
  255. double_ciphertext = (unsigned char*) malloc(ciphertext_size + 20); // +20 for the tag (prolly 16 or w/e)
  256. ret = aes_gcm_wrapper(1, ciphertext, ciphertext_size, double_ciphertext, &double_ciphertext_size );
  257. if(ret != 0)
  258. {
  259. free(ciphertext); free(double_ciphertext);
  260. printf("Error in encrypting to decryptor.\n"); fflush(stdout);
  261. return 34;
  262. }
  263. // Communicating with the decryptor enclave by transferring the serialized, encrypted buffer to another protobuf
  264. // (no crypto in the php extension code for this function)
  265. ret=exchange_ciphertext_fields_with_decryptor(double_ciphertext, double_ciphertext_size, ciphertext, &ciphertext_size);
  266. free(double_ciphertext);
  267. if(ret!=0)
  268. {
  269. free(ciphertext);
  270. return ret;
  271. }
  272. // Decrypting from the decryptor enclave
  273. plaintext=(unsigned char*)malloc(ciphertext_size);
  274. ret = aes_gcm_wrapper(0, (unsigned char*) ciphertext, ciphertext_size,
  275. plaintext, &plaintext_size);
  276. free(ciphertext);
  277. if(ret != 0)
  278. {
  279. printf("Error in decrypting content from the decryptor.\n"); fflush(stdout);
  280. return 36;
  281. }
  282. // Getting a deserialized protobuf
  283. protobuf_client_to_decryptor_msg.clear_ciphertext_fields();
  284. if(!protobuf_client_to_decryptor_msg.ParseFromArray(plaintext, plaintext_size))
  285. {
  286. printf("Error in generating protobuf with plaintexts.\n"); fflush(stdout);
  287. return 35;
  288. }
  289. free(plaintext);
  290. // Setting the output to elements in that protobuf.
  291. size=protobuf_client_to_decryptor_msg.ciphertext_fields_size();
  292. for(counter=0;counter<size;counter++)
  293. {
  294. plaintext_client_data.push_back(protobuf_client_to_decryptor_msg.ciphertext_fields(counter).field());
  295. }
  296. return 0;
  297. }