tests.rs 14 KB

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