Skip to content

Commit

Permalink
Fix the PIR potential attacks (#57)
Browse files Browse the repository at this point in the history
* test should be mostly working

* πŸ”„ "fix the randomness
"
Update anysphere/asphr commit SHA
πŸ”— anysphere/asphr@5d62ae8

* finish index rotation

* πŸ”„ "finish index rotation
"
Update anysphere/asphr commit SHA
πŸ”— anysphere/asphr@18ee6bc

* πŸ”„ "fix all problems."
Update anysphere/asphr commit SHA
πŸ”— anysphere/asphr@f906a71

* final commit and fixes.

Co-authored-by: Shengtong Zhang <[email protected]>
Co-authored-by: Sualeh Asif <[email protected]>
Co-authored-by: Sualeh Asif <[email protected]>
  • Loading branch information
4 people authored Aug 2, 2022
1 parent 8ae31aa commit b5cd569
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 10 deletions.
25 changes: 25 additions & 0 deletions daemon/db/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,10 @@ pub mod ffi {
pub authentication_token: String,
pub public_id: String,
}

// Note, that the pir_secret_key and pir_galois_key are not deprecated since they are regenereated
// on every request. We have them here for consistency.
// TOOD(sualeh, arvid220u): remove them if we need to.
#[derive(Insertable)]
#[diesel(table_name = crate::schema::registration)]
struct RegistrationFragment {
Expand Down Expand Up @@ -612,6 +616,9 @@ pub mod ffi {
fn get_friend_address(&self, uid: i32) -> Result<Address>;
// fails if no such friend exists
fn get_random_enabled_friend_address_excluding(&self, uids: Vec<i32>) -> Result<Address>;
// DO NOT USE OUTSIDE OF TESTING
// returns the sequence number of the last ACKed message from the friend
fn test_only_get_ack_seq_num(&self, uid: i32) -> Result<i32>;

// this exists as a helper function if you need it. They take a connection
// fn get_friend_from_public_id(&self, public_id: &str) -> Result<CompleteFriend>;
Expand Down Expand Up @@ -2159,6 +2166,7 @@ impl DB {
q.first(conn)
}


/// Get a friend from the database, given their public ID.
///
/// Arguments:
Expand Down Expand Up @@ -2253,6 +2261,23 @@ impl DB {
})
}

// Get the newest sequence number ACKed by the friend.
// There should be no reason to use this outside of testing
pub fn test_only_get_ack_seq_num(&self, uid: i32) -> Result<i32, anyhow::Error>
{
use crate::schema::transmission;

let mut conn = self.connect()?;
conn.transaction::<_, anyhow::Error, _>(|conn_b| {
let ack_seq_num = transmission::table
.find(uid)
.select(transmission::sent_acked_seqnum)
.first::<i32>(conn_b)
.context("get_ack_seq_num, failed to find seqnum from the transmission table")?;
Ok(ack_seq_num)
})
}

/// We insert a message into the `message` table,
/// then we insert a sent message into the `sent` table,
/// then we insert the chunks into the `outgoing_chunk` table
Expand Down
31 changes: 21 additions & 10 deletions daemon/transmitter/transmitter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,11 @@ auto generate_dummy_address(const db::Registration& reg) -> db::Address {
// convert dummy_read_write_keys to a rust::Vec<uint8_t>
auto read_key_vec_rust = string_to_rust_u8Vec(dummy_read_write_keys.first);
auto write_key_vec_rust = string_to_rust_u8Vec(dummy_read_write_keys.second);

return (db::Address){-1, 0, read_key_vec_rust, write_key_vec_rust, 0};
// The dummy PIR index is designed to not coincide
// with any other index. Since it is very very
// large, it will result in an all zero PIR query.
return (db::Address){-1, DUMMY_INDEX, read_key_vec_rust, write_key_vec_rust,
DUMMY_INDEX};
}

auto generate_dummy_async_invitation() -> db::OutgoingAsyncInvitation {
Expand All @@ -49,8 +52,7 @@ auto generate_dummy_async_invitation() -> db::OutgoingAsyncInvitation {
.invitation_public_key = invitation_public_key_rust,
.kx_public_key = kx_public_key_rust,
.message = "Hello dummy",
.sent_at = 0,
};
.sent_at = 0};
}

Transmitter::Transmitter(Global& G, shared_ptr<asphrserver::Server::Stub> stub)
Expand All @@ -67,9 +69,7 @@ auto Transmitter::setup_registration_caching() -> void {
if (!cached_pir_client.has_value() ||
cached_pir_client_secret_key.value() != pir_secret_key_str) {
auto reg = G.db->get_registration();
cached_pir_client = std::optional(std::make_unique<FastPIRClient>(
rust_u8Vec_to_string(reg.pir_secret_key),
rust_u8Vec_to_string(reg.pir_galois_key)));
cached_pir_client = std::optional(std::make_unique<FastPIRClient>());

cached_pir_client_secret_key = rust_u8Vec_to_string(reg.pir_secret_key);
dummy_address = generate_dummy_address(reg);
Expand Down Expand Up @@ -215,8 +215,14 @@ auto Transmitter::retrieve() -> void {
for (auto& r : receive_addresses) {
friends_to_receive_from += std::to_string(r.uid) + ",";
}

// log real name as well as uid
auto friends_address = string("");
for (auto& r : receive_addresses) {
friends_address += std::to_string(r.read_index) + ",";
}
ASPHR_LOG_INFO("Receiving messages from the following friends.", friend_uids,
friends_to_receive_from);
friends_to_receive_from, friend_address, friends_address);

// -----
// Step 2: execute the PIR queries
Expand Down Expand Up @@ -376,12 +382,17 @@ auto Transmitter::retrieve() -> void {
}
}
} else {
std::stringstream ss;
for (auto& c : decoded) {
ss << std::hex << (int)c;
}
ASPHR_LOG_INFO(
"Failed to decrypt message (message was probably not for us, "
"which "
"is okay).",
decrypted_error_code, decrypted.status().code(),
decrypted_error_message, decrypted.status().message());
raw_message, ss.str(), decrypted_error_code,
decrypted.status().code(), decrypted_error_message,
decrypted.status().message());
}
} else {
ASPHR_LOG_ERR("Could not retrieve PIR reply from server.", friend_uid,
Expand Down

0 comments on commit b5cd569

Please sign in to comment.