tests.rs 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  1. /*! Unit tests that require access to the testing-only function
  2. BridgeLine::random() or private fields */
  3. use super::bridge_table::BridgeLine;
  4. use super::proto::*;
  5. use super::*;
  6. use std::time::{Duration, Instant};
  7. struct PerfStat {
  8. // Report performance metrics for each test
  9. req_len: usize,
  10. resp_len: usize,
  11. req_t: Duration,
  12. resp_t: Duration,
  13. resp_handle_t: Duration,
  14. }
  15. struct TestHarness {
  16. bdb: BridgeDb,
  17. pub ba: BridgeAuth,
  18. }
  19. impl TestHarness {
  20. fn new() -> Self {
  21. // Create a BridegDb
  22. let mut bdb = BridgeDb::new();
  23. // Create a BridgeAuth
  24. let mut ba = BridgeAuth::new(bdb.pubkey);
  25. // Make 15 open invitation bridges, in 5 sets of 3
  26. for _ in 0..5 {
  27. let bucket = [
  28. BridgeLine::random(),
  29. BridgeLine::random(),
  30. BridgeLine::random(),
  31. ];
  32. ba.add_openinv_bridges(bucket, &mut bdb);
  33. }
  34. // Add 5 more hot spare buckets
  35. for _ in 0..5 {
  36. let bucket = [
  37. BridgeLine::random(),
  38. BridgeLine::random(),
  39. BridgeLine::random(),
  40. ];
  41. ba.add_spare_bucket(bucket);
  42. }
  43. // Create the encrypted bridge table
  44. ba.enc_bridge_table();
  45. Self { bdb, ba }
  46. }
  47. fn advance_days(&mut self, days: u16) {
  48. self.ba.advance_days(days);
  49. }
  50. fn open_invite(&mut self) -> (PerfStat, (cred::Lox, bridge_table::BridgeLine)) {
  51. // Issue an open invitation
  52. let inv = self.bdb.invite();
  53. let req_start = Instant::now();
  54. // Use it to get a Lox credential
  55. let (req, state) = open_invite::request(&inv);
  56. let encoded: Vec<u8> = bincode::serialize(&req).unwrap();
  57. let req_t = req_start.elapsed();
  58. let req_len = encoded.len();
  59. let resp_start = Instant::now();
  60. let decoded: open_invite::Request = bincode::deserialize(&encoded[..]).unwrap();
  61. let resp = self.ba.handle_open_invite(decoded).unwrap();
  62. let encoded_resp: Vec<u8> = bincode::serialize(&resp).unwrap();
  63. let resp_t = resp_start.elapsed();
  64. let resp_len = encoded_resp.len();
  65. let resp_handle_start = Instant::now();
  66. let decode_resp: open_invite::Response = bincode::deserialize(&encoded_resp[..]).unwrap();
  67. let (cred, bridgeline) =
  68. open_invite::handle_response(state, decode_resp, &self.ba.lox_pub).unwrap();
  69. let resp_handle_t = resp_handle_start.elapsed();
  70. return (
  71. PerfStat {
  72. req_len,
  73. resp_len,
  74. req_t,
  75. resp_t,
  76. resp_handle_t,
  77. },
  78. (cred, bridgeline),
  79. );
  80. }
  81. fn trust_promotion(&mut self, cred: &cred::Lox) -> cred::Migration {
  82. let (promreq, promstate) =
  83. trust_promotion::request(&cred, &self.ba.lox_pub, self.ba.today()).unwrap();
  84. let promresp = self.ba.handle_trust_promotion(promreq).unwrap();
  85. trust_promotion::handle_response(promstate, promresp).unwrap()
  86. }
  87. fn level0_migration(&mut self, loxcred: &cred::Lox, migcred: &cred::Migration) -> cred::Lox {
  88. let (migreq, migstate) =
  89. migration::request(loxcred, migcred, &self.ba.lox_pub, &self.ba.migration_pub).unwrap();
  90. let migresp = self.ba.handle_migration(migreq).unwrap();
  91. migration::handle_response(migstate, migresp, &self.ba.lox_pub).unwrap()
  92. }
  93. fn level_up(&mut self, cred: &cred::Lox) -> cred::Lox {
  94. // Read the bucket in the credential to get today's Bucket
  95. // Reachability credential
  96. let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap();
  97. let encbuckets = self.ba.enc_bridge_table();
  98. let bucket =
  99. bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap();
  100. let reachcred = bucket.1.unwrap();
  101. // Use the Bucket Reachability credential to advance to the next
  102. // level
  103. let (req, state) = level_up::request(
  104. &cred,
  105. &reachcred,
  106. &self.ba.lox_pub,
  107. &self.ba.reachability_pub,
  108. self.ba.today(),
  109. )
  110. .unwrap();
  111. let resp = self.ba.handle_level_up(req).unwrap();
  112. level_up::handle_response(state, resp, &self.ba.lox_pub).unwrap()
  113. }
  114. fn issue_invite(&mut self, cred: &cred::Lox) -> (cred::Lox, cred::Invitation) {
  115. // Read the bucket in the credential to get today's Bucket
  116. // Reachability credential
  117. let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap();
  118. let encbuckets = self.ba.enc_bridge_table();
  119. let bucket =
  120. bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap();
  121. let reachcred = bucket.1.unwrap();
  122. let (req, state) = issue_invite::request(
  123. &cred,
  124. &reachcred,
  125. &self.ba.lox_pub,
  126. &self.ba.reachability_pub,
  127. self.ba.today(),
  128. )
  129. .unwrap();
  130. let resp = self.ba.handle_issue_invite(req).unwrap();
  131. issue_invite::handle_response(state, resp, &self.ba.lox_pub, &self.ba.invitation_pub)
  132. .unwrap()
  133. }
  134. fn redeem_invite(&mut self, inv: &cred::Invitation) -> cred::Lox {
  135. let (req, state) =
  136. redeem_invite::request(&inv, &self.ba.invitation_pub, self.ba.today()).unwrap();
  137. let resp = self.ba.handle_redeem_invite(req).unwrap();
  138. redeem_invite::handle_response(state, resp, &self.ba.lox_pub).unwrap()
  139. }
  140. fn check_blockage(&mut self, cred: &cred::Lox) -> cred::Migration {
  141. let (req, state) = check_blockage::request(&cred, &self.ba.lox_pub).unwrap();
  142. let resp = self.ba.handle_check_blockage(req).unwrap();
  143. check_blockage::handle_response(state, resp).unwrap()
  144. }
  145. fn blockage_migration(&mut self, cred: &cred::Lox, mig: &cred::Migration) -> cred::Lox {
  146. let (req, state) =
  147. blockage_migration::request(&cred, &mig, &self.ba.lox_pub, &self.ba.migration_pub)
  148. .unwrap();
  149. let resp = self.ba.handle_blockage_migration(req).unwrap();
  150. blockage_migration::handle_response(state, resp, &self.ba.lox_pub).unwrap()
  151. }
  152. }
  153. #[test]
  154. fn test_open_invite() {
  155. let mut th = TestHarness::new();
  156. // Join an untrusted user
  157. let (perf_stat, (cred, bridgeline)) = th.open_invite();
  158. // Check that we can use the credential to read a bucket
  159. let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap();
  160. let encbuckets = th.ba.enc_bridge_table();
  161. let bucket =
  162. bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap();
  163. println!("Request size = {:?}", perf_stat.req_len);
  164. println!("Request time = {:?}", perf_stat.req_t);
  165. println!("Response size = {:?}", perf_stat.resp_len);
  166. println!("Response time = {:?}", perf_stat.resp_t);
  167. println!("Response handle time = {:?}", perf_stat.resp_handle_t);
  168. println!("cred = {:?}", cred);
  169. println!("bucket = {:?}", bucket);
  170. println!("bridgeline = {:?}", bridgeline);
  171. assert!(bucket.1.is_none());
  172. assert!(th.ba.verify_lox(&cred));
  173. assert!(bridgeline == bucket.0[0]);
  174. }
  175. #[test]
  176. fn test_trust_promotion() {
  177. let mut th = TestHarness::new();
  178. let cred = th.open_invite().1 .0;
  179. assert!(th.ba.verify_lox(&cred));
  180. // Time passes
  181. th.advance_days(47);
  182. let migcred = th.trust_promotion(&cred);
  183. assert!(th.ba.verify_migration(&migcred));
  184. // Check that we can use the to_bucket in the Migration credenital
  185. // to read a bucket
  186. let (id, key) = bridge_table::from_scalar(migcred.to_bucket).unwrap();
  187. let encbuckets = th.ba.enc_bridge_table();
  188. let bucket =
  189. bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap();
  190. println!("bucket = {:?}", bucket);
  191. assert!(th.ba.verify_reachability(&bucket.1.unwrap()));
  192. }
  193. #[test]
  194. fn test_level0_migration() {
  195. let mut th = TestHarness::new();
  196. let cred = th.open_invite().1 .0;
  197. assert!(th.ba.verify_lox(&cred));
  198. // Time passes
  199. th.advance_days(47);
  200. let migcred = th.trust_promotion(&cred);
  201. assert!(th.ba.verify_migration(&migcred));
  202. let newloxcred = th.level0_migration(&cred, &migcred);
  203. assert!(th.ba.verify_lox(&newloxcred));
  204. println!("newloxcred = {:?}", newloxcred);
  205. // Check that we can use the credenital to read a bucket
  206. let (id, key) = bridge_table::from_scalar(newloxcred.bucket).unwrap();
  207. let encbuckets = th.ba.enc_bridge_table();
  208. let bucket =
  209. bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap();
  210. println!("bucket = {:?}", bucket);
  211. assert!(th.ba.verify_reachability(&bucket.1.unwrap()));
  212. }
  213. #[test]
  214. fn test_level_up() {
  215. let mut th = TestHarness::new();
  216. // Join an untrusted user
  217. let cred = th.open_invite().1 .0;
  218. // Time passes
  219. th.advance_days(47);
  220. // Go up to level 1
  221. let migcred = th.trust_promotion(&cred);
  222. let cred1 = th.level0_migration(&cred, &migcred);
  223. assert!(scalar_u32(&cred1.trust_level).unwrap() == 1);
  224. // Time passes
  225. th.advance_days(20);
  226. let cred2 = th.level_up(&cred1);
  227. assert!(scalar_u32(&cred2.trust_level).unwrap() == 2);
  228. println!("cred2 = {:?}", cred2);
  229. assert!(th.ba.verify_lox(&cred2));
  230. // Time passes
  231. th.advance_days(30);
  232. let cred3 = th.level_up(&cred2);
  233. assert!(scalar_u32(&cred3.trust_level).unwrap() == 3);
  234. println!("cred3 = {:?}", cred3);
  235. assert!(th.ba.verify_lox(&cred3));
  236. // Time passes
  237. th.advance_days(60);
  238. let cred4 = th.level_up(&cred3);
  239. assert!(scalar_u32(&cred3.trust_level).unwrap() == 3);
  240. println!("cred4 = {:?}", cred4);
  241. assert!(th.ba.verify_lox(&cred4));
  242. }
  243. #[test]
  244. fn test_issue_invite() {
  245. let mut th = TestHarness::new();
  246. // Join an untrusted user
  247. let cred = th.open_invite().1 .0;
  248. // Time passes
  249. th.advance_days(47);
  250. // Go up to level 1
  251. let migcred = th.trust_promotion(&cred);
  252. let cred1 = th.level0_migration(&cred, &migcred);
  253. assert!(scalar_u32(&cred1.trust_level).unwrap() == 1);
  254. // Time passes
  255. th.advance_days(20);
  256. // Go up to level 2
  257. let cred2 = th.level_up(&cred1);
  258. assert!(scalar_u32(&cred2.trust_level).unwrap() == 2);
  259. println!("cred2 = {:?}", cred2);
  260. assert!(th.ba.verify_lox(&cred2));
  261. // Issue an invitation
  262. let (cred2a, invite) = th.issue_invite(&cred2);
  263. assert!(th.ba.verify_lox(&cred2a));
  264. assert!(th.ba.verify_invitation(&invite));
  265. println!("cred2a = {:?}", cred2a);
  266. println!("invite = {:?}", invite);
  267. }
  268. #[test]
  269. fn test_redeem_invite() {
  270. let mut th = TestHarness::new();
  271. // Join an untrusted user
  272. let cred = th.open_invite().1 .0;
  273. // Time passes
  274. th.advance_days(47);
  275. // Go up to level 1
  276. let migcred = th.trust_promotion(&cred);
  277. let cred1 = th.level0_migration(&cred, &migcred);
  278. assert!(scalar_u32(&cred1.trust_level).unwrap() == 1);
  279. // Time passes
  280. th.advance_days(20);
  281. // Go up to level 2
  282. let cred2 = th.level_up(&cred1);
  283. assert!(scalar_u32(&cred2.trust_level).unwrap() == 2);
  284. println!("cred2 = {:?}", cred2);
  285. assert!(th.ba.verify_lox(&cred2));
  286. // Issue an invitation to Bob
  287. let (cred2a, bob_invite) = th.issue_invite(&cred2);
  288. assert!(th.ba.verify_lox(&cred2a));
  289. assert!(th.ba.verify_invitation(&bob_invite));
  290. println!("cred2a = {:?}", cred2a);
  291. println!("bob_invite = {:?}", bob_invite);
  292. // Time passes
  293. th.advance_days(12);
  294. // Bob joins the system
  295. let bob_cred = th.redeem_invite(&bob_invite);
  296. assert!(th.ba.verify_lox(&bob_cred));
  297. println!("bob_cred = {:?}", bob_cred);
  298. }
  299. #[test]
  300. fn test_mark_unreachable() {
  301. let mut th = TestHarness::new();
  302. println!("spares = {:?}", th.ba.bridge_table.spares);
  303. println!("tmig = {:?}", th.ba.trustup_migration_table.table);
  304. println!("bmig = {:?}", th.ba.blockage_migration_table.table);
  305. println!("openinv = {:?}\n", th.bdb.openinv_buckets);
  306. // Mark a bridge in an untrusted bucket as unreachable
  307. let b6 = th.ba.bridge_table.buckets[6][0];
  308. th.ba.bridge_unreachable(&b6, &mut th.bdb);
  309. println!("spares = {:?}", th.ba.bridge_table.spares);
  310. println!("tmig = {:?}", th.ba.trustup_migration_table.table);
  311. println!("bmig = {:?}", th.ba.blockage_migration_table.table);
  312. println!("openinv = {:?}\n", th.bdb.openinv_buckets);
  313. // Mark another bridge grouped to the same trusted bucket as
  314. // unreachable
  315. let b7 = th.ba.bridge_table.buckets[7][0];
  316. th.ba.bridge_unreachable(&b7, &mut th.bdb);
  317. println!("spares = {:?}", th.ba.bridge_table.spares);
  318. println!("tmig = {:?}", th.ba.trustup_migration_table.table);
  319. println!("bmig = {:?}", th.ba.blockage_migration_table.table);
  320. println!("openinv = {:?}\n", th.bdb.openinv_buckets);
  321. // That will have introduced a blockage migration. Get the target
  322. let target: u32 = *th
  323. .ba
  324. .blockage_migration_table
  325. .table
  326. .iter()
  327. .next()
  328. .unwrap()
  329. .1;
  330. // Block two of the bridges in that target bucket
  331. let bt1 = th.ba.bridge_table.buckets[target as usize][1];
  332. let bt2 = th.ba.bridge_table.buckets[target as usize][2];
  333. th.ba.bridge_unreachable(&bt1, &mut th.bdb);
  334. th.ba.bridge_unreachable(&bt2, &mut th.bdb);
  335. println!("spares = {:?}", th.ba.bridge_table.spares);
  336. println!("tmig = {:?}", th.ba.trustup_migration_table.table);
  337. println!("bmig = {:?}", th.ba.blockage_migration_table.table);
  338. println!("openinv = {:?}\n", th.bdb.openinv_buckets);
  339. }
  340. #[test]
  341. fn test_blockage_migration() {
  342. let mut th = TestHarness::new();
  343. // Join an untrusted user
  344. let cred = th.open_invite().1 .0;
  345. // Time passes
  346. th.advance_days(47);
  347. // Go up to level 1
  348. let migcred = th.trust_promotion(&cred);
  349. let cred1 = th.level0_migration(&cred, &migcred);
  350. assert!(scalar_u32(&cred1.trust_level).unwrap() == 1);
  351. // Time passes
  352. th.advance_days(20);
  353. // Go up to level 2
  354. let cred2 = th.level_up(&cred1);
  355. assert!(scalar_u32(&cred2.trust_level).unwrap() == 2);
  356. println!("cred2 = {:?}", cred2);
  357. assert!(th.ba.verify_lox(&cred2));
  358. // Time passes
  359. th.advance_days(29);
  360. // Go up to level 3
  361. let cred3 = th.level_up(&cred2);
  362. assert!(scalar_u32(&cred3.trust_level).unwrap() == 3);
  363. println!("cred3 = {:?}", cred3);
  364. assert!(th.ba.verify_lox(&cred3));
  365. // Get our bridges
  366. let (id, key) = bridge_table::from_scalar(cred3.bucket).unwrap();
  367. let encbuckets = th.ba.enc_bridge_table();
  368. let bucket =
  369. bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets[id as usize]).unwrap();
  370. // We should have a Bridge Reachability credential
  371. assert!(bucket.1.is_some());
  372. // Oh, no! Two of our bridges are blocked!
  373. th.ba.bridge_unreachable(&bucket.0[0], &mut th.bdb);
  374. th.ba.bridge_unreachable(&bucket.0[2], &mut th.bdb);
  375. println!("spares = {:?}", th.ba.bridge_table.spares);
  376. println!("tmig = {:?}", th.ba.trustup_migration_table.table);
  377. println!("bmig = {:?}", th.ba.blockage_migration_table.table);
  378. println!("openinv = {:?}\n", th.bdb.openinv_buckets);
  379. // Time passes
  380. th.advance_days(1);
  381. let encbuckets2 = th.ba.enc_bridge_table();
  382. let bucket2 =
  383. bridge_table::BridgeTable::decrypt_bucket(id, &key, &encbuckets2[id as usize]).unwrap();
  384. // We should no longer have a Bridge Reachability credential
  385. assert!(bucket2.1.is_none());
  386. // See about getting a Migration credential for the blockage
  387. let migration = th.check_blockage(&cred3);
  388. println!("migration = {:?}", migration);
  389. // Migrate
  390. let cred4 = th.blockage_migration(&cred3, &migration);
  391. println!("cred4 = {:?}", cred4);
  392. assert!(th.ba.verify_lox(&cred4));
  393. }