libsql_replication/
lib.rs

1pub mod frame;
2pub mod injector;
3pub mod meta;
4pub mod replicator;
5pub mod rpc;
6pub mod snapshot;
7
8mod error;
9
10use libsql_sys::Cipher;
11
12pub const LIBSQL_PAGE_SIZE: usize = 4096;
13
14#[derive(Debug, Clone)]
15pub struct FrameEncryptor {
16    enc: cbc::Encryptor<aes::Aes256>,
17    dec: cbc::Decryptor<aes::Aes256>,
18}
19
20impl FrameEncryptor {
21    pub fn new(encryption_config: libsql_sys::EncryptionConfig) -> Self {
22        #[cfg(feature = "encryption")]
23        const SEED: u32 = 911;
24        #[cfg(not(feature = "encryption"))]
25        let _ = encryption_config;
26
27        use aes::cipher::KeyIvInit;
28
29        // TODO: make cipher configurable
30        assert!(matches!(encryption_config.cipher, Cipher::Aes256Cbc));
31
32        #[allow(unused_mut)]
33        let mut iv: [u8; 16] = [0; 16];
34        #[allow(unused_mut)]
35        let mut digest: [u8; 32] = [0; 32];
36        #[cfg(feature = "encryption")]
37        libsql_sys::connection::generate_initial_vector(SEED, &mut iv);
38        #[cfg(feature = "encryption")]
39        libsql_sys::connection::generate_aes256_key(&encryption_config.encryption_key, &mut digest);
40
41        let enc = cbc::Encryptor::new((&digest).into(), (&iv).into());
42        let dec = cbc::Decryptor::new((&digest).into(), (&iv).into());
43        Self { enc, dec }
44    }
45
46    pub fn encrypt(&self, data: &mut [u8]) -> Result<(), rusqlite::ffi::Error> {
47        use aes::cipher::{block_padding::NoPadding, BlockEncryptMut};
48        // NOTICE: We don't want to return padding errors, it will make the code
49        // prone to CBC padding oracle attacks.
50        self.enc
51            .clone()
52            .encrypt_padded_mut::<NoPadding>(data, data.len())
53            .map_err(|_| rusqlite::ffi::Error::new(libsql_sys::ffi::SQLITE_IOERR_WRITE))?;
54        Ok(())
55    }
56
57    pub fn decrypt(&self, data: &mut [u8]) -> Result<(), rusqlite::ffi::Error> {
58        use aes::cipher::{block_padding::NoPadding, BlockDecryptMut};
59        // NOTICE: We don't want to return padding errors, it will make the code
60        // prone to CBC padding oracle attacks.
61        self.dec
62            .clone()
63            .decrypt_padded_mut::<NoPadding>(data)
64            .map_err(|_| rusqlite::ffi::Error::new(libsql_sys::ffi::SQLITE_IOERR_READ))?;
65        Ok(())
66    }
67}