passing encryption key from builder to Lmdb lib, with proper memory management

without.crypto
Niko 2 years ago
parent 21f7436178
commit bbe0707d22
  1. 2
      Cargo.toml
  2. 1
      lmdb-sys/build.rs
  3. 2
      lmdb-sys/lmdb
  4. 3
      lmdb-sys/src/bindings.rs
  5. BIN
      lmdb-sys/tests/fixtures/testdb/data.mdb
  6. BIN
      lmdb-sys/tests/fixtures/testdb/lock.mdb
  7. 6
      lmdb-sys/tests/simple.rs
  8. 37
      src/environment.rs

@ -2,7 +2,7 @@
name = "lmdb-lofire"
# NB: When modifying, also modify html_root_url in lib.rs
version = "0.14.0"
authors = ["NikoPLP <info@parlepeuple.fr>"]
authors = ["Dan Burkert <dan@danburkert.com>", "Victor Porof <vporof@mozilla.com>","NikoPLP <info@parlepeuple.fr>"]
license = "Apache-2.0"
description = "Idiomatic and safe LMDB wrapper."
documentation = "https://docs.rs/lmdb-lofire"

@ -65,6 +65,7 @@ fn main() {
builder
.define("MDB_IDL_LOGN", Some(MDB_IDL_LOGN.to_string().as_str()))
.file(lmdb.join("mdb.c"))
.file(lmdb.join("chacha8.c"))
.file(lmdb.join("midl.c"))
// https://github.com/mozilla/lmdb/blob/b7df2cac50fb41e8bd16aab4cc5fd167be9e032a/libraries/liblmdb/Makefile#L23
.flag_if_supported("-Wno-unused-parameter")

@ -1 +1 @@
Subproject commit a9e0d9dfcaa30a885b250fc71bbc31a2a597842b
Subproject commit 6156b10356e3b2840abed2afd59f7a2ea2581f42

@ -591,6 +591,9 @@ extern "C" {
#[doc = " </ul>"]
pub fn mdb_env_set_mapsize(env: *mut MDB_env, size: usize) -> ::libc::c_int;
}
extern "C" {
pub fn mdb_env_init_crypto(env: *mut MDB_env, key: *mut ::libc::c_void) -> ::libc::c_int;
}
extern "C" {
#[doc = " @brief Set the maximum number of threads/reader slots for the environment."]
#[doc = ""]

Binary file not shown.

Binary file not shown.

@ -59,8 +59,8 @@ fn test_simple(env_path: &str) {
mv_data: ptr::null_mut(),
};
let mut txn: *mut MDB_txn = ptr::null_mut();
let sval = str!("fdedeoo") as *mut c_void;
let dval = str!("bdedear") as *mut c_void;
//let sval = str!("fdedeoo") as *mut c_void;
//let dval = str!("bdedear") as *mut c_void;
let mut buffer: [u8; 7] = [0; 7];
buffer[0] = 65;
@ -77,7 +77,7 @@ fn test_simple(env_path: &str) {
E!(mdb_env_open(env, str!(env_path), 0, 0664));
E!(mdb_txn_begin(env, ptr::null_mut(), 0, &mut txn));
E!(mdb_dbi_open(txn, str!("test"), MDB_CREATE, &mut dbi));
E!(mdb_dbi_open(txn, str!("testdb"), MDB_CREATE, &mut dbi));
E!(mdb_txn_commit(txn));
key.mv_size = 7;

@ -1,9 +1,11 @@
use libc::{c_uint, size_t};
use std::alloc::{alloc, dealloc, Layout};
use std::ffi::CStr;
use std::ffi::CString;
#[cfg(windows)]
use std::ffi::OsStr;
use std::os::raw::c_char;
#[cfg(unix)]
use std::os::unix::ffi::OsStrExt;
use std::path::Path;
@ -20,6 +22,8 @@ use error::{lmdb_result, Error, Result};
use flags::{DatabaseFlags, EnvironmentFlags};
use transaction::{RoTransaction, RwTransaction, Transaction};
use libc::c_void;
#[cfg(windows)]
/// Adding a 'missing' trait from windows OsStrExt
trait OsStrExtLmdb {
@ -32,12 +36,15 @@ impl OsStrExtLmdb for OsStr {
}
}
static ZEROS: [u8; 32] = [0; 32];
/// An LMDB environment.
///
/// An environment supports multiple databases, all residing in the same shared-memory map.
pub struct Environment {
env: *mut ffi::MDB_env,
dbi_open_mutex: Mutex<()>,
enc_key_ptr: *mut u8,
}
impl Environment {
@ -49,6 +56,7 @@ impl Environment {
max_readers: None,
max_dbs: None,
map_size: None,
encryption_key: None,
}
}
@ -363,7 +371,16 @@ impl fmt::Debug for Environment {
impl Drop for Environment {
fn drop(&mut self) {
unsafe { ffi::mdb_env_close(self.env) }
unsafe {
ffi::mdb_env_close(self.env);
if !self.enc_key_ptr.is_null() {
// zeros the heap memory that was used for the key
std::ptr::copy(ZEROS.as_ptr(), self.enc_key_ptr, 16);
// and dealloc it
let layout = Layout::new::<[u8; 32]>();
dealloc(self.enc_key_ptr, layout);
}
}
}
}
@ -378,6 +395,7 @@ pub struct EnvironmentBuilder {
max_readers: Option<c_uint>,
max_dbs: Option<c_uint>,
map_size: Option<size_t>,
encryption_key: Option<[u8; 32]>,
}
impl EnvironmentBuilder {
@ -399,8 +417,18 @@ impl EnvironmentBuilder {
/// paths are not supported either.
pub fn open_with_permissions(&self, path: &Path, mode: ffi::mdb_mode_t) -> Result<Environment> {
let mut env: *mut ffi::MDB_env = ptr::null_mut();
let mut enc_key_ptr: *mut u8 = ptr::null_mut();
unsafe {
lmdb_try!(ffi::mdb_env_create(&mut env));
if let Some(encryption_key) = self.encryption_key {
let layout = Layout::new::<[u8; 32]>();
enc_key_ptr = alloc(layout);
std::ptr::copy(encryption_key.as_ptr(), enc_key_ptr, 32);
lmdb_try_with_cleanup!(ffi::mdb_env_init_crypto(env, enc_key_ptr as *mut c_void), || {
ffi::mdb_env_close(env);
dealloc(enc_key_ptr, layout);
})
}
if let Some(max_readers) = self.max_readers {
lmdb_try_with_cleanup!(ffi::mdb_env_set_maxreaders(env, max_readers), ffi::mdb_env_close(env))
}
@ -421,6 +449,7 @@ impl EnvironmentBuilder {
}
Ok(Environment {
env,
enc_key_ptr,
dbi_open_mutex: Mutex::new(()),
})
}
@ -471,6 +500,12 @@ impl EnvironmentBuilder {
self.map_size = Some(map_size);
self
}
/// Sets the encryption key to use for the environment.
pub fn set_enc_key(&mut self, key: [u8; 32]) -> &mut EnvironmentBuilder {
self.encryption_key = Some(key);
self
}
}
#[cfg(test)]

Loading…
Cancel
Save