|
|
@@ -1,8 +1,15 @@
|
|
|
#[cfg(all(test, feature = "bridgeauth"))]
|
|
|
+use super::proto::{
|
|
|
+ check_blockage, issue_invite,
|
|
|
+ level_up::{self, LEVEL_INTERVAL},
|
|
|
+ migration, open_invite,
|
|
|
+ trust_promotion::{self, UNTRUSTED_INTERVAL},
|
|
|
+};
|
|
|
+#[cfg(all(test, feature = "bridgeauth"))]
|
|
|
use super::*;
|
|
|
|
|
|
#[cfg(all(test, feature = "bridgeauth"))]
|
|
|
-use crate::bridge_table::BridgeLine;
|
|
|
+use crate::{bridge_table::BridgeLine, lox_creds::BucketReachability};
|
|
|
|
|
|
#[cfg(all(test, feature = "bridgeauth"))]
|
|
|
use rand::RngCore;
|
|
|
@@ -53,6 +60,37 @@ impl TestHarness {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ /// Blocks a percentage of the bridges for the passed Test Harness
|
|
|
+ /// excluding the hot spare buckets as they will not have been handed out.
|
|
|
+ /// The logic assumes hot spare buckets are appended to the end of the bridge_table
|
|
|
+ /// bucket list.
|
|
|
+
|
|
|
+ fn block_percent_bridges(&mut self, percent_blockage: usize) {
|
|
|
+ let blockable_range =
|
|
|
+ self.ba.bridge_table.buckets.len() - self.ba.bridge_table.spares.len();
|
|
|
+ let mut block_index: HashSet<usize> = HashSet::new();
|
|
|
+ let mut rng = rand::rngs::OsRng;
|
|
|
+
|
|
|
+ while block_index.len() < percent_blockage {
|
|
|
+ let rand_num = rng.gen_range(1..blockable_range);
|
|
|
+ if !self.bdb.openinv_buckets.contains(&(rand_num as u32))
|
|
|
+ && !self.bdb.distributed_buckets.contains(&(rand_num as u32))
|
|
|
+ && !block_index.contains(&rand_num)
|
|
|
+ {
|
|
|
+ block_index.insert(rand_num);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for index in block_index {
|
|
|
+ let ba_clone = self.ba.bridge_table.buckets.clone();
|
|
|
+ if let Some(bridgelines) = ba_clone.get(&u32::try_from(index).unwrap()) {
|
|
|
+ for bridgeline in bridgelines {
|
|
|
+ self.ba.bridge_blocked(bridgeline, &mut self.bdb);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// Verify the two MACs on a Lox credential
|
|
|
pub fn verify_lox(&self, cred: &lox_creds::Lox) {
|
|
|
assert!(
|
|
|
@@ -119,6 +157,186 @@ impl TestHarness {
|
|
|
* cred.MAC.P;
|
|
|
assert_eq!(Q, cred.MAC.Q, "Invitation MAC Q should match");
|
|
|
}
|
|
|
+
|
|
|
+ pub fn open_invite(
|
|
|
+ &mut self,
|
|
|
+ rng: &mut (impl CryptoRng + RngCore),
|
|
|
+ invite: &[u8; OPENINV_LENGTH],
|
|
|
+ ) -> Lox {
|
|
|
+ let open_invitation_request = open_invite::request(rng, self.ba.lox_pub.clone());
|
|
|
+ assert!(
|
|
|
+ open_invitation_request.is_ok(),
|
|
|
+ "Open invitation request should succeed"
|
|
|
+ );
|
|
|
+ let (request, client_state) = open_invitation_request.unwrap();
|
|
|
+ let open_invitation_response = self.ba.open_invitation(request, invite);
|
|
|
+ assert!(
|
|
|
+ open_invitation_response.is_ok(),
|
|
|
+ "Open invitation response from server should succeed"
|
|
|
+ );
|
|
|
+ let (response, _) = open_invitation_response.unwrap();
|
|
|
+ let lox_cred = open_invite::handle_response(client_state, response);
|
|
|
+ assert!(lox_cred.is_ok(), "Handle response should succeed");
|
|
|
+ lox_cred.unwrap()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn trust_promotion(
|
|
|
+ &mut self,
|
|
|
+ rng: &mut (impl CryptoRng + RngCore),
|
|
|
+ cred: Lox,
|
|
|
+ ) -> Migration {
|
|
|
+ self.advance_days((UNTRUSTED_INTERVAL + 1).try_into().unwrap());
|
|
|
+ let trust_promo_request =
|
|
|
+ trust_promotion::request(rng, cred, self.ba.migrationkey_pub.clone(), self.ba.today());
|
|
|
+ assert!(
|
|
|
+ trust_promo_request.is_ok(),
|
|
|
+ "Trust Promotion request should succeed"
|
|
|
+ );
|
|
|
+ let (tp_request, tp_client_state) = trust_promo_request.unwrap();
|
|
|
+ let trust_promo_response = self.ba.handle_trust_promotion(tp_request);
|
|
|
+ assert!(
|
|
|
+ trust_promo_response.is_ok(),
|
|
|
+ "Trust promotion response from server should succeed"
|
|
|
+ );
|
|
|
+ let (response, enc) = trust_promo_response.unwrap();
|
|
|
+ let mig_cred = trust_promotion::handle_response(
|
|
|
+ self.ba.migration_pub.clone(),
|
|
|
+ tp_client_state,
|
|
|
+ response,
|
|
|
+ enc,
|
|
|
+ );
|
|
|
+ assert!(mig_cred.is_ok(), "Handle response should succeed");
|
|
|
+ mig_cred.unwrap()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn migration(
|
|
|
+ &mut self,
|
|
|
+ rng: &mut (impl CryptoRng + RngCore),
|
|
|
+ cred: Lox,
|
|
|
+ mig_cred: Migration,
|
|
|
+ ) -> Lox {
|
|
|
+ let migration_request = migration::request(rng, cred, mig_cred, self.ba.lox_pub.clone());
|
|
|
+ assert!(
|
|
|
+ migration_request.is_ok(),
|
|
|
+ "Migration request should succeed"
|
|
|
+ );
|
|
|
+ let (mig_request, mig_client_state) = migration_request.unwrap();
|
|
|
+ let migration_response = self.ba.handle_migration(mig_request);
|
|
|
+ assert!(
|
|
|
+ migration_response.is_ok(),
|
|
|
+ "Migration response from server should succeed"
|
|
|
+ );
|
|
|
+ let response = migration_response.unwrap();
|
|
|
+ let new_cred = migration::handle_response(mig_client_state, response);
|
|
|
+ assert!(new_cred.is_ok(), "Handle response should succeed");
|
|
|
+ new_cred.unwrap()
|
|
|
+ }
|
|
|
+
|
|
|
+ fn reach_cred(&mut self, cred: Lox) -> BucketReachability {
|
|
|
+ let (id, key) = bridge_table::from_scalar(cred.bucket.unwrap()).unwrap();
|
|
|
+ let encbuckets = self.ba.enc_bridge_table().clone();
|
|
|
+ let reach_pub = self.ba.reachability_pub.clone();
|
|
|
+ let bucket = bridge_table::BridgeTable::decrypt_bucket(
|
|
|
+ id,
|
|
|
+ &key,
|
|
|
+ encbuckets.get(&id).unwrap(),
|
|
|
+ &reach_pub,
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ bucket.1.unwrap()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn level_up(&mut self, rng: &mut (impl CryptoRng + RngCore), cred: Lox) -> Lox {
|
|
|
+ let trust_level: u32 = scalar_u32(&cred.trust_level.unwrap()).unwrap();
|
|
|
+ self.advance_days(LEVEL_INTERVAL[trust_level as usize] + 1);
|
|
|
+ let reachcred = self.reach_cred(cred.clone());
|
|
|
+ let level_up_request = level_up::request(
|
|
|
+ rng,
|
|
|
+ cred.clone(),
|
|
|
+ reachcred,
|
|
|
+ self.ba.lox_pub.clone(),
|
|
|
+ self.ba.today(),
|
|
|
+ );
|
|
|
+ assert!(level_up_request.is_ok(), "Level up request should succeed");
|
|
|
+ let (level_up_request, level_up_client_state) = level_up_request.unwrap();
|
|
|
+ let level_up_response = self.ba.handle_level_up(level_up_request);
|
|
|
+ assert!(
|
|
|
+ level_up_response.is_ok(),
|
|
|
+ "Level up response from server should succeed"
|
|
|
+ );
|
|
|
+ let response = level_up_response.unwrap();
|
|
|
+ let new_cred = level_up::handle_response(level_up_client_state, response);
|
|
|
+ assert!(new_cred.is_ok(), "Handle response should succeed");
|
|
|
+ new_cred.unwrap()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn issue_invite(
|
|
|
+ &mut self,
|
|
|
+ rng: &mut (impl CryptoRng + RngCore),
|
|
|
+ cred: Lox,
|
|
|
+ ) -> (Invitation, Lox) {
|
|
|
+ let reachcred = self.reach_cred(cred.clone());
|
|
|
+ let issue_invite_request = issue_invite::request(
|
|
|
+ rng,
|
|
|
+ cred.clone(),
|
|
|
+ self.ba.lox_pub.clone(),
|
|
|
+ reachcred,
|
|
|
+ self.ba.invitation_pub.clone(),
|
|
|
+ self.ba.today(),
|
|
|
+ );
|
|
|
+ let (issue_invite_request, issue_invite_client_state) = issue_invite_request.unwrap();
|
|
|
+ let issue_invite_response = self.ba.handle_issue_invite(issue_invite_request);
|
|
|
+ assert!(
|
|
|
+ issue_invite_response.is_ok(),
|
|
|
+ "Issue Invite response from server should succeed"
|
|
|
+ );
|
|
|
+ let response = issue_invite_response.unwrap();
|
|
|
+ let i_cred = issue_invite::handle_response(issue_invite_client_state, response);
|
|
|
+ assert!(i_cred.is_ok(), "Handle response should succeed");
|
|
|
+ i_cred.unwrap()
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn block_bridges(&mut self, cred: Lox) {
|
|
|
+ // Get our bridges
|
|
|
+ let (id, key) = bridge_table::from_scalar(cred.bucket.unwrap()).unwrap();
|
|
|
+ let encbuckets = self.ba.enc_bridge_table().clone();
|
|
|
+ let bucket = bridge_table::BridgeTable::decrypt_bucket(
|
|
|
+ id,
|
|
|
+ &key,
|
|
|
+ encbuckets.get(&id).unwrap(),
|
|
|
+ &self.ba.reachability_pub.clone(),
|
|
|
+ )
|
|
|
+ .unwrap();
|
|
|
+ // We should have a Bridge Reachability credential
|
|
|
+ assert!(bucket.1.is_some());
|
|
|
+ // Oh, no! Two of our bridges are blocked!
|
|
|
+ self.ba.bridge_blocked(&bucket.0[0], &mut self.bdb);
|
|
|
+ self.ba.bridge_blocked(&bucket.0[2], &mut self.bdb);
|
|
|
+ }
|
|
|
+
|
|
|
+ pub fn check_blockage(&mut self, rng: &mut (impl CryptoRng + RngCore), cred: Lox) -> Migration {
|
|
|
+ let check_blockage_request =
|
|
|
+ check_blockage::request(rng, cred, self.ba.migrationkey_pub.clone());
|
|
|
+ assert!(
|
|
|
+ check_blockage_request.is_ok(),
|
|
|
+ "Check blockage request should succeed"
|
|
|
+ );
|
|
|
+ let (check_blockage_request, check_blockage_client_state) = check_blockage_request.unwrap();
|
|
|
+ let check_blockage_response = self.ba.handle_check_blockage(check_blockage_request);
|
|
|
+ assert!(
|
|
|
+ check_blockage_response.is_ok(),
|
|
|
+ "Check blockage response from server should succeed"
|
|
|
+ );
|
|
|
+ let (response, enc) = check_blockage_response.unwrap();
|
|
|
+ let mig_cred = check_blockage::handle_response(
|
|
|
+ self.ba.migration_pub.clone(),
|
|
|
+ check_blockage_client_state,
|
|
|
+ response,
|
|
|
+ enc,
|
|
|
+ );
|
|
|
+ assert!(mig_cred.is_ok(), "Handle response should succeed");
|
|
|
+ mig_cred.unwrap()
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/// Create a random BridgeLine for testing
|