Преглед на файлове

Check that we can use the credential to read a bucket

Ian Goldberg преди 3 години
родител
ревизия
8d85ca1ada
променени са 3 файла, в които са добавени 33 реда и са изтрити 6 реда
  1. 1 0
      Cargo.toml
  2. 27 6
      src/bridge_table.rs
  3. 5 0
      src/lib.rs

+ 1 - 0
Cargo.toml

@@ -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"]

+ 27 - 6
src/bridge_table.rs

@@ -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))
+}

+ 5 - 0
src/lib.rs

@@ -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);
     }
 }