ProtobufLAInitiator.cpp 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276
  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. #include <queue>
  18. int global_decryptor_fd;
  19. #define TOKEN_H_MAX_LENGTH 300;
  20. // TODO: Make these private functions
  21. int read_protobuf_msg_from_fd(int accept_fd, google::protobuf::MessageLite& message)
  22. {
  23. ZeroCopyInputStream* raw_input;
  24. CodedInputStream* coded_input;
  25. uint32_t size;
  26. CodedInputStream::Limit limit;
  27. raw_input = new FileInputStream(accept_fd);
  28. coded_input = new CodedInputStream(raw_input);
  29. if(!coded_input->ReadVarint32(&size))
  30. {
  31. printf("Error in reading size of msg\n");
  32. fflush(stdout);
  33. return -1;
  34. }
  35. printf("size of msg was read to be %d \n", size);
  36. fflush(stdout);
  37. limit = coded_input->PushLimit(size);
  38. if(!message.ParseFromCodedStream(coded_input))
  39. {
  40. printf("Error in parsing msg\n");
  41. fflush(stdout);
  42. return -1;
  43. }
  44. printf("Done parsing msg\n"); fflush(stdout);
  45. coded_input->PopLimit(limit);
  46. return 0;
  47. }
  48. // TODO: private functions
  49. int write_protobuf_msg_to_fd(int accept_fd, google::protobuf::MessageLite& message)
  50. {
  51. ZeroCopyOutputStream* raw_output = new FileOutputStream(accept_fd);
  52. CodedOutputStream* coded_output = new CodedOutputStream(raw_output);
  53. coded_output->WriteVarint32(message.ByteSize());
  54. if(!message.SerializeToCodedStream(coded_output))
  55. {
  56. printf("SerializeToCodedStream failed\n");
  57. fflush(stdout);
  58. return -1;
  59. }
  60. // As per this - https://stackoverflow.com/questions/22881876/protocol-buffers-how-to-serialize-and-deserialize-multiple-messages-into-a-file?noredirect=1&lq=1
  61. // 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)
  62. delete coded_output;
  63. delete raw_output;
  64. fflush(stdout);
  65. return 0;
  66. }
  67. // Sets up a socket connected to the port passed as input - returns the socket FD on success and -1 on error.
  68. // Also prints the errno on error.
  69. int set_up_socket_connect(int port)
  70. {
  71. int sock = 0;
  72. if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
  73. {
  74. printf("\n Error in socket call - errno is %d \n", errno);
  75. return -1;
  76. }
  77. struct sockaddr_in serv_addr;
  78. memset(&serv_addr, '0', sizeof(serv_addr));
  79. serv_addr.sin_family = AF_INET;
  80. serv_addr.sin_port = htons(port);
  81. // Convert IPv4 and IPv6 addresses from text to binary form
  82. if(inet_pton(AF_INET, "127.0.0.1", &serv_addr.sin_addr)<=0)
  83. {
  84. printf("\nError in inet_pton - errno is %d\n", errno);
  85. return -1;
  86. }
  87. if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
  88. {
  89. printf("\nError in connect - errno is %d \n", errno);
  90. return -1;
  91. }
  92. return sock;
  93. }
  94. int local_attestation_initiator(int port)
  95. {
  96. // declare msg1, msg2, msg3 protobuf objects
  97. protobuf_sgx_dh_msg1_t protobuf_msg1;
  98. protobuf_sgx_dh_msg2_t protobuf_msg2;
  99. protobuf_sgx_dh_msg3_t protobuf_msg3;
  100. uint32_t protobuf_sgx_ret;
  101. uint32_t session_id;
  102. int decryptor_fd;
  103. setbuf(stdout,NULL);
  104. decryptor_fd=set_up_socket_connect(port);
  105. if(decryptor_fd == -1)
  106. {
  107. perror("\nCould not set up the socket: had the following error: ");
  108. fflush(stderr);
  109. }
  110. global_decryptor_fd=decryptor_fd;
  111. // Reading msg 1 from decryptor enclave.
  112. if(read_protobuf_msg_from_fd(decryptor_fd, protobuf_msg1)!=0)
  113. return -1;
  114. // Generating message 2 given message 1 as input
  115. protobuf_sgx_ret = process_protobuf_dh_msg1_generate_protobuf_dh_msg2(protobuf_msg1, protobuf_msg2, &session_id);
  116. if(protobuf_sgx_ret != 0)
  117. {
  118. printf("Error in process_protobuf_dh_msg1_generate_protobuf_dh_msg2: 0x%x", protobuf_sgx_ret); fflush(stdout); return protobuf_sgx_ret;
  119. }
  120. // Writing msg 2 to decryptor enclave.
  121. if(write_protobuf_msg_to_fd(decryptor_fd, protobuf_msg2)!=0)
  122. return -1;
  123. // Reading msg3 from decryptor enclave
  124. if(read_protobuf_msg_from_fd(decryptor_fd, protobuf_msg3)!=0)
  125. return -1;
  126. // Process message 3
  127. protobuf_sgx_ret = process_protobuf_dh_msg3(protobuf_msg3, &session_id);
  128. if(protobuf_sgx_ret != 0)
  129. {
  130. printf("Error in process_protobuf_dh_msg3: 0x%x", protobuf_sgx_ret); fflush(stdout); return protobuf_sgx_ret;
  131. }
  132. return 0;
  133. }
  134. uint32_t post_local_attestation_get_mitigator_header(unsigned char* base64_encoded_token_H, uint32_t* base64_encoded_token_H_length)
  135. {
  136. unsigned char* encrypted_token_H_and_tag, *plaintext_token_H;
  137. uint32_t encrypted_token_H_and_tag_length, plaintext_token_H_length;
  138. protobuf_post_LA_encrypted_msg_t protobuf_encrypted_msg;
  139. uint32_t count;
  140. uint32_t internal_return_status;
  141. // Reading the encrypted token H from the
  142. if(read_protobuf_msg_from_fd(global_decryptor_fd, protobuf_encrypted_msg)!=0)
  143. {
  144. printf("Not all of the post-LA message was read\n"); fflush(stdout); return 0xfe;
  145. }
  146. std::string protobuf_encrypted_msg_string(protobuf_encrypted_msg.msg());
  147. encrypted_token_H_and_tag_length=protobuf_encrypted_msg_string.length();
  148. encrypted_token_H_and_tag = (unsigned char*) malloc(encrypted_token_H_and_tag_length);
  149. memcpy(encrypted_token_H_and_tag, protobuf_encrypted_msg_string.c_str(), protobuf_encrypted_msg_string.length());
  150. printf("Read the following encrypted token T and tag from the decryptor socket.\n"); fflush(stdout);
  151. printf("Encrypted data:\n");
  152. for(count=0; count<encrypted_token_H_and_tag_length; count++)
  153. printf("0x%02x ", encrypted_token_H_and_tag[count]);
  154. printf("\n"); fflush(stdout);
  155. // TODO: Modify aes_gcm_wrapper to do the thing where it takes care of the tag internally.
  156. 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);
  157. if(internal_return_status != 0)
  158. {
  159. printf("Error in decryption 0x%x", internal_return_status); fflush(stdout); return internal_return_status;
  160. }
  161. printf("Decryptor's short-term public key\n");
  162. for(count=0;count<64;count++)
  163. printf("0x%02x ", plaintext_token_H[count]);
  164. printf("\n"); fflush(stdout);
  165. printf("Verifier mrenclave\n");
  166. for(count=64;count<96;count++)
  167. printf("0x%02x ", plaintext_token_H[count]);
  168. printf("\n"); fflush(stdout);
  169. *base64_encoded_token_H_length=base64_encoding_wrapper(base64_encoded_token_H, plaintext_token_H, plaintext_token_H_length);
  170. /*
  171. // TODO: Better return value handling.
  172. 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)))
  173. {
  174. printf("Somehow not the entire token was encoded in base64:0x%x\n", base64_encoded_token_H_length); fflush(stdout); return 0x55;
  175. }
  176. */
  177. printf("Successfully done Local attestation\n");
  178. fflush(stdout);
  179. return 0;
  180. }
  181. uint32_t base64_decoding_on_all_client_data(unsigned char* ip_base64_client_public_key_ciphertext,
  182. uint32_t ip_base64_client_public_key_ciphertext_length,
  183. unsigned char* op_client_public_key_ciphertext,
  184. uint32_t* op_client_public_key_ciphertext_length
  185. )
  186. {
  187. uint32_t openssl_ret_status;
  188. openssl_ret_status=base64_decoding_wrapper(ip_base64_client_public_key_ciphertext, op_client_public_key_ciphertext, ip_base64_client_public_key_ciphertext_length);
  189. if(openssl_ret_status == -1)
  190. return 0xfe;
  191. *op_client_public_key_ciphertext_length = openssl_ret_status;
  192. return 0;
  193. }
  194. // should be called with the base64encoded public key and data to be decrypted
  195. // base64 encoded public key should be of length 4*(ceil(64/3)) = 88 (at least)
  196. int decrypt_client_data_through_decryptor( unsigned char* ip_base64_client_public_key_ciphertext,
  197. uint32_t ip_base64_client_public_key_ciphertext_length,
  198. unsigned char* op_plaintext,
  199. uint32_t* op_plaintext_length
  200. )
  201. {
  202. /* unsigned char* ciphertext_to_decryptor; const char *ciphertext_from_decryptor;
  203. uint32_t ciphertext_to_decryptor_length, ciphertext_from_decryptor_length;
  204. uint32_t internal_return_status;
  205. protobuf_post_LA_encrypted_msg_t protobuf_encrypted_msg;
  206. // Encrypting to the decryptor enclave
  207. ciphertext_to_decryptor=(unsigned char*) malloc(ip_base64_client_public_key_ciphertext_length + 16);
  208. internal_return_status = aes_gcm_wrapper(1, ip_base64_client_public_key_ciphertext, ip_base64_client_public_key_ciphertext_length,
  209. ciphertext_to_decryptor, &ciphertext_to_decryptor_length );
  210. // Error checking on ciphertext that is to be sent to decryptor
  211. if(internal_return_status != 0)
  212. {
  213. free(ciphertext_to_decryptor);
  214. return internal_return_status;
  215. }
  216. // write message to decryptor
  217. protobuf_encrypted_msg.set_msg( ciphertext_to_decryptor , ciphertext_to_decryptor_length );
  218. free(ciphertext_to_decryptor);
  219. if(write_protobuf_msg_to_fd(global_decryptor_fd, protobuf_encrypted_msg)!=0)
  220. {
  221. printf("Not all of the client's pub key and ciphertext data was written\n"); fflush(stdout); return 0xfe;
  222. }
  223. // clear the message before setting it again
  224. protobuf_encrypted_msg.clear_msg();
  225. // read encrypted data
  226. printf("Reading msg from decryptor"); fflush(stdout);
  227. if(read_protobuf_msg_from_fd(global_decryptor_fd, protobuf_encrypted_msg)!=0)
  228. {
  229. printf("Not all of the decryptor's message was read\n"); fflush(stdout); return 0xf3;
  230. }
  231. printf("Done reading msg from decryptor\n"); fflush(stdout);
  232. ciphertext_from_decryptor_length = protobuf_encrypted_msg.msg().length();
  233. ciphertext_from_decryptor = protobuf_encrypted_msg.msg().c_str();
  234. // Decrypt data from decryptor
  235. internal_return_status = aes_gcm_wrapper(0, (unsigned char*) ciphertext_from_decryptor, ciphertext_from_decryptor_length,
  236. op_plaintext, op_plaintext_length
  237. );
  238. if(internal_return_status != 0)
  239. return internal_return_status;
  240. */
  241. return 0;
  242. }