From b5cd5698d1ce7f78ff4418481a2d2f959304e637 Mon Sep 17 00:00:00 2001 From: Arvid Lunnemark Date: Tue, 2 Aug 2022 09:27:33 -0700 Subject: [PATCH] Fix the PIR potential attacks (#57) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * test should be mostly working * 🔄 "fix the randomness " Update anysphere/asphr commit SHA 🔗 https://github.com/anysphere/asphr/commit/5d62ae899118588419a0f2bce6e0c6bb315036f6 * finish index rotation * 🔄 "finish index rotation " Update anysphere/asphr commit SHA 🔗 https://github.com/anysphere/asphr/commit/18ee6bc932220f890d7fa70dccd1fc6ed61f227b * 🔄 "fix all problems." Update anysphere/asphr commit SHA 🔗 https://github.com/anysphere/asphr/commit/f906a71e645df08d3cec0720684a3f7c41a59547 * final commit and fixes. Co-authored-by: Shengtong Zhang Co-authored-by: Sualeh Asif Co-authored-by: Sualeh Asif --- daemon/db/db.rs | 25 +++++++++++++++++++++++++ daemon/transmitter/transmitter.cc | 31 +++++++++++++++++++++---------- 2 files changed, 46 insertions(+), 10 deletions(-) diff --git a/daemon/db/db.rs b/daemon/db/db.rs index 32f8b36c..b4b5306a 100644 --- a/daemon/db/db.rs +++ b/daemon/db/db.rs @@ -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 { @@ -612,6 +616,9 @@ pub mod ffi { fn get_friend_address(&self, uid: i32) -> Result
; // fails if no such friend exists fn get_random_enabled_friend_address_excluding(&self, uids: Vec) -> Result
; + // 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; // 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; @@ -2159,6 +2166,7 @@ impl DB { q.first(conn) } + /// Get a friend from the database, given their public ID. /// /// Arguments: @@ -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 + { + 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::(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 diff --git a/daemon/transmitter/transmitter.cc b/daemon/transmitter/transmitter.cc index 9984ed38..895a22b3 100644 --- a/daemon/transmitter/transmitter.cc +++ b/daemon/transmitter/transmitter.cc @@ -24,8 +24,11 @@ auto generate_dummy_address(const db::Registration& reg) -> db::Address { // convert dummy_read_write_keys to a rust::Vec 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 { @@ -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 stub) @@ -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( - rust_u8Vec_to_string(reg.pir_secret_key), - rust_u8Vec_to_string(reg.pir_galois_key))); + cached_pir_client = std::optional(std::make_unique()); cached_pir_client_secret_key = rust_u8Vec_to_string(reg.pir_secret_key); dummy_address = generate_dummy_address(reg); @@ -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 @@ -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,