Check that we can use the credential to read a bucket

This commit is contained in:
Ian Goldberg 2021-04-29 11:28:05 -04:00
parent 77b92036c7
commit 450c62bfc7
3 changed files with 33 additions and 6 deletions

View File

@ -17,6 +17,7 @@ hex_fmt = "0.3"
aes-gcm = "0.8"
base64 = "0.13"
time = "0.2"
subtle = "2.4"
[features]
default = ["u64_backend"]

View File

@ -13,6 +13,7 @@ use aes_gcm::Aes128Gcm;
use curve25519_dalek::scalar::Scalar;
use rand::RngCore;
use std::convert::TryInto;
use subtle::ConstantTimeEq;
/// Each bridge information line is serialized into this many bytes
pub const BRIDGE_BYTES: usize = 220;
@ -194,6 +195,16 @@ impl BridgeTable {
plaintext.as_slice().try_into().unwrap(),
))
}
/// Decrypt an individual encrypted bucket, given its id and key
pub fn decrypt_bucket_id(
&self,
id: u32,
key: &[u8; 16],
) -> Result<[BridgeLine; MAX_BRIDGES_PER_BUCKET], aead::Error> {
let encbucket = self.encbuckets[id as usize];
BridgeTable::decrypt_bucket(key, &encbucket)
}
}
// Unit tests that require access to the testing-only function
@ -225,18 +236,15 @@ mod tests {
btable.encrypt_table();
// Try to decrypt a 1-bridge bucket
let key7 = btable.keys[7];
let encbucket7 = btable.encbuckets[7];
let bucket7 = BridgeTable::decrypt_bucket(&key7, &encbucket7)?;
let bucket7 = btable.decrypt_bucket_id(7, &key7)?;
println!("bucket 7 = {:?}", bucket7);
// Try to decrypt a 3-bridge bucket
let key24 = btable.keys[24];
let encbucket24 = btable.encbuckets[24];
let bucket24 = BridgeTable::decrypt_bucket(&key24, &encbucket24)?;
let bucket24 = btable.decrypt_bucket_id(24, &key24)?;
println!("bucket 24 = {:?}", bucket24);
// Try to decrypt a bucket with the wrong key
let key12 = btable.keys[12];
let encbucket15 = btable.encbuckets[15];
let res = BridgeTable::decrypt_bucket(&key12, &encbucket15).unwrap_err();
let res = btable.decrypt_bucket_id(15, &key12).unwrap_err();
println!("bucket key mismatch = {:?}", res);
Ok(())
}
@ -252,3 +260,16 @@ pub fn to_scalar(id: u32, key: [u8; 16]) -> Scalar {
// This cannot fail, since we're only using the low 20 bytes of b
Scalar::from_canonical_bytes(b).unwrap()
}
/// Convert a Scalar attribute to an id and key if possible
pub fn from_scalar(s: Scalar) -> Result<(u32, [u8; 16]), aead::Error> {
// Check that the top 12 bytes of the Scalar are 0
let sbytes = s.as_bytes();
if sbytes[20..].ct_eq(&[0u8; 12]).unwrap_u8() == 0 {
return Err(aead::Error);
}
let id = u32::from_le_bytes(sbytes[16..20].try_into().unwrap());
let mut key: [u8; 16] = [0; 16];
key.copy_from_slice(&sbytes[..16]);
Ok((id, key))
}

View File

@ -277,6 +277,11 @@ mod tests {
let resp = ba.handle_open_invite(req).unwrap();
let cred =
open_invite::handle_response(state, resp, &ba.lox_pub, &ba.migration_pub).unwrap();
// Check that we can use the credential to read a bucket
let (id, key) = bridge_table::from_scalar(cred.bucket).unwrap();
let bucket = ba.bridge_table.decrypt_bucket_id(id, &key).unwrap();
println!("cred = {:?}", cred);
println!("bucket = {:?}", bucket);
}
}