|
@@ -0,0 +1,108 @@
|
|
|
+typedef uint8_t token[SGX_AESGCM_MAC_SIZE];
|
|
|
+typedef uint8_t aes_key[SGX_AESGCM_KEY_SIZE];
|
|
|
+
|
|
|
+// #define VERBOSE_CLIENT
|
|
|
+
|
|
|
+/*
|
|
|
+
|
|
|
+ Client -> Ingestion Server (C->I) communication protocols:
|
|
|
+
|
|
|
+ Each client has a 4-byte Client ID (id). Client(C) and ingestion servers(I)
|
|
|
+ are bootstrapped with a shared secret key (K). Clients messages to the
|
|
|
+ ingestion server have an 8-byte header followed by some data. There are
|
|
|
+ two types of client messages for C->I communications:
|
|
|
+
|
|
|
+ 1) CLIENT_AUTHENTICATE:
|
|
|
+ Header: (0x00 + 4-byte Client ID)
|
|
|
+ Body: HMAC(K, epoch_number)
|
|
|
+ - where MAC is a Keyed MAC with the shared secret key K
|
|
|
+ over the epoch number.
|
|
|
+
|
|
|
+ 2) CLIENT_MESSAGE_BUNDLE:
|
|
|
+ Header: (0x01 + 4-byte Client ID)
|
|
|
+ Body: CMP
|
|
|
+ - where CMP = Client Message Payload is
|
|
|
+ IV, AESGCM([CM_1], [CM_2], ..., [CM_k]), TAG
|
|
|
+ with k being the maximum number of messages a client can send in an
|
|
|
+ epoch, and IV and TAG are the AESGCM IV and TAG for that CMP.
|
|
|
+ - each CM = Client Message, has the format:
|
|
|
+ 4-byte Sender ID , 4-byte Recipient ID, 16-byte Token,
|
|
|
+ <Upto msg_size - 24> - bytes of message data
|
|
|
+ -NOTE: This will eventually expand to accomodate Token manipulation
|
|
|
+ component of clients' messages as well.
|
|
|
+
|
|
|
+ Headers are stored as the low 5 bytes of a uint64_t.
|
|
|
+
|
|
|
+*/
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/*
|
|
|
+ Structure for capture each individual simulated client's state
|
|
|
+
|
|
|
+*/
|
|
|
+class Client
|
|
|
+{
|
|
|
+
|
|
|
+private:
|
|
|
+ // Clients' have a simulator ID sim_id used for:
|
|
|
+ // (i) the simulator to divvy up clients across threads
|
|
|
+ // (ii) the simulator and ingestion servers to align simulated clients
|
|
|
+ // and their pre-established shared-secrets
|
|
|
+ clientid_t sim_id;
|
|
|
+
|
|
|
+ // The actual client id used by TEEMS is id.
|
|
|
+ // Format: the first DEST_STORAGE_NODE_BITS bits store the storage node
|
|
|
+ // number and the userid at that storage node in the last DEST_UID_BITS
|
|
|
+ clientid_t id;
|
|
|
+ aes_key key;
|
|
|
+ unsigned char iv[SGX_AESGCM_IV_SIZE];
|
|
|
+
|
|
|
+ boost::asio::ip::tcp::socket *ingestion_sock = NULL;
|
|
|
+
|
|
|
+ void generateAuthenticationMessage();
|
|
|
+
|
|
|
+ void generateMessageBundle(uint8_t priv_out, uint32_t msg_size,
|
|
|
+ unsigned char *pt_msgbundle);
|
|
|
+
|
|
|
+ bool encryptMessageBundle(uint32_t bundle_size, unsigned char *pt_msgbundle,
|
|
|
+ unsigned char* enc_msgbundle);
|
|
|
+
|
|
|
+public:
|
|
|
+
|
|
|
+ Client () {
|
|
|
+ memset(key, 0, SGX_AESGCM_KEY_SIZE);
|
|
|
+ memset(iv, 0, SGX_AESGCM_IV_SIZE);
|
|
|
+ }
|
|
|
+
|
|
|
+ void initClient(clientid_t cid, aes_key ckey, uint16_t num_storage_nodes,
|
|
|
+ std::vector<uint16_t> &storage_map) {
|
|
|
+ sim_id = cid;
|
|
|
+ uint16_t stg_no = cid % num_storage_nodes;
|
|
|
+ uint16_t stg_id = storage_map[stg_no];
|
|
|
+ id = stg_id << DEST_UID_BITS;
|
|
|
+ id += (cid/num_storage_nodes);
|
|
|
+ printf("Client sim_id = %d, stg_id = %d, cid = %d\n", sim_id, stg_id, id);
|
|
|
+ memcpy(key, ckey, SGX_AESGCM_KEY_SIZE);
|
|
|
+ }
|
|
|
+
|
|
|
+ bool socketReady(){
|
|
|
+ return(ingestion_sock!=NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ clientid_t getid(){
|
|
|
+ return id;
|
|
|
+ }
|
|
|
+
|
|
|
+ unsigned char* getKey(){
|
|
|
+ return ((unsigned char*) key);
|
|
|
+ }
|
|
|
+
|
|
|
+ void initializeSocket(boost::asio::io_context &ioc, NodeConfig &ing_server);
|
|
|
+
|
|
|
+ int sendAuthMessage();
|
|
|
+
|
|
|
+ void sendMessageBundle(uint16_t priv_out, uint16_t msg_size,
|
|
|
+ unsigned char *pt_msgbundle, unsigned char *enc_msgbundle);
|
|
|
+
|
|
|
+};
|