systemLA.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. // Knows only protobuf_sgx objects, protobuf header.
  2. // For socket programming
  3. #include <sys/socket.h>
  4. #include <stdlib.h>
  5. #include <netinet/in.h>
  6. #include <string.h>
  7. #include <errno.h>
  8. #include<unistd.h>
  9. #include <stdio.h>
  10. #include "ProtobufLAMessages.pb.h"
  11. #include <google/protobuf/io/coded_stream.h>
  12. #include <google/protobuf/io/zero_copy_stream_impl.h>
  13. using namespace google::protobuf::io;
  14. #include "protobufLAInitiator.h"
  15. #include "../Decryptor/Decryptor_u.h"
  16. #include "sgx_tcrypto.h"
  17. #include <iostream>
  18. #include "Openssl_crypto.h"
  19. // TODO: Make these private functions
  20. int apache_fd;
  21. int decrypt_client_data_wrapper(unsigned char* op_plaintext , uint32_t own_enclave_id);
  22. int read_protobuf_msg_from_fd(int accept_fd, google::protobuf::MessageLite& message)
  23. {
  24. ZeroCopyInputStream* raw_input;
  25. CodedInputStream* coded_input;
  26. uint32_t size;
  27. CodedInputStream::Limit limit;
  28. raw_input = new FileInputStream(accept_fd);
  29. coded_input = new CodedInputStream(raw_input);
  30. if(!coded_input->ReadVarint32(&size))
  31. {
  32. printf("Error in reading size of msg");
  33. fflush(stdout);
  34. return -1;
  35. }
  36. //printf("size of msg was read to be %" PRIu32 " \n", size);
  37. fflush(stdout);
  38. limit = coded_input->PushLimit(size);
  39. if(!message.ParseFromCodedStream(coded_input))
  40. {
  41. printf("Error in parsing msg");
  42. fflush(stdout);
  43. return -1;
  44. }
  45. coded_input->PopLimit(limit);
  46. delete raw_input;
  47. delete coded_input;
  48. return 0;
  49. }
  50. // TODO: private functions
  51. int write_protobuf_msg_to_fd(int accept_fd, google::protobuf::MessageLite& message)
  52. {
  53. ZeroCopyOutputStream* raw_output = new FileOutputStream(accept_fd);
  54. CodedOutputStream* coded_output = new CodedOutputStream(raw_output);
  55. coded_output->WriteVarint32(message.ByteSize());
  56. if(!message.SerializeToCodedStream(coded_output))
  57. {
  58. printf("SerializeToCodedStream failed");
  59. fflush(stdout);
  60. return -1;
  61. }
  62. // As per this - https://stackoverflow.com/questions/22881876/protocol-buffers-how-to-serialize-and-deserialize-multiple-messages-into-a-file?noredirect=1&lq=1
  63. // 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)
  64. delete coded_output;
  65. delete raw_output;
  66. fflush(stdout);
  67. return 0;
  68. }
  69. // Sets up a socket to bind and listen to the given port. Returns FD of the socket on success, -1 on failure (and prints a msg to stdout with the errno)
  70. int set_up_socket(int port, sockaddr_in* address)
  71. {
  72. int server_fd = 0;
  73. // Creating socket file descriptor for listening for attestation requests.
  74. server_fd = socket(AF_INET, SOCK_STREAM | SOCK_CLOEXEC, 0);
  75. if (server_fd == -1)
  76. {
  77. printf("Error in creating a socket - %d", errno);
  78. return -1;
  79. }
  80. // Preparing the address struct for binding
  81. address->sin_family = AF_INET;
  82. address->sin_addr.s_addr = INADDR_ANY; // Todo: should this be localhost?
  83. address->sin_port = htons(port);
  84. // memset(address->sin_zero,0,sizeof(address->sin_zero));
  85. socklen_t addrlen = sizeof(*address);
  86. // Binding
  87. if (bind(server_fd, (sockaddr*)address, addrlen)<0)
  88. {
  89. printf("Error in binding %d - port was %d - ", errno, port);
  90. return -1;
  91. }
  92. // Listening
  93. if (listen(server_fd, 128) < 0)
  94. {
  95. printf("Error in listening %d", errno);
  96. return -1;
  97. }
  98. return server_fd;
  99. }
  100. int local_attestation_initiator(int port, uint32_t own_enclave_id)
  101. {
  102. // declare msg1, msg2, msg3 protobuf objects
  103. protobuf_sgx_dh_msg1_t protobuf_msg1;
  104. protobuf_sgx_dh_msg2_t protobuf_msg2;
  105. protobuf_sgx_dh_msg3_t protobuf_msg3;
  106. protobuf_post_LA_encrypted_msg_t protobuf_encrypted_msg;
  107. uint32_t protobuf_sgx_ret; uint32_t sgx_ret;
  108. // For socket to listen to the Apache enclave.
  109. int server_fd=0; int accept_fd = 0;
  110. struct sockaddr_in own_addr;
  111. struct sockaddr_storage apache_addr; socklen_t apache_addr_size = sizeof(apache_addr);
  112. uint32_t session_id; uint8_t read_or_write;
  113. size_t bytes_read_post_la; uint8_t encrypted_apache_mrsigner_and_tag[48];
  114. size_t bytes_written_post_la;
  115. // int counter;
  116. server_fd=set_up_socket(port, &own_addr);
  117. if(server_fd==-1)
  118. return -1;
  119. printf("Successfully set up a socket to communicate with the Apache enclave.\n");
  120. fflush(stdout);
  121. protobuf_sgx_ret = generate_protobuf_dh_msg1(own_enclave_id, protobuf_msg1, &session_id);
  122. if(protobuf_sgx_ret != 0)
  123. {
  124. printf("Error in generate_protobuf_dh_msg1: 0x%x", protobuf_sgx_ret); fflush(stdout); return protobuf_sgx_ret;
  125. }
  126. accept_fd = accept(server_fd, (struct sockaddr *)&apache_addr,&apache_addr_size);
  127. if (accept_fd <0)
  128. {
  129. printf("Error in accepting %d", errno);
  130. return -1;
  131. }
  132. printf("Accepted fd\n"); fflush(stdout);
  133. if(write_protobuf_msg_to_fd(accept_fd, protobuf_msg1)!=0)
  134. return -1;
  135. if(read_protobuf_msg_from_fd(accept_fd, protobuf_msg2)!=0)
  136. return -1;
  137. protobuf_sgx_ret = process_protobuf_dh_msg2_generate_protobuf_dh_msg3(own_enclave_id, protobuf_msg2, protobuf_msg3, &session_id, &read_or_write);
  138. if(protobuf_sgx_ret != 0)
  139. {
  140. printf("Error in generate_protobuf_dh_msg2: 0x%x", protobuf_sgx_ret); fflush(stdout); return protobuf_sgx_ret;
  141. }
  142. if(write_protobuf_msg_to_fd(accept_fd, protobuf_msg3)!=0)
  143. return -1;
  144. // read_or_write=0;
  145. printf("Here\n"); fflush(stdout);
  146. if(read_or_write)
  147. {
  148. bytes_read_post_la=read(accept_fd, encrypted_apache_mrsigner_and_tag, 32);
  149. if(bytes_read_post_la!=32)
  150. {
  151. printf("Not all of the encrypted apache's mrsigner was read from the verifier.\n"); fflush(stdout); return 0xfe;
  152. }
  153. bytes_read_post_la=read(accept_fd, encrypted_apache_mrsigner_and_tag+32, 16);
  154. if(bytes_read_post_la!=16)
  155. {
  156. printf("Not all of the encrypted apache's mrsigner **tag** was read from the verifier.\n"); fflush(stdout); return 0xfe;
  157. }
  158. uint32_t count;
  159. for(count=0;count<48;count++)
  160. printf("0x%02x ", encrypted_apache_mrsigner_and_tag[count]);
  161. printf("\n");fflush(stdout);
  162. // sgx_ret=decrypt_wrapper(own_enclave_id, encrypted_apache_mrsigner_and_tag, 32, encrypted_apache_mrsigner_and_tag+32 , plaintext);
  163. Decryptor_decrypt_verifiers_message_set_apache_mrsigner(own_enclave_id, &sgx_ret, encrypted_apache_mrsigner_and_tag, encrypted_apache_mrsigner_and_tag+32);
  164. if(sgx_ret!=0)
  165. {
  166. printf("Error in decryption: 0x%x\n", sgx_ret); fflush(stdout); return sgx_ret;
  167. }
  168. printf("Successful decryption\n"); fflush(stdout);
  169. }
  170. else
  171. {
  172. apache_fd=accept_fd;
  173. uint8_t encrypted_sign_data_and_sign_and_tag[176];
  174. memset(encrypted_sign_data_and_sign_and_tag,0x0,176);
  175. uint8_t plaintext_sign_data_and_sign[160];
  176. uint8_t plaintext_priv_key[32];
  177. sgx_ec256_signature_t sig2;
  178. Decryptor_create_and_encrypt_mitigator_header_value(own_enclave_id, &sgx_ret, plaintext_sign_data_and_sign, encrypted_sign_data_and_sign_and_tag , encrypted_sign_data_and_sign_and_tag+160, plaintext_priv_key,&sig2);
  179. if(sgx_ret!=0)
  180. {
  181. printf("Error in generating encrypted mitigator header:0x%x\n", sgx_ret); fflush(stdout); return 0xf3;
  182. }
  183. uint32_t count;
  184. for(count=0;count<160;count++)
  185. {
  186. printf("0x%02x ", encrypted_sign_data_and_sign_and_tag[count]);
  187. }
  188. printf("\n"); fflush(stdout);
  189. printf("Plaintext Signature data:\n"); fflush(stdout);
  190. for(count=0;count<96;count++)
  191. {
  192. printf("0x%02x ", plaintext_sign_data_and_sign[count]);
  193. }
  194. printf("\n"); fflush(stdout);
  195. printf("Plaintext signature: \n"); fflush(stdout);
  196. for(count=0;count<32;count++)
  197. {
  198. printf("%02x", plaintext_sign_data_and_sign[count+96]);
  199. }
  200. printf("\n"); fflush(stdout);
  201. for(count=32;count<64;count++)
  202. {
  203. printf("%02x", plaintext_sign_data_and_sign[count+96]);
  204. }
  205. printf("\n"); fflush(stdout);
  206. printf("Heres the private key used to sign this \n"); // TODO: Remove this printf and the private key parts to the ecall
  207. for(count=0;count<32;count++)
  208. printf("%02x", plaintext_priv_key[31-count]);
  209. printf("\n"); fflush(stdout);
  210. for(count=0;count<8;count++)
  211. {
  212. printf("%02x ", sig2.x[count]);
  213. }
  214. printf("\n"); fflush(stdout);
  215. for(count=0;count<8;count++)
  216. {
  217. printf("%02x ", sig2.y[count]);
  218. }
  219. printf("\n"); fflush(stdout);
  220. protobuf_encrypted_msg.set_msg((void*)encrypted_sign_data_and_sign_and_tag, 176);
  221. if(write_protobuf_msg_to_fd(apache_fd, protobuf_encrypted_msg) != 0)
  222. {
  223. printf("Not all of the decryptor's signature was written to the Apache.\n"); fflush(stdout); return 0xfe;
  224. }
  225. unsigned char op_plaintext[160];
  226. do {
  227. // sleep(100);
  228. decrypt_client_data_wrapper(op_plaintext, own_enclave_id);
  229. // sleep(100);
  230. } while(true);
  231. }
  232. printf("Successfully done Local attestation\n");
  233. fflush(stdout);
  234. return 0;
  235. }
  236. // decrypt_client_data function that does a read-then-write loop
  237. // say msg length amount of bytes are read
  238. ////// TODO: first need to decrypt all data received with the aes-gcm apache_iv
  239. ////// Decryptor.cpp function gets the first 64 bytes as first arg and the rest of ciphertext as 2nd arg.
  240. // then need to call the sgx's compute_shared_key fn for ECDH key - on first 64 bytes.
  241. // print this key
  242. // call sha256 on it
  243. // TODO: decrypt rest of msglength - 64 bytes using this key. (set IV in crypto function)
  244. ////// TODO: then encrypt all user data with apache's key
  245. ////// return here
  246. /// write data.
  247. int decrypt_client_data_wrapper(unsigned char* op_plaintext , uint32_t own_enclave_id)
  248. {
  249. protobuf_post_LA_encrypted_msg_t protobuf_msg_from_apache;
  250. unsigned char* msg_from_apache;
  251. unsigned int protobuf_msg_from_apache_length;
  252. uint32_t sgx_ret_status;
  253. unsigned char client_keys_and_data_encrypted_to_enclave[160+64];
  254. unsigned int client_data_encrypted_to_enclave_length;
  255. unsigned char client_data_encrypted_to_apache[160+64];
  256. unsigned int client_data_encrypted_to_apache_length;
  257. printf("Reading msg from apache"); fflush(stdout);
  258. if(read_protobuf_msg_from_fd(apache_fd, protobuf_msg_from_apache)!=0)
  259. {
  260. printf("Not all of the Apache's message was read\n"); fflush(stdout); return 0xfe;
  261. }
  262. protobuf_msg_from_apache_length = protobuf_msg_from_apache.msg().length();
  263. msg_from_apache = (unsigned char*) protobuf_msg_from_apache.msg().c_str();
  264. std::string protobuf_encrypted_msg_string(protobuf_msg_from_apache.msg());
  265. int counter;
  266. memset(client_keys_and_data_encrypted_to_enclave, 0, 160+64);
  267. for(counter=0;counter<protobuf_msg_from_apache_length;counter++)
  268. {
  269. client_keys_and_data_encrypted_to_enclave[counter]=*(msg_from_apache+counter);
  270. printf("%d ",msg_from_apache[counter]);
  271. }
  272. printf("\n"); fflush(stdout);
  273. client_data_encrypted_to_enclave_length = protobuf_msg_from_apache_length-64; // TODO: we hope it's greater than 0
  274. // Just so that the ciphertext is returned back to Apache in case decrypt_client_data fails.
  275. for(counter=0;counter<client_data_encrypted_to_enclave_length;counter++)
  276. client_data_encrypted_to_apache[counter]=client_keys_and_data_encrypted_to_enclave[counter+64];
  277. printf("Key in big endian form:\n"); fflush(stdout);
  278. for(counter=0; counter<64; counter++)
  279. printf("0x%02x ", *(client_keys_and_data_encrypted_to_enclave + counter));
  280. printf("\n"); fflush(stdout);
  281. client_data_encrypted_to_apache_length = client_data_encrypted_to_enclave_length;
  282. uint8_t clen;
  283. Decryptor_decrypt_client_data(own_enclave_id, &sgx_ret_status, client_keys_and_data_encrypted_to_enclave, client_data_encrypted_to_enclave_length, client_data_encrypted_to_apache, &clen);
  284. if(sgx_ret_status != 0)
  285. {
  286. printf("decrypt_client_data returned :0x%x\n", sgx_ret_status); fflush(stdout); //return sgx_ret_status;
  287. }
  288. if(clen != 0)
  289. client_data_encrypted_to_apache_length = clen;
  290. printf("About to write the following bytes to the apache\n"); fflush(stdout);
  291. for(counter=0;counter<client_data_encrypted_to_apache_length;counter++)
  292. printf("%d,", client_data_encrypted_to_apache[counter]);
  293. printf("\n"); fflush(stdout);
  294. protobuf_msg_from_apache.set_msg((void*) client_data_encrypted_to_apache, client_data_encrypted_to_apache_length);// Is this message set tho?
  295. if(write_protobuf_msg_to_fd(apache_fd, protobuf_msg_from_apache)!=0)
  296. {
  297. printf("Not all of the protobuf message was written to Apache.\n"); fflush(stdout); return 0xfe;
  298. }
  299. printf("Wrote data to Apache of length %d \n", protobuf_msg_from_apache.ByteSize());fflush(stdout);
  300. return 0;
  301. }