mc_oblivious_traits/
naive_storage.rs

1// Copyright (c) 2018-2023 The MobileCoin Foundation
2
3//! HeapORAMStorage just uses a Vec to provide access to block storage in the
4//! simplest way possible. It does not do any memory encryption or talk to
5//! untrusted. It does not have any oblivious properties itself.
6//! This is suitable for tests, or ORAMs that fit entirely in the enclave.
7
8use super::*;
9
10use alloc::vec;
11use balanced_tree_index::TreeIndex;
12
13/// The HeapORAMStorage is simply vector
14pub struct HeapORAMStorage<BlockSize: ArrayLength<u8>, MetaSize: ArrayLength<u8>> {
15    /// The storage for the blocks
16    data: Vec<A64Bytes<BlockSize>>,
17    /// The storage for the metadata
18    metadata: Vec<A8Bytes<MetaSize>>,
19    /// This is here so that we can provide good debug asserts in tests,
20    /// it wouldn't be needed necessarily in a production version.
21    checkout_index: Option<u64>,
22}
23
24impl<BlockSize: ArrayLength<u8>, MetaSize: ArrayLength<u8>> HeapORAMStorage<BlockSize, MetaSize> {
25    pub fn new(size: u64) -> Self {
26        Self {
27            data: vec![Default::default(); size as usize],
28            metadata: vec![Default::default(); size as usize],
29            checkout_index: None,
30        }
31    }
32}
33
34impl<BlockSize: ArrayLength<u8>, MetaSize: ArrayLength<u8>> ORAMStorage<BlockSize, MetaSize>
35    for HeapORAMStorage<BlockSize, MetaSize>
36{
37    fn len(&self) -> u64 {
38        self.data.len() as u64
39    }
40    fn checkout(
41        &mut self,
42        leaf_index: u64,
43        dest: &mut [A64Bytes<BlockSize>],
44        dest_meta: &mut [A8Bytes<MetaSize>],
45    ) {
46        debug_assert!(self.checkout_index.is_none(), "double checkout");
47        debug_assert!(dest.len() == dest_meta.len(), "buffer size mismatch");
48        debug_assert!(
49            leaf_index.parents().count() == dest.len(),
50            "leaf height doesn't match buffer sizes"
51        );
52        for (n, tree_index) in leaf_index.parents().enumerate() {
53            dest[n] = self.data[tree_index as usize].clone();
54            dest_meta[n] = self.metadata[tree_index as usize].clone();
55        }
56        self.checkout_index = Some(leaf_index);
57    }
58    fn checkin(
59        &mut self,
60        leaf_index: u64,
61        src: &mut [A64Bytes<BlockSize>],
62        src_meta: &mut [A8Bytes<MetaSize>],
63    ) {
64        debug_assert!(self.checkout_index.is_some(), "checkin without checkout");
65        debug_assert!(
66            self.checkout_index == Some(leaf_index),
67            "unexpected checkin"
68        );
69        debug_assert!(src.len() == src_meta.len(), "buffer size mismatch");
70        debug_assert!(
71            leaf_index.parents().count() == src.len(),
72            "leaf height doesn't match buffer sizes"
73        );
74        for (n, tree_index) in leaf_index.parents().enumerate() {
75            self.data[tree_index as usize] = src[n].clone();
76            self.metadata[tree_index as usize] = src_meta[n].clone();
77        }
78        self.checkout_index = None;
79    }
80}
81
82/// HeapORAMStorage simply allocates a vector, and requires no special
83/// initialization support
84pub struct HeapORAMStorageCreator {}
85
86impl<BlockSize: ArrayLength<u8> + 'static, MetaSize: ArrayLength<u8> + 'static>
87    ORAMStorageCreator<BlockSize, MetaSize> for HeapORAMStorageCreator
88{
89    type Output = HeapORAMStorage<BlockSize, MetaSize>;
90    type Error = HeapORAMStorageCreatorError;
91
92    fn create<R: RngCore + CryptoRng>(
93        size: u64,
94        _rng: &mut R,
95    ) -> Result<Self::Output, Self::Error> {
96        Ok(Self::Output::new(size))
97    }
98}
99
100/// There are not actually any failure modes
101#[derive(Debug)]
102pub enum HeapORAMStorageCreatorError {}
103
104impl core::fmt::Display for HeapORAMStorageCreatorError {
105    fn fmt(&self, _: &mut core::fmt::Formatter) -> core::fmt::Result {
106        unreachable!()
107    }
108}