tests.rs 15 KB

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