Skip to content

Commit

Permalink
portal: Keyring::load() verify secret before returning a Keyring
Browse files Browse the repository at this point in the history
Adds `verify_secret()`.

With this change, calls to `oo7::portal::Keyring::load()`, and
`oo7::portal::Keyring::open()` will fail when used with a
wrong secret/password.

`fixtures/latest.keyring`: version 1 keyring.

Signed-off-by: Dhanuka Warusadura <[email protected]>
  • Loading branch information
warusadura committed Sep 3, 2024
1 parent 97fdd19 commit b6f67ff
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 0 deletions.
Binary file added client/fixtures/latest.keyring
Binary file not shown.
15 changes: 15 additions & 0 deletions client/src/portal/api/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,21 @@ impl Keyring {
)
}

pub(crate) fn verify_secret(&self, secret: &Secret) -> bool {
let key = self.derive_key(secret);

// if this is a new keyring or a keyring with zero items
if self.items.len() == 0 {
return true;
}

// attempting to decrypt the first item
match self.items[0].clone().decrypt(&key) {
Ok(_) => return true,
Err(_) => return false,
}
}

// Reset Keyring content
pub(crate) fn reset(&mut self) {
let salt = rand::thread_rng().gen::<[u8; DEFAULT_SALT_SIZE]>().to_vec();
Expand Down
42 changes: 42 additions & 0 deletions client/src/portal/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,10 @@ impl Keyring {

let keyring = api::Keyring::try_from(content.as_slice())?;

if !keyring.verify_secret(&secret) {
return Err(Error::ChecksumMismatch);
}

(mtime, keyring)
}
};
Expand Down Expand Up @@ -679,6 +683,44 @@ mod tests {
Ok(())
}

#[tokio::test]
async fn load() -> Result<(), Error> {
let temp_dir = tempdir()?;
let keyring_dir = temp_dir.path().join("keyrings");

fs::create_dir_all(&keyring_dir).await?;

let fixture_path = PathBuf::from(env!("CARGO_MANIFEST_DIR"))
.join("fixtures")
.join("latest.keyring");

fs::copy(&fixture_path, &keyring_dir.join("latest.keyring")).await?;

std::env::set_var("XDG_DATA_HOME", &temp_dir.path());

// Keyring::load with the wrong secret
let password = b"wrong";
let secret = Secret::from(password.to_vec());
match Keyring::load(keyring_dir.join("latest.keyring"), secret).await {
Err(err) => {
assert!(matches!(err, Error::ChecksumMismatch));
}
Ok(_) => assert!(false),
};

// Keyring::load with the correct secret
let password = b"test";
let secret = Secret::from(password.to_vec());
match Keyring::load(keyring_dir.join("latest.keyring"), secret).await {
Err(err) => {
assert!(matches!(err, Error::ChecksumMismatch));
}
Ok(_) => assert!(true),
};

Ok(())
}

#[tokio::test]
async fn change_secret() -> Result<(), Error> {
let path = PathBuf::from("../../tests/test_rekeying.keyring");
Expand Down

0 comments on commit b6f67ff

Please sign in to comment.