#include "oasm_lib.h" #include "enclave_api.h" #include "obliv.hpp" // Routines for processing private data obliviously // Obliviously tally the number of messages in the given buffer destined // for each storage node. Each message is of size msg_size bytes. // There are num_msgs messages in the buffer. There are // num_storage_nodes storage nodes in total. The destination storage // node of each message is determined by looking at the top // DEST_STORAGE_NODE_BITS bits of the (little-endian) 32-bit word at the // beginning of the message; this will be a number between 0 and // num_storage_nodes-1, which is not necessarily the node number of the // storage node, which may be larger if, for example, there are a bunch // of routing or ingestion nodes that are not also storage nodes. The // return value is a vector of length num_storage_nodes containing the // tally. std::vector obliv_tally_stg(const uint8_t *buf, uint32_t msg_size, uint32_t num_msgs, uint32_t num_storage_nodes) { // The _contents_ of buf are private, but everything else in the // input is public. The contents of the output tally (but not its // length) are also private. std::vector tally(num_storage_nodes, 0); // This part must all be oblivious except for the length checks on // num_msgs and num_storage_nodes while (num_msgs) { uint32_t storage_node_id = (*(const uint32_t*)buf) >> DEST_UID_BITS; for (uint32_t i=0; i &tally, uint32_t tot_padding) { // A value with 0 in the top DEST_STORAGE_NODE_BITS and all 1s in // the bottom DEST_UID_BITS. uint32_t pad_user = (1< &tally, uint32_t msgs_per_stg) { const nodenum_t num_storage_nodes = nodenum_t(tally.size()); // Determine the number of messages exceeding and under the maximum that // can be sent to a storage server. Oblivious to the contents of tally // vector. std::vector excess(num_storage_nodes, 0); std::vector padding(num_storage_nodes, 0); for (nodenum_t i=0; i msgs_per_stg; uint32_t diff = tally[i] - msgs_per_stg; excess[i] = oselect_uint32_t(0, diff, exceeds); diff = msgs_per_stg - tally[i]; padding[i] = oselect_uint32_t(0, diff, !exceeds); } uint8_t *cur_msg = buf + ((num_msgs-1)*msg_size); uint32_t pad_user = (1<> DEST_UID_BITS; bool node_excess = false; for (uint32_t j=0; j 0); node_excess = oselect_uint32_t(node_excess, cur_node_excess, at_msg_node); excess[j] -= (at_msg_node & cur_node_excess); tally[j] -= (at_msg_node & cur_node_excess); } // Find first node that needs padding. Decrement padding count and // increment tally for that if current-message node has excess messages. bool found_padding = false; nodenum_t found_padding_node = 0; for (uint32_t j=0; j