implement zeroizing of secrets after use

This commit is contained in:
multi prise
2025-08-07 15:07:13 +02:00
committed by Damir Jelić
parent 2a073043fd
commit 24d02a72e3
4 changed files with 13 additions and 7 deletions

1
Cargo.lock generated
View File

@@ -3519,6 +3519,7 @@ dependencies = [
"tokio",
"tracing",
"vodozemac",
"zeroize",
]
[[package]]

View File

@@ -42,6 +42,7 @@ thiserror.workspace = true
tokio = { workspace = true, features = ["fs"] }
tracing.workspace = true
vodozemac.workspace = true
zeroize.workspace = true
[dev-dependencies]
assert_matches.workspace = true

View File

@@ -32,6 +32,7 @@ use std::{
};
use deadpool_sqlite::PoolConfig;
use zeroize::Zeroize;
#[cfg(feature = "crypto-store")]
pub use self::crypto_store::SqliteCryptoStore;
@@ -46,9 +47,11 @@ pub use self::state_store::{SqliteStateStore, DATABASE_NAME as STATE_STORE_DATAB
#[cfg(test)]
matrix_sdk_test_utils::init_tracing_for_tests!();
#[derive(Clone, Debug, Eq, PartialEq)]
#[derive(Clone, Debug, Eq, PartialEq, Zeroize)]
pub enum Secret {
#[zeroize]
Key([u8; 32]),
#[zeroize]
PassPhrase(String),
}

View File

@@ -28,6 +28,7 @@ use ruma::{serde::Raw, time::SystemTime, OwnedEventId, OwnedRoomId};
use rusqlite::{limits::Limit, OptionalExtension, Params, Row, Statement, Transaction};
use serde::{de::DeserializeOwned, Serialize};
use tracing::{error, warn};
use zeroize::Zeroize;
use crate::{
error::{Error, Result},
@@ -457,31 +458,31 @@ pub(crate) trait SqliteKeyValueStoreAsyncConnExt: SqliteAsyncConnExt {
/// Get the [`StoreCipher`] of the database or create it.
async fn get_or_create_store_cipher(
&self,
secret: Secret,
mut secret: Secret,
) -> Result<StoreCipher, OpenStoreError> {
let encrypted_cipher = self.get_kv("cipher").await.map_err(OpenStoreError::LoadCipher)?;
let cipher = if let Some(encrypted) = encrypted_cipher {
match secret {
Secret::PassPhrase(passphrase) => StoreCipher::import(passphrase, &encrypted)?,
Secret::Key(key) => StoreCipher::import_with_key(key, &encrypted)?,
Secret::PassPhrase(ref passphrase) => StoreCipher::import(&passphrase, &encrypted)?,
Secret::Key(key) => StoreCipher::import_with_key(&key, &encrypted)?,
}
} else {
let cipher = StoreCipher::new()?;
let export = match secret {
Secret::PassPhrase(passphrase) => {
Secret::PassPhrase(ref passphrase) => {
if cfg!(not(test)) {
cipher.export(passphrase)
} else {
cipher._insecure_export_fast_for_testing(passphrase)
}
}
Secret::Key(key) => cipher.export_with_key(key),
Secret::Key(key) => cipher.export_with_key(&key),
};
self.set_kv("cipher", export?).await.map_err(OpenStoreError::SaveCipher)?;
cipher
};
secret.zeroize();
Ok(cipher)
}
}