diff --git a/src/lib.rs b/src/lib.rs index a934e38..f643e1a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -8,6 +8,7 @@ use lox_library::{ scalar_u32, IssuerPubKey, OPENINV_LENGTH, }; use lox_utils::{EncBridgeTable, Invite}; +use serde_json::error::Error; use std::collections::HashMap; pub mod networking; @@ -44,8 +45,15 @@ pub async fn eligible_for_trust_promotion( Some(v) => v, None => return false, }; + let date = match get_today(net).await { + Ok(v) => v, + Err(e) => { + eprintln!("Failed to get date, error: {}", e); + return false; + } + }; scalar_u32(&cred.trust_level).unwrap() == 0 - && level_since + trust_promotion::UNTRUSTED_INTERVAL <= get_today(net).await + && level_since + trust_promotion::UNTRUSTED_INTERVAL <= date } // Helper function to check if credential is eligible for @@ -55,56 +63,68 @@ pub async fn eligible_for_level_up(net: &dyn Networking, cred: &lox_library::cre Some(v) => v, None => return false, }; + let date = match get_today(net).await { + Ok(v) => v, + Err(e) => { + eprintln!("Failed to get date, error: {}", e); + return false; + } + }; let trust_level = scalar_u32(&cred.trust_level).unwrap(); let blockages = scalar_u32(&cred.blockages).unwrap(); trust_level > 0 && blockages <= MAX_BLOCKAGES[trust_level as usize] - && level_since + LEVEL_INTERVAL[trust_level as usize] <= get_today(net).await + && level_since + LEVEL_INTERVAL[trust_level as usize] <= date } // Get current date from Lox Auth -pub async fn get_today(net: &dyn Networking) -> u32 { +pub async fn get_today(net: &dyn Networking) -> Result { let resp = net.request("/today".to_string(), [].to_vec()).await; - let today: u32 = serde_json::from_slice(&resp).unwrap(); - today + let today: u32 = serde_json::from_slice(&resp)?; + Ok(today) } // Download Lox Auth pubkeys -pub async fn get_lox_auth_keys(net: &dyn Networking) -> Vec { +pub async fn get_lox_auth_keys(net: &dyn Networking) -> Result, Error> { let resp = net.request("/pubkeys".to_string(), [].to_vec()).await; - let lox_auth_pubkeys: Vec = serde_json::from_slice(&resp).unwrap(); - lox_auth_pubkeys + let lox_auth_pubkeys: Vec = serde_json::from_slice(&resp)?; + Ok(lox_auth_pubkeys) } // Get encrypted bridge table -pub async fn get_reachability_credential(net: &dyn Networking) -> HashMap { +pub async fn get_reachability_credential( + net: &dyn Networking, +) -> Result, Error> { let resp = net.request("/reachability".to_string(), [].to_vec()).await; - let reachability_cred: EncBridgeTable = serde_json::from_slice(&resp).unwrap(); - reachability_cred.etable + let reachability_cred: EncBridgeTable = serde_json::from_slice(&resp)?; + Ok(reachability_cred.etable) } // Get encrypted bridge table from BridgeDB and decrypt our entry pub async fn get_bucket( net: &dyn Networking, lox_cred: &lox_library::cred::Lox, -) -> ( - [BridgeLine; MAX_BRIDGES_PER_BUCKET], - Option, -) { - let encbuckets = get_reachability_credential(net).await; +) -> Result< + ( + [BridgeLine; MAX_BRIDGES_PER_BUCKET], + Option, + ), + Error, +> { + let encbuckets = get_reachability_credential(net).await?; let (id, key) = from_scalar(lox_cred.bucket).unwrap(); let encbucket = match encbuckets.get(&id) { Some(encbucket) => encbucket, None => panic!("Provided ID not found"), }; - BridgeTable::decrypt_bucket(id, &key, &encbucket).unwrap() + Ok(BridgeTable::decrypt_bucket(id, &key, &encbucket).unwrap()) } // Get an open invitation -pub async fn get_open_invitation(net: &dyn Networking) -> [u8; OPENINV_LENGTH] { +pub async fn get_open_invitation(net: &dyn Networking) -> Result<[u8; OPENINV_LENGTH], Error> { let resp = net.request("/invite".to_string(), [].to_vec()).await; - let open_invite: [u8; OPENINV_LENGTH] = serde_json::from_slice::(&resp).unwrap().invite; - open_invite + let open_invite: [u8; OPENINV_LENGTH] = serde_json::from_slice::(&resp)?.invite; + Ok(open_invite) } // Get a Lox Credential from an open invitation @@ -112,13 +132,13 @@ pub async fn get_lox_credential( net: &dyn Networking, open_invite: &[u8; OPENINV_LENGTH], lox_pub: &IssuerPubKey, -) -> (lox_library::cred::Lox, BridgeLine) { +) -> Result<(lox_library::cred::Lox, BridgeLine), Error> { let (req, state) = open_invite::request(&open_invite); - let encoded_req: Vec = serde_json::to_vec(&req).unwrap(); + let encoded_req: Vec = serde_json::to_vec(&req)?; let encoded_resp = net.request("/openreq".to_string(), encoded_req).await; - let decoded_resp: open_invite::Response = serde_json::from_slice(&encoded_resp).unwrap(); + let decoded_resp: open_invite::Response = serde_json::from_slice(&encoded_resp)?; let (cred, bridgeline) = open_invite::handle_response(state, decoded_resp, &lox_pub).unwrap(); - (cred, bridgeline) + Ok((cred, bridgeline)) } // Get a migration credential to migrate to higher trust @@ -126,13 +146,14 @@ pub async fn trust_promotion( net: &dyn Networking, lox_cred: &lox_library::cred::Lox, lox_pub: &IssuerPubKey, -) -> lox_library::cred::Migration { - let (req, state) = trust_promotion::request(&lox_cred, &lox_pub, get_today(net).await).unwrap(); - let encoded_req: Vec = serde_json::to_vec(&req).unwrap(); +) -> Result { + let (req, state) = + trust_promotion::request(&lox_cred, &lox_pub, get_today(net).await?).unwrap(); + let encoded_req: Vec = serde_json::to_vec(&req)?; let encoded_resp = net.request("/trustpromo".to_string(), encoded_req).await; - let decoded_resp: trust_promotion::Response = serde_json::from_slice(&encoded_resp).unwrap(); + let decoded_resp: trust_promotion::Response = serde_json::from_slice(&encoded_resp)?; let migration_cred = trust_promotion::handle_response(state, decoded_resp).unwrap(); - migration_cred + Ok(migration_cred) } // Promote from untrusted (trust level 0) to trusted (trust level 1) @@ -142,14 +163,14 @@ pub async fn trust_migration( migration_cred: &lox_library::cred::Migration, lox_pub: &IssuerPubKey, migration_pub: &IssuerPubKey, -) -> lox_library::cred::Lox { +) -> Result { let (req, state) = migration::request(lox_cred, migration_cred, lox_pub, migration_pub).unwrap(); - let encoded_req: Vec = serde_json::to_vec(&req).unwrap(); + let encoded_req: Vec = serde_json::to_vec(&req)?; let encoded_resp = net.request("/trustmig".to_string(), encoded_req).await; - let decoded_resp: migration::Response = serde_json::from_slice(&encoded_resp).unwrap(); + let decoded_resp: migration::Response = serde_json::from_slice(&encoded_resp)?; let cred = migration::handle_response(state, decoded_resp, lox_pub).unwrap(); - cred + Ok(cred) } // Increase trust from at least level 1 to higher levels @@ -159,20 +180,20 @@ pub async fn level_up( reachcred: &cred::BucketReachability, lox_pub: &IssuerPubKey, reachability_pub: &IssuerPubKey, -) -> lox_library::cred::Lox { +) -> Result { let (req, state) = level_up::request( lox_cred, &reachcred, lox_pub, reachability_pub, - get_today(net).await, + get_today(net).await?, ) .unwrap(); - let encoded_req: Vec = serde_json::to_vec(&req).unwrap(); + let encoded_req: Vec = serde_json::to_vec(&req)?; let encoded_resp = net.request("/levelup".to_string(), encoded_req).await; - let decoded_resp: level_up::Response = serde_json::from_slice(&encoded_resp).unwrap(); + let decoded_resp: level_up::Response = serde_json::from_slice(&encoded_resp)?; let cred = level_up::handle_response(state, decoded_resp, lox_pub).unwrap(); - cred + Ok(cred) } // Request an Invitation credential to give to a friend @@ -183,7 +204,7 @@ pub async fn issue_invite( lox_pub: &IssuerPubKey, reachability_pub: &IssuerPubKey, invitation_pub: &IssuerPubKey, -) -> (lox_library::cred::Lox, lox_library::cred::Invitation) { +) -> Result<(lox_library::cred::Lox, lox_library::cred::Invitation), Error> { // Read the bucket in the credential to get today's Bucket // Reachability credential @@ -196,15 +217,15 @@ pub async fn issue_invite( &reachcred, lox_pub, reachability_pub, - get_today(net).await, + get_today(net).await?, ) .unwrap(); - let encoded_req: Vec = serde_json::to_vec(&req).unwrap(); + let encoded_req: Vec = serde_json::to_vec(&req)?; let encoded_resp = net.request("/issueinvite".to_string(), encoded_req).await; - let decoded_resp: issue_invite::Response = serde_json::from_slice(&encoded_resp).unwrap(); + let decoded_resp: issue_invite::Response = serde_json::from_slice(&encoded_resp)?; let (cred, invite) = issue_invite::handle_response(state, decoded_resp, lox_pub, invitation_pub).unwrap(); - (cred, invite) + Ok((cred, invite)) } // Redeem an Invitation credential to start at trust level 1 @@ -213,16 +234,16 @@ pub async fn redeem_invite( invite: &lox_library::cred::Invitation, lox_pub: &IssuerPubKey, invitation_pub: &IssuerPubKey, -) -> (lox_library::cred::Lox, [BridgeLine; MAX_BRIDGES_PER_BUCKET]) { +) -> Result<(lox_library::cred::Lox, [BridgeLine; MAX_BRIDGES_PER_BUCKET]), Error> { let (req, state) = - redeem_invite::request(invite, invitation_pub, get_today(net).await).unwrap(); - let encoded_req: Vec = serde_json::to_vec(&req).unwrap(); + redeem_invite::request(invite, invitation_pub, get_today(net).await?).unwrap(); + let encoded_req: Vec = serde_json::to_vec(&req)?; let encoded_resp = net.request("/redeem".to_string(), encoded_req).await; - let decoded_resp: redeem_invite::Response = serde_json::from_slice(&encoded_resp).unwrap(); + let decoded_resp: redeem_invite::Response = serde_json::from_slice(&encoded_resp)?; let cred = redeem_invite::handle_response(state, decoded_resp, lox_pub).unwrap(); - let bucket = get_bucket(net, &cred).await.0; - (cred, bucket) + let bucket = get_bucket(net, &cred).await?.0; + Ok((cred, bucket)) } // Check for a migration credential to move to a new bucket @@ -230,13 +251,13 @@ pub async fn check_blockage( net: &dyn Networking, lox_cred: &lox_library::cred::Lox, lox_pub: &IssuerPubKey, -) -> lox_library::cred::Migration { +) -> Result { let (req, state) = check_blockage::request(lox_cred, lox_pub).unwrap(); - let encoded_req: Vec = serde_json::to_vec(&req).unwrap(); + let encoded_req: Vec = serde_json::to_vec(&req)?; let encoded_resp = net.request("/checkblockage".to_string(), encoded_req).await; - let decoded_resp: check_blockage::Response = serde_json::from_slice(&encoded_resp).unwrap(); + let decoded_resp: check_blockage::Response = serde_json::from_slice(&encoded_resp)?; let migcred = check_blockage::handle_response(state, decoded_resp).unwrap(); - migcred + Ok(migcred) } // Migrate to a new bucket (must be level >= 3) @@ -246,16 +267,16 @@ pub async fn blockage_migration( migcred: &lox_library::cred::Migration, lox_pub: &IssuerPubKey, migration_pub: &IssuerPubKey, -) -> lox_library::cred::Lox { +) -> Result { let (req, state) = blockage_migration::request(lox_cred, migcred, lox_pub, migration_pub).unwrap(); - let encoded_req: Vec = serde_json::to_vec(&req).unwrap(); + let encoded_req: Vec = serde_json::to_vec(&req)?; let encoded_resp = net .request("/blockagemigration".to_string(), encoded_req) .await; - let decoded_resp: blockage_migration::Response = serde_json::from_slice(&encoded_resp).unwrap(); + let decoded_resp: blockage_migration::Response = serde_json::from_slice(&encoded_resp)?; let cred = blockage_migration::handle_response(state, decoded_resp, lox_pub).unwrap(); - cred + Ok(cred) } #[cfg(test)] diff --git a/src/main.rs b/src/main.rs index 4f8f187..92fefb9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -73,7 +73,7 @@ async fn main() { serde_json::from_reader(lox_auth_pubkeys_infile).unwrap() } else { // download from Lox Auth - let pubkeys = get_lox_auth_keys(&net).await; + let pubkeys = get_lox_auth_keys(&net).await.unwrap(); // save to file for next time save_object(&pubkeys, &lox_auth_pubkeys_filename); pubkeys @@ -90,7 +90,8 @@ async fn main() { get_lox_pub(&lox_auth_pubkeys), get_invitation_pub(&lox_auth_pubkeys), ) - .await; + .await + .unwrap(); // save to files for future use save_object(&cred, &lox_cred_filename); @@ -101,9 +102,10 @@ async fn main() { || !Path::new(bucket_filename).exists() { // get new Lox Credential - let open_invite = get_open_invitation(&net).await; - let (cred, bl) = - get_lox_credential(&net, &open_invite, get_lox_pub(&lox_auth_pubkeys)).await; + let open_invite = get_open_invitation(&net).await.unwrap(); + let (cred, bl) = get_lox_credential(&net, &open_invite, get_lox_pub(&lox_auth_pubkeys)) + .await + .unwrap(); let mut bucket = [BridgeLine::default(); MAX_BRIDGES_PER_BUCKET]; // note: this is a bucket with one real bridgeline and n-1 // default (zeroed out) bridgelines @@ -127,7 +129,9 @@ async fn main() { let (cred, bucket) = if old_level == 0 { if eligible_for_trust_promotion(&net, &lox_cred).await { let migration_cred = - trust_promotion(&net, &lox_cred, get_lox_pub(&lox_auth_pubkeys)).await; + trust_promotion(&net, &lox_cred, get_lox_pub(&lox_auth_pubkeys)) + .await + .unwrap(); let cred = trust_migration( &net, &lox_cred, @@ -135,15 +139,16 @@ async fn main() { get_lox_pub(&lox_auth_pubkeys), get_migration_pub(&lox_auth_pubkeys), ) - .await; - let bucket = get_bucket(&net, &cred).await.0; + .await + .unwrap(); + let bucket = get_bucket(&net, &cred).await.unwrap().0; (cred, bucket) } else { (lox_cred, bucket) } } else { if eligible_for_level_up(&net, &lox_cred).await { - let (bucket, reachcred) = get_bucket(&net, &lox_cred).await; + let (bucket, reachcred) = get_bucket(&net, &lox_cred).await.unwrap(); let cred = level_up( &net, &lox_cred, @@ -151,8 +156,9 @@ async fn main() { get_lox_pub(&lox_auth_pubkeys), get_reachability_pub(&lox_auth_pubkeys), ) - .await; - let bucket = get_bucket(&net, &lox_cred).await.0; + .await + .unwrap(); + let bucket = get_bucket(&net, &lox_cred).await.unwrap().0; (cred, bucket) } else { (lox_cred, bucket) @@ -177,12 +183,13 @@ async fn main() { let (cred, invite) = issue_invite( &net, &lox_cred, - &get_reachability_credential(&net).await, + &get_reachability_credential(&net).await.unwrap(), get_lox_pub(&lox_auth_pubkeys), get_reachability_pub(&lox_auth_pubkeys), get_invitation_pub(&lox_auth_pubkeys), ) - .await; + .await + .unwrap(); // TODO: Make this unique per-run (e.g., add timestamp) save_object(&invite, &invite_filename); save_object(&cred, &lox_cred_filename); diff --git a/src/tests.rs b/src/tests.rs index 38fbf68..ef35b42 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -55,7 +55,7 @@ pub async fn test_level_up( ) .await; assert!(eligible_for_level_up(net, cred).await); - let (bucket, reachcred) = get_bucket(net, cred).await; + let (bucket, reachcred) = get_bucket(net, cred).await.unwrap(); println!("Leveling up from level {} to {}", level, min(4, level + 1)); let new_cred = level_up( net, @@ -64,7 +64,8 @@ pub async fn test_level_up( get_lox_pub(la_pubkeys), get_reachability_pub(la_pubkeys), ) - .await; + .await + .unwrap(); new_cred } @@ -78,16 +79,17 @@ async fn test_credential_operations() { let net_test = HyperNet { hostname: "http://localhost:8005".to_string(), }; - let la_pubkeys = get_lox_auth_keys(&net).await; + let la_pubkeys = get_lox_auth_keys(&net).await.unwrap(); // Get new Lox credential println!("Getting new open-entry Lox credential"); - let open_inv = get_open_invitation(&net).await; - let (mut cred, bridgeline) = - get_lox_credential(&net, &open_inv, get_lox_pub(&la_pubkeys)).await; - let bucket = get_bucket(&net, &cred).await.0; + let open_inv = get_open_invitation(&net).await.unwrap(); + let (mut cred, bridgeline) = get_lox_credential(&net, &open_inv, get_lox_pub(&la_pubkeys)) + .await + .unwrap(); + let bucket = get_bucket(&net, &cred).await.unwrap().0; - //assert_eq!(bucket[0], bridgeline); // For some reason, this sometimes fails. + assert_eq!(bucket[0], bridgeline); // For some reason, this sometimes fails. assert_eq!(bucket[1], BridgeLine::default()); assert_eq!(bucket[2], BridgeLine::default()); @@ -98,7 +100,9 @@ async fn test_credential_operations() { // Advance server time and trust migrate advance_days(&net_test, u16::try_from(UNTRUSTED_INTERVAL).unwrap()).await; assert!(eligible_for_trust_promotion(&net, &cred).await); - let migration_cred = trust_promotion(&net, &cred, get_lox_pub(&la_pubkeys)).await; + let migration_cred = trust_promotion(&net, &cred, get_lox_pub(&la_pubkeys)) + .await + .unwrap(); cred = trust_migration( &net, &cred, @@ -106,11 +110,13 @@ async fn test_credential_operations() { get_lox_pub(&la_pubkeys), get_migration_pub(&la_pubkeys), ) - .await; + .await + .unwrap(); assert_eq!(scalar_u32(&cred.trust_level).unwrap(), 1); // Advance server time and level up for i in 1..LEVEL_INTERVAL.len() { + println!("Leveling up to level {}", min(i, LEVEL_INTERVAL.len() - 1)); assert_eq!( scalar_u32(&cred.trust_level).unwrap(), u32::try_from(i).unwrap() @@ -130,7 +136,7 @@ async fn test_credential_operations() { // Invite as many friends as possible for j in 0..LEVEL_INVITATIONS[i] { println!("Inviting friend {}", j); - let encbuckets = get_reachability_credential(&net).await; + let encbuckets = get_reachability_credential(&net).await.unwrap(); let (new_cred, invite) = issue_invite( &net, &cred, @@ -139,14 +145,16 @@ async fn test_credential_operations() { get_reachability_pub(&la_pubkeys), get_invitation_pub(&la_pubkeys), ) - .await; + .await + .unwrap(); let (friend_cred, friend_bucket) = redeem_invite( &net, &invite, get_lox_pub(&la_pubkeys), get_invitation_pub(&la_pubkeys), ) - .await; + .await + .unwrap(); cred = new_cred; assert_eq!( @@ -181,7 +189,7 @@ async fn test_credential_operations() { // Block 1 bridge println!("Marking one bridge blocked"); - let bridges = get_bucket(&net, &cred).await.0; + let bridges = get_bucket(&net, &cred).await.unwrap().0; let blocked_bridges = bridges_to_block(bridges, 1); let response = net_tp .request( @@ -195,13 +203,13 @@ async fn test_credential_operations() { advance_days(&net_test, 1).await; // Check that we still have a Bucket Reachability credential - let (bucket, reachcred) = get_bucket(&net, &cred).await; + let (bucket, reachcred) = get_bucket(&net, &cred).await.unwrap(); assert!(reachcred.is_some()); println!("Can still obtain bucket reachability credential"); // Block 2 bridges println!("Marking two bridges blocked"); - let bridges = get_bucket(&net, &cred).await.0; + let bridges = get_bucket(&net, &cred).await.unwrap().0; let blocked_bridges = bridges_to_block(bridges, 2); let response = net_tp .request( @@ -215,13 +223,15 @@ async fn test_credential_operations() { advance_days(&net_test, 1).await; // Check that we don't have a Bucket Reachability credential - let (bucket, reachcred) = get_bucket(&net, &cred).await; + let (bucket, reachcred) = get_bucket(&net, &cred).await.unwrap(); assert!(reachcred.is_none()); println!("Cannot obtain bucket reachability credential"); // Migrate to a new bucket println!("Migrating to a new bucket"); - let migration_cred = check_blockage(&net, &cred, get_lox_pub(&la_pubkeys)).await; + let migration_cred = check_blockage(&net, &cred, get_lox_pub(&la_pubkeys)) + .await + .unwrap(); cred = blockage_migration( &net, &cred, @@ -229,11 +239,11 @@ async fn test_credential_operations() { get_lox_pub(&la_pubkeys), get_migration_pub(&la_pubkeys), ) - .await; + .await + .unwrap(); assert_eq!(scalar_u32(&cred.trust_level).unwrap(), 2); assert_eq!(scalar_u32(&cred.blockages).unwrap(), 1); - // TODO: Figure out why this always fails // Level up to level 3 cred = test_level_up(&net, &net_test, &cred, &la_pubkeys).await; @@ -242,7 +252,7 @@ async fn test_credential_operations() { // Another blockage happens println!("Marking three bridges blocked"); - let bridges = get_bucket(&net, &cred).await.0; + let bridges = get_bucket(&net, &cred).await.unwrap().0; let blocked_bridges = bridges_to_block(bridges, 3); let response = net_tp .request( @@ -257,7 +267,9 @@ async fn test_credential_operations() { // Migrate again println!("Migrating to a new bucket"); - let migration_cred = check_blockage(&net, &cred, get_lox_pub(&la_pubkeys)).await; + let migration_cred = check_blockage(&net, &cred, get_lox_pub(&la_pubkeys)) + .await + .unwrap(); cred = blockage_migration( &net, &cred, @@ -265,7 +277,8 @@ async fn test_credential_operations() { get_lox_pub(&la_pubkeys), get_migration_pub(&la_pubkeys), ) - .await; + .await + .unwrap(); assert_eq!(scalar_u32(&cred.trust_level).unwrap(), 1); // Level up to level 2