123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- #[cfg(all(test, feature = "bridgeauth"))]
- use super::*;
- #[cfg(all(test, feature = "bridgeauth"))]
- use crate::bridge_table::BridgeLine;
- #[cfg(all(test, feature = "bridgeauth"))]
- use rand::RngCore;
- #[cfg(all(test, feature = "bridgeauth"))]
- #[allow(unused_imports)]
- use base64::{engine::general_purpose, Engine as _};
- #[derive(Default)]
- #[cfg(all(test, feature = "bridgeauth"))]
- pub struct TestHarness {
- pub bdb: BridgeDb,
- pub ba: BridgeAuth,
- }
- #[cfg(all(test, feature = "bridgeauth"))]
- impl TestHarness {
- pub fn new() -> Self {
- TestHarness::new_buckets(5, 5)
- }
- pub fn new_buckets(num_buckets: u16, hot_spare: u16) -> Self {
- // Create a BridegDb
- let mut bdb = BridgeDb::new();
- let mut rng = rand::thread_rng();
- // Create a BridgeAuth
- let mut ba = BridgeAuth::new(bdb.pubkey.clone(), &mut rng);
- // Make 3 x num_buckets open invitation bridges, in sets of 3
- for _ in 0..num_buckets {
- let bucket = [random(), random(), random()];
- let _ = ba.add_openinv_bridges(bucket, &mut bdb);
- }
- // Add hot_spare more hot spare buckets
- for _ in 0..hot_spare {
- let bucket = [random(), random(), random()];
- let _ = ba.add_spare_bucket(bucket, &mut bdb);
- }
- // Create the encrypted bridge table
- ba.enc_bridge_table();
- Self { bdb, ba }
- }
- // pub fn advance_days(&mut self, days: u16) {
- // self.ba.advance_days(days);
- // }
- /// Verify the two MACs on a Lox credential
- pub fn verify_lox(&self, cred: &lox_creds::Lox) {
- assert!(
- !bool::from(cred.MAC.P.is_identity()),
- "Lox cred MAC P should not be identity"
- );
- let Q = (self.ba.lox_priv.x0
- + self.ba.lox_priv.xr
- + cred.id.unwrap() * self.ba.lox_priv.x[0]
- + cred.bucket.unwrap() * self.ba.lox_priv.x[1]
- + cred.trust_level.unwrap() * self.ba.lox_priv.x[2]
- + cred.level_since.unwrap() * self.ba.lox_priv.x[3]
- + cred.invites_remaining.unwrap() * self.ba.lox_priv.x[4]
- + cred.blockages.unwrap() * self.ba.lox_priv.x[5])
- * cred.MAC.P;
- assert_eq!(Q, cred.MAC.Q, "Lox MAC Q should match computation");
- }
- /// Verify the MAC on a Migration credential
- pub fn verify_migration(&self, cred: &lox_creds::Migration) {
- assert!(
- !bool::from(cred.MAC.P.is_identity()),
- "Migration cred MAC P should not be identity"
- );
- let Q = (self.ba.migration_priv.x0
- + self.ba.migration_priv.xr
- + cred.lox_id.unwrap() * self.ba.migration_priv.x[0]
- + cred.from_bucket.unwrap() * self.ba.migration_priv.x[1]
- + cred.to_bucket.unwrap() * self.ba.migration_priv.x[2])
- * cred.MAC.P;
- assert_eq!(Q, cred.MAC.Q, "Migration MAC Q should match computation");
- }
- /// Verify the MAC on a Bucket Reachability credential
- pub fn verify_reachability(&self, cred: &lox_creds::BucketReachability) {
- assert!(
- !bool::from(cred.MAC.P.is_identity()),
- "Reachability cred MAC P should not be identity"
- );
- let Q = (self.ba.reachability_priv.x0
- + self.ba.reachability_priv.xr
- + cred.date.unwrap() * self.ba.reachability_priv.x[0]
- + cred.bucket.unwrap() * self.ba.reachability_priv.x[1])
- * cred.MAC.P;
- assert_eq!(Q, cred.MAC.Q, "Reachability MAC Q should match computation");
- }
- /// Verify the MAC on a Invitation credential
- pub fn verify_invitation(&mut self, cred: &lox_creds::Invitation) {
- assert!(
- !bool::from(cred.MAC.P.is_identity()),
- "Invitation MAC P should not be identity"
- );
- let Q = (self.ba.invitation_priv.x0
- + self.ba.invitation_priv.xr
- + cred.inv_id.unwrap() * self.ba.invitation_priv.x[0]
- + cred.date.unwrap() * self.ba.invitation_priv.x[1]
- + cred.bucket.unwrap() * self.ba.invitation_priv.x[2]
- + cred.blockages.unwrap() * self.ba.invitation_priv.x[3])
- * cred.MAC.P;
- assert_eq!(Q, cred.MAC.Q, "Invitation MAC Q should match");
- }
- }
- /// Create a random BridgeLine for testing
- #[cfg(all(test, feature = "bridgeauth"))]
- pub fn random() -> BridgeLine {
- let mut rng = rand::rngs::OsRng;
- let mut res: BridgeLine = Default::default();
- // Pick a random 4-byte address
- let mut addr: [u8; 4] = [0; 4];
- rng.fill_bytes(&mut addr);
- // If the leading byte is 224 or more, that's not a valid IPv4
- // address. Choose an IPv6 address instead (but don't worry too
- // much about it being well formed).
- if addr[0] >= 224 {
- rng.fill_bytes(&mut res.addr);
- } else {
- // Store an IPv4 address as a v4-mapped IPv6 address
- res.addr[10] = 255;
- res.addr[11] = 255;
- res.addr[12..16].copy_from_slice(&addr);
- };
- let ports: [u16; 4] = [443, 4433, 8080, 43079];
- let portidx = (rng.next_u32() % 4) as usize;
- res.port = ports[portidx];
- res.uid_fingerprint = rng.next_u64();
- let mut cert: [u8; 52] = [0; 52];
- rng.fill_bytes(&mut cert);
- let infostr: String = format!(
- "obfs4 cert={}, iat-mode=0",
- general_purpose::STANDARD_NO_PAD.encode(cert)
- );
- res.info[..infostr.len()].copy_from_slice(infostr.as_bytes());
- res
- }
|