Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions python/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,9 @@ use chisel::Chisel;
use crate::errors::to_py_err;

/// Map a Python key argument to a `chisel::Key`. `bytes` → `Key::Raw` (any
/// length; the engine validates the length and raises BadKeyLength via
/// to_py_err if it is wrong). `str` → `Key::Passphrase`. Anything else raises
/// non-empty length is accepted; empty key material is refused deep in the
/// engine and surfaces as InvalidEncryptionKeyError via to_py_err). `str` →
/// `Key::Passphrase`. Anything else raises
/// a Python `TypeError`. Key material is wrapped in `Zeroizing` immediately so
/// it is scrubbed when the `Key` is dropped; we never log or repr the value.
///
Expand Down
1 change: 1 addition & 0 deletions python/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
// not match the handle's stored tag)
// FatalError (drop-and-reopen recovery only)
// IoError (ALSO subclasses builtin OSError — see register)
// DecryptionFailedError (encrypted page/superblock failed AEAD auth)
// ChecksumMismatchError
// CorruptSuperblockError
// FileSizeMismatchError
Expand Down
3 changes: 2 additions & 1 deletion src/crypto/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,8 @@ const KEK_INFO: &[u8] = b"chisel-kek-v1";
/// # Errors
/// Returns `CryptoError::Kdf` if the KDF primitive rejects its parameters
/// (e.g. Argon2id with zero memory cost). Returns `CryptoError::BadKeyLength`
/// if `kdf == Hkdf` and the raw key bytes are empty.
/// if the supplied key material is empty (an empty `Raw` key or empty
/// `Passphrase`), regardless of `kdf`.
pub fn derive_kek(
key: &Key,
kdf: KdfId,
Expand Down
3 changes: 2 additions & 1 deletion src/page_io.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
// Two backings, one interface:
// - `Backing::File` — the durable path. Owns a `File` handle for its entire
// lifetime; the advisory flock is tied to that fd and released on drop.
// Two fsyncs per commit; shadow paging guarantees crash consistency.
// Three fsyncs per commit (I28 pre-drain, data pages, superblock); shadow
// paging guarantees crash consistency.
// - `Backing::Memory` — the ephemeral path. Pages live in a flat `Vec<u8>`
// addressed by `page_id * stride`; fsync is a no-op; no flock is taken.
// Used for benchmark parity with SQLite `:memory:` — see the in-memory-mode
Expand Down
8 changes: 5 additions & 3 deletions src/superblock/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -381,7 +381,8 @@ impl Superblock {
/// Serialize an encrypted superblock: bootstrap fields + crypto-header in
/// cleartext; sensitive fields sealed under the DEK. The byte ranges that
/// would hold sensitive data in a plaintext page are left ZERO so nothing
/// leaks (named_roots at 52..308, root/page-id scalars at 16..52, etc.).
/// leaks (named_roots at 52..308, root/page-id scalars at 16..48, etc.;
/// page_size at 48..52 stays cleartext).
///
/// Panics if `self.encryption` is `None` — only call for encrypted DBs.
pub fn serialize_encrypted(&self, cipher: &crate::crypto::PageCipher) -> [u8; PAGE_SIZE] {
Expand All @@ -390,8 +391,9 @@ impl Superblock {
.as_ref()
.expect("serialize_encrypted requires Superblock.encryption = Some");
let mut buf = [0u8; PAGE_SIZE];
// Plaintext bootstrap fields only. Sensitive scalar fields (16..52)
// and named_roots (52..308) are intentionally left zero.
// Plaintext bootstrap fields only. Sensitive scalar fields (16..48)
// and named_roots (52..308) are intentionally left zero (page_size at
// 48..52 is a cleartext bootstrap field, written just below).
buf[0..4].copy_from_slice(&self.magic.to_le_bytes());
buf[4..8].copy_from_slice(&self.format_version.to_le_bytes());
buf[8..16].copy_from_slice(&self.txn_counter.to_le_bytes());
Expand Down
2 changes: 1 addition & 1 deletion src/transaction/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

use super::*;

/// Borrows of the exactly-ten pieces of `TransactionManager` state the commit
/// Borrows of the exactly-twelve pieces of `TransactionManager` state the commit
/// protocol touches, bundled so `commit_inner` can stay a thin caller while the
/// load-bearing sequence lives here. All fields are distinct manager fields (plus
/// the shared `&RefCell` for the cache), so the borrow checker accepts the
Expand Down
4 changes: 2 additions & 2 deletions src/transaction/keys.rs
Original file line number Diff line number Diff line change
Expand Up @@ -373,8 +373,8 @@ mod tests {
#[test]
fn rewrite_alternates_superblock_slots() {
let mut db = fresh_encrypted();
// After fresh_encrypted: one create + one data commit = txn_counter=3
// (create writes N=2 initial slots + one commit). The next write targets
// After fresh_encrypted: create leaves txn_counter = superblock_count-1
// = 1 (N=2), then one data commit bumps it to 2. The next write targets
// txn_counter % 2.
// CryptoHeader is Copy so we can just use the value twice.
let hdr: CryptoHeader = db.crypto_header.unwrap();
Expand Down
2 changes: 1 addition & 1 deletion src/transaction/lifecycle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ impl TransactionManager {

fn commit_inner(&mut self) -> Result<()> {
// The 3-fsync commit protocol lives in `commit::run_commit`, operating
// over the ten pieces of manager state it touches via `CommitCtx`. The
// over the twelve pieces of manager state it touches via `CommitCtx`. The
// ordering there is load-bearing (see the step-by-step rationale on
// `commit()` above and in `commit.rs`); this stays a thin caller. All
// `&mut self.<field>` borrows are distinct fields and `&self.cache` is a
Expand Down
2 changes: 1 addition & 1 deletion src/transaction/recovery.rs
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ impl TransactionManager {
current_roots: roots,
handle_table: HandleTable::new(),
membership_index: MembershipIndex::new(),
// Slot 0 was written last in the loop above, at counter
// Slot 0 was written first in the loop above (i=0), at counter
// (superblock_count - 1 - 0) = superblock_count - 1. That's
// the highest counter and therefore the winner on select().
txn_counter: (superblock_count - 1) as u64,
Expand Down
Loading