Skip to content

Commit 6ea8c35

Browse files
authored
Merge pull request #92 from bluele/fix-keymanager
Fix keymanager to be thread-safe Signed-off-by: Jun Kimura <[email protected]>
2 parents df90274 + 98326e3 commit 6ea8c35

File tree

6 files changed

+115
-38
lines changed

6 files changed

+115
-38
lines changed

modules/enclave-api/src/enclave.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ use store::host::{HostStore, IntoCommitStore};
99
use store::transaction::{CommitStore, CreatedTx, UpdateKey};
1010

1111
/// `Enclave` keeps an enclave id and reference to the host environement
12-
pub struct Enclave<S> {
12+
pub struct Enclave<S: CommitStore> {
1313
pub(crate) path: PathBuf,
1414
pub(crate) key_manager: EnclaveKeyManager,
1515
pub(crate) store: Arc<RwLock<HostStore>>,
1616
pub(crate) sgx_enclave: SgxEnclave,
1717
_marker: PhantomData<S>,
1818
}
1919

20-
impl<S> Enclave<S> {
20+
impl<S: CommitStore> Enclave<S> {
2121
pub fn new(
2222
path: impl Into<PathBuf>,
2323
key_manager: EnclaveKeyManager,
@@ -49,7 +49,7 @@ impl<S> Enclave<S> {
4949
}
5050

5151
/// `EnclaveInfo` is an accessor to enclave information
52-
pub trait EnclaveInfo {
52+
pub trait EnclaveInfo: Sync + Send {
5353
/// `get_eid` returns the enclave id
5454
fn get_eid(&self) -> sgx_enclave_id_t;
5555
/// `metadata` returns the metadata of the enclave
@@ -58,7 +58,7 @@ pub trait EnclaveInfo {
5858
fn get_key_manager(&self) -> &EnclaveKeyManager;
5959
}
6060

61-
impl<S> EnclaveInfo for Enclave<S> {
61+
impl<S: CommitStore> EnclaveInfo for Enclave<S> {
6262
/// `get_eid` returns the enclave id
6363
fn get_eid(&self) -> sgx_enclave_id_t {
6464
self.sgx_enclave.geteid()

modules/keymanager/src/errors.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,15 @@ define_error! {
3636

3737
Rusqlite
3838
[TraceError<rusqlite::Error>]
39-
|_| { "rusqlite error" }
39+
|_| { "rusqlite error" },
40+
41+
MutexLock
42+
{
43+
descr: String
44+
}
45+
|e| {
46+
format_args!("mutex lock error: descr={}", e.descr)
47+
}
4048
}
4149
}
4250

modules/keymanager/src/lib.rs

Lines changed: 42 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -7,37 +7,42 @@ use lcp_types::{Mrenclave, Time};
77
use log::*;
88
use rusqlite::{params, types::Type, Connection};
99
use serde::{Deserialize, Serialize};
10+
use std::sync::Mutex;
1011
use std::{ops::Deref, path::Path, time::Duration};
1112

1213
pub static KEY_MANAGER_DB: &str = "km.sqlite";
1314

1415
pub struct EnclaveKeyManager {
15-
conn: Connection,
16+
conn: Mutex<Connection>,
1617
}
1718

1819
impl EnclaveKeyManager {
1920
pub fn new(home_dir: &Path) -> Result<Self, Error> {
2021
let km_db = home_dir.join(KEY_MANAGER_DB);
2122
let db_exists = km_db.exists();
22-
let conn = Connection::open(&km_db)?;
23+
let conn = Mutex::new(Connection::open(&km_db)?);
2324
let this = Self { conn };
2425
if !db_exists {
25-
this.setup()?;
26+
this.init_db()?;
2627
info!("initialized Key Manager: {:?}", km_db);
2728
}
2829
Ok(this)
2930
}
3031

3132
#[cfg(test)]
3233
pub fn new_in_memory() -> Result<Self, Error> {
33-
let conn = Connection::open_in_memory()?;
34+
let conn = Mutex::new(Connection::open_in_memory()?);
3435
let this = Self { conn };
35-
this.setup()?;
36+
this.init_db()?;
3637
Ok(this)
3738
}
3839

39-
fn setup(&self) -> Result<(), Error> {
40-
self.conn.execute_batch(
40+
fn init_db(&self) -> Result<(), Error> {
41+
let conn = self
42+
.conn
43+
.lock()
44+
.map_err(|e| Error::mutex_lock(e.to_string()))?;
45+
conn.execute_batch(
4146
r#"
4247
BEGIN;
4348
CREATE TABLE enclave_keys (
@@ -61,7 +66,11 @@ impl EnclaveKeyManager {
6166

6267
/// Load a sealed enclave key by address
6368
pub fn load(&self, address: Address) -> Result<SealedEnclaveKeyInfo, Error> {
64-
let mut stmt = self.conn.prepare(
69+
let conn = self
70+
.conn
71+
.lock()
72+
.map_err(|e| Error::mutex_lock(e.to_string()))?;
73+
let mut stmt = conn.prepare(
6574
"SELECT ek_sealed, mrenclave, avr, signature, signing_cert FROM enclave_keys WHERE ek_address = ?1",
6675
)?;
6776
let key_info = stmt.query_row(params![address.to_hex_string()], |row| {
@@ -98,7 +107,11 @@ impl EnclaveKeyManager {
98107
sealed_ek: SealedEnclaveKey,
99108
mrenclave: Mrenclave,
100109
) -> Result<(), Error> {
101-
let mut stmt = self.conn.prepare(
110+
let conn = self
111+
.conn
112+
.lock()
113+
.map_err(|e| Error::mutex_lock(e.to_string()))?;
114+
let mut stmt = conn.prepare(
102115
"INSERT INTO enclave_keys (ek_address, ek_sealed, mrenclave) VALUES (?1, ?2, ?3)",
103116
)?;
104117
let _ = stmt.execute(params![
@@ -115,9 +128,13 @@ impl EnclaveKeyManager {
115128
address: Address,
116129
avr: EndorsedAttestationVerificationReport,
117130
) -> Result<(), Error> {
131+
let conn = self
132+
.conn
133+
.lock()
134+
.map_err(|e| Error::mutex_lock(e.to_string()))?;
118135
let attested_at = avr.get_avr()?.attestation_time()?;
119136
// update avr and attested_at and signature and sigining_cert
120-
let mut stmt = self.conn.prepare(
137+
let mut stmt = conn.prepare(
121138
"UPDATE enclave_keys SET avr = ?1, attested_at = ?2, signature = ?3, signing_cert = ?4 WHERE ek_address = ?5",
122139
)?;
123140
stmt.execute(params![
@@ -132,7 +149,11 @@ impl EnclaveKeyManager {
132149

133150
/// Returns a list of available enclave keys
134151
pub fn available_keys(&self, mrenclave: Mrenclave) -> Result<Vec<SealedEnclaveKeyInfo>, Error> {
135-
let mut stmt = self.conn.prepare(
152+
let conn = self
153+
.conn
154+
.lock()
155+
.map_err(|e| Error::mutex_lock(e.to_string()))?;
156+
let mut stmt = conn.prepare(
136157
r#"
137158
SELECT ek_address, ek_sealed, mrenclave, avr, signature, signing_cert
138159
FROM enclave_keys
@@ -164,7 +185,11 @@ impl EnclaveKeyManager {
164185

165186
/// Returns a list of all enclave keys
166187
pub fn all_keys(&self) -> Result<Vec<SealedEnclaveKeyInfo>, Error> {
167-
let mut stmt = self.conn.prepare(
188+
let conn = self
189+
.conn
190+
.lock()
191+
.map_err(|e| Error::mutex_lock(e.to_string()))?;
192+
let mut stmt = conn.prepare(
168193
"SELECT ek_address, ek_sealed, mrenclave, avr, signature, signing_cert FROM enclave_keys ORDER BY updated_at DESC",
169194
)?;
170195
let key_infos = stmt
@@ -200,10 +225,12 @@ impl EnclaveKeyManager {
200225

201226
/// Prune keys after the expiration time(secs) from the attestation time.
202227
pub fn prune(&self, expiration_time: u64) -> Result<usize, Error> {
203-
let expired = (Time::now() - Duration::from_secs(expiration_time))?;
204-
let mut stmt = self
228+
let conn = self
205229
.conn
206-
.prepare("DELETE FROM enclave_keys WHERE attested_at <= ?1")?;
230+
.lock()
231+
.map_err(|e| Error::mutex_lock(e.to_string()))?;
232+
let expired = (Time::now() - Duration::from_secs(expiration_time))?;
233+
let mut stmt = conn.prepare("DELETE FROM enclave_keys WHERE attested_at <= ?1")?;
207234
let count = stmt.execute(params![expired.as_unix_timestamp_secs()])?;
208235
Ok(count)
209236
}

modules/service/src/service.rs

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -33,19 +33,6 @@ where
3333
}
3434
}
3535

36-
unsafe impl<E, S> Send for AppService<E, S>
37-
where
38-
S: CommitStore + 'static,
39-
E: EnclaveProtoAPI<S> + 'static,
40-
{
41-
}
42-
unsafe impl<E, S> Sync for AppService<E, S>
43-
where
44-
S: CommitStore + 'static,
45-
E: EnclaveProtoAPI<S> + 'static,
46-
{
47-
}
48-
4936
impl<E, S> AppService<E, S>
5037
where
5138
S: CommitStore + 'static,

modules/store/src/memory.rs

Lines changed: 59 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,72 @@ use crate::store::TxId;
33
use crate::transaction::{CommitStore, CreatedTx, Tx, TxAccessor};
44
use crate::{KVStore, Result};
55
use std::collections::HashMap;
6+
use std::sync::Mutex;
67

78
// MemStore is only available for testing purposes
89
#[derive(Default, Debug)]
9-
pub struct MemStore {
10+
pub struct MemStore(Mutex<InnerMemStore>);
11+
12+
impl KVStore for MemStore {
13+
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
14+
self.0.lock().unwrap().get(key)
15+
}
16+
17+
fn set(&mut self, key: Vec<u8>, value: Vec<u8>) {
18+
self.0.lock().unwrap().set(key, value)
19+
}
20+
21+
fn remove(&mut self, key: &[u8]) {
22+
self.0.lock().unwrap().remove(key)
23+
}
24+
}
25+
26+
impl TxAccessor for MemStore {
27+
fn run_in_tx<T>(&self, tx_id: TxId, f: impl FnOnce(&dyn KVStore) -> T) -> Result<T> {
28+
self.0.lock().unwrap().run_in_tx(tx_id, f)
29+
}
30+
31+
fn run_in_mut_tx<T>(
32+
&mut self,
33+
tx_id: TxId,
34+
f: impl FnOnce(&mut dyn KVStore) -> T,
35+
) -> Result<T> {
36+
self.0.lock().unwrap().run_in_mut_tx(tx_id, f)
37+
}
38+
}
39+
40+
impl CommitStore for MemStore {
41+
type Tx = MemTx;
42+
43+
fn create_transaction(
44+
&mut self,
45+
_update_key: Option<crate::transaction::UpdateKey>,
46+
) -> Result<Self::Tx> {
47+
self.0.lock().unwrap().create_transaction(_update_key)
48+
}
49+
50+
fn begin(&mut self, tx: &<Self::Tx as CreatedTx>::PreparedTx) -> Result<()> {
51+
self.0.lock().unwrap().begin(tx)
52+
}
53+
54+
fn commit(&mut self, tx: <Self::Tx as CreatedTx>::PreparedTx) -> Result<()> {
55+
self.0.lock().unwrap().commit(tx)
56+
}
57+
58+
fn rollback(&mut self, tx: <Self::Tx as CreatedTx>::PreparedTx) {
59+
self.0.lock().unwrap().rollback(tx)
60+
}
61+
}
62+
63+
#[derive(Default, Debug)]
64+
pub struct InnerMemStore {
1065
running_tx_exists: bool,
1166
latest_tx_id: TxId,
1267
uncommitted_data: HashMap<Vec<u8>, Option<Vec<u8>>>,
1368
committed_data: HashMap<Vec<u8>, Vec<u8>>,
1469
}
1570

16-
impl KVStore for MemStore {
71+
impl KVStore for InnerMemStore {
1772
fn get(&self, key: &[u8]) -> Option<Vec<u8>> {
1873
if self.running_tx_exists {
1974
match self.uncommitted_data.get(key) {
@@ -42,7 +97,7 @@ impl KVStore for MemStore {
4297
}
4398
}
4499

45-
impl TxAccessor for MemStore {
100+
impl TxAccessor for InnerMemStore {
46101
fn run_in_tx<T>(&self, _tx_id: TxId, f: impl FnOnce(&dyn KVStore) -> T) -> Result<T> {
47102
Ok(f(self))
48103
}
@@ -56,7 +111,7 @@ impl TxAccessor for MemStore {
56111
}
57112
}
58113

59-
impl CommitStore for MemStore {
114+
impl CommitStore for InnerMemStore {
60115
type Tx = MemTx;
61116

62117
fn create_transaction(

modules/store/src/transaction.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ pub trait CreatedTx: Tx {
1919
}
2020

2121
/// `CommitStore` is a store that supports transactions
22-
pub trait CommitStore {
22+
pub trait CommitStore: Sync + Send {
2323
type Tx: CreatedTx;
2424

2525
/// `create_transaction` creates a transaction with a given `update_key`

0 commit comments

Comments
 (0)