ProtobufLAInitiator.cpp 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  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. plaintext_token_H=(unsigned char*) malloc(encrypted_token_H_and_tag_length);
  156. // TODO: Modify aes_gcm_wrapper to do the thing where it takes care of the tag internally.
  157. 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);
  158. if(internal_return_status != 0)
  159. {
  160. free(encrypted_token_H_and_tag);
  161. free(plaintext_token_H);
  162. printf("Error in decryption 0x%x", internal_return_status); fflush(stdout); return internal_return_status;
  163. }
  164. printf("Decryptor's short-term public key\n");
  165. for(count=0;count<64;count++)
  166. printf("0x%02x ", plaintext_token_H[count]);
  167. printf("\n"); fflush(stdout);
  168. printf("Verifier mrenclave\n");
  169. for(count=64;count<96;count++)
  170. printf("0x%02x ", plaintext_token_H[count]);
  171. printf("\n"); fflush(stdout);
  172. *base64_encoded_token_H_length=base64_encoding_wrapper(base64_encoded_token_H, plaintext_token_H, plaintext_token_H_length);
  173. /*
  174. // TODO: Better return value handling.
  175. 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)))
  176. {
  177. printf("Somehow not the entire token was encoded in base64:0x%x\n", base64_encoded_token_H_length); fflush(stdout); return 0x55;
  178. }
  179. */
  180. free(encrypted_token_H_and_tag);
  181. free(plaintext_token_H);
  182. fflush(stdout);
  183. return 0;
  184. }
  185. uint32_t base64_decoding_on_all_client_data(unsigned char* ip_base64_client_public_key_ciphertext,
  186. uint32_t ip_base64_client_public_key_ciphertext_length,
  187. unsigned char* op_client_public_key_ciphertext,
  188. uint32_t* op_client_public_key_ciphertext_length
  189. )
  190. {
  191. /* uint32_t openssl_ret_status;
  192. openssl_ret_status=base64_decoding_wrapper(ip_base64_client_public_key_ciphertext, op_client_public_key_ciphertext, ip_base64_client_public_key_ciphertext_length);
  193. if(openssl_ret_status == -1)
  194. return 0xfe;
  195. *op_client_public_key_ciphertext_length = openssl_ret_status;
  196. */ return 0;
  197. }
  198. // should be called with the base64encoded public key and data to be decrypted
  199. // base64 encoded public key should be of length 4*(ceil(64/3)) = 88 (at least)
  200. int decrypt_client_data_through_decryptor( unsigned char* ip_base64_client_public_key_ciphertext,
  201. uint32_t ip_base64_client_public_key_ciphertext_length,
  202. unsigned char* op_plaintext,
  203. uint32_t* op_plaintext_length
  204. )
  205. {
  206. unsigned char* ciphertext_to_decryptor, *ciphertext_from_decryptor;
  207. uint32_t ciphertext_to_decryptor_length, ciphertext_from_decryptor_length;
  208. uint32_t internal_return_status; uint32_t counter;
  209. protobuf_post_LA_encrypted_msg_t protobuf_encrypted_msg;
  210. std::string protobuf_encrypted_msg_string;
  211. // Encrypting to the decryptor enclave
  212. ciphertext_to_decryptor=(unsigned char*) malloc(ip_base64_client_public_key_ciphertext_length + 16);
  213. internal_return_status = aes_gcm_wrapper(1, ip_base64_client_public_key_ciphertext, ip_base64_client_public_key_ciphertext_length,
  214. ciphertext_to_decryptor, &ciphertext_to_decryptor_length );
  215. // Error checking on ciphertext that is to be sent to decryptor
  216. if(internal_return_status != 0)
  217. {
  218. free(ciphertext_to_decryptor);
  219. return internal_return_status;
  220. }
  221. printf("Sending this ciphertext and tag to the decryptor enclave:\n");
  222. for(counter=0;counter< ciphertext_to_decryptor_length;counter++)
  223. printf("0x%02x ", ciphertext_to_decryptor[counter]);
  224. printf("\n"); fflush(stdout);
  225. // write message to decryptor
  226. protobuf_encrypted_msg.set_msg( ciphertext_to_decryptor , ciphertext_to_decryptor_length );
  227. free(ciphertext_to_decryptor);
  228. if(write_protobuf_msg_to_fd(global_decryptor_fd, protobuf_encrypted_msg)!=0)
  229. {
  230. printf("Not all of the client's pub key and ciphertext data was written\n"); fflush(stdout); return 0xfe;
  231. }
  232. // clear the message before setting it again
  233. protobuf_encrypted_msg.clear_msg();
  234. // read encrypted data
  235. printf("Reading msg from decryptor"); fflush(stdout);
  236. if(read_protobuf_msg_from_fd(global_decryptor_fd, protobuf_encrypted_msg)!=0)
  237. {
  238. printf("Not all of the decryptor's message was read\n"); fflush(stdout); return 0xf3;
  239. }
  240. printf("Done reading msg from decryptor\n"); fflush(stdout);
  241. protobuf_encrypted_msg_string=std::string(protobuf_encrypted_msg.msg());
  242. ciphertext_from_decryptor_length=protobuf_encrypted_msg_string.length();
  243. ciphertext_from_decryptor = (unsigned char*) malloc(ciphertext_from_decryptor_length);
  244. memcpy(ciphertext_from_decryptor, protobuf_encrypted_msg_string.c_str(), protobuf_encrypted_msg_string.length());
  245. printf("Got this ciphertext and tag from the decryptor enclave");
  246. for(counter=0;counter< ciphertext_from_decryptor_length;counter++)
  247. printf("0x%02x ", ciphertext_from_decryptor[counter]);
  248. printf("\n");
  249. // Decrypt data from decryptor
  250. /* internal_return_status = aes_gcm_wrapper(0, ciphertext_from_decryptor, ciphertext_from_decryptor_length,
  251. op_plaintext, op_plaintext_length
  252. );
  253. */
  254. internal_return_status = 0x34;
  255. free(ciphertext_from_decryptor);
  256. return internal_return_status;
  257. }