1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Copyright (c) 2018-2021 The MobileCoin Foundation

//! This module defines several "factory traits" that e.g. create recursive ORAMS
//! and control the configuration of recursive children etc.
//!
//! Factories are useful, as opposed to "new_from_..." traits, because a single
//! generic implementation may be often configured in one of several ways.
//! The factory is thus a configuration strategy and they naturally may chain
//! together to create an easy-to-use interface to get an ORAM.
//!
//! This is an alternative to hard-coding constants such as the block size or
//! number of buckets in an ORAM into the implementation code itself, and may
//! make it easier to create automated benchmarks that compare the effects of
//! different settings.

use super::*;

use alloc::boxed::Box;
use rand_core::SeedableRng;

/// A factory which creates an ORAM of arbitrary size using recursive strategy.
/// The result is required to have the 'static lifetime, and not be tied to the factory.
pub trait ORAMCreator<ValueSize: ArrayLength<u8>, RngType: RngCore + CryptoRng> {
    type Output: ORAM<ValueSize> + Send + Sync + 'static;

    fn create<M: 'static + FnMut() -> RngType>(
        size: u64,
        stash_size: usize,
        rng_maker: &mut M,
    ) -> Self::Output;
}

/// A factory which creates a PositionMap
pub trait PositionMapCreator<RngType: RngCore + CryptoRng> {
    fn create<M: 'static + FnMut() -> RngType>(
        size: u64,
        height: u32,
        stash_size: usize,
        rng_maker: &mut M,
    ) -> Box<dyn PositionMap + Send + Sync + 'static>;
}

/// A factory which makes ORAMStorage objects of some type
///
/// In case of tests, it may simply create Vec objects.
/// In production, it likely calls out to untrusted and asks to allocate
/// block storage for an ORAM.
///
/// The result is required to have the 'static lifetime, there is no in-enclave
/// "manager" object which these objects can refer to. Instead they are either
/// wrapping a vector, or e.g. they hold integer handles which they use when they make
/// OCALL's to untrusted.
/// So there is no manager object in the enclave which they cannot outlive.
pub trait ORAMStorageCreator<BlockSize: ArrayLength<u8>, MetaSize: ArrayLength<u8>> {
    /// The storage type produced
    type Output: ORAMStorage<BlockSize, MetaSize> + Send + Sync + 'static;
    /// The error type produced
    type Error: Display + Debug;

    /// Create OramStorage, giving it a size and a CSPRNG for initialization.
    /// This should usually be RDRAND but in tests it might have a seed.
    ///
    /// It is expected that all storage will be zeroed from the caller's point
    /// of view, the first time that they access any of it.
    fn create<R: RngCore + CryptoRng>(
        size: u64,
        csprng: &mut R,
    ) -> Result<Self::Output, Self::Error>;
}

/// A factory which makes ObliviousMap objects of some type, based on an ORAM
pub trait OMapCreator<KeySize: ArrayLength<u8>, ValueSize: ArrayLength<u8>, R: RngCore + CryptoRng>
{
    /// The storage type produced
    type Output: ObliviousHashMap<KeySize, ValueSize> + Send + Sync + 'static;

    /// Create an oblivious map, with at least capacity specified.
    /// The stash size will be used by ORAMs underlying it.
    fn create<M: 'static + FnMut() -> R>(
        desired_capacity: u64,
        stash_size: usize,
        rng_maker: M,
    ) -> Self::Output;
}

/// A helper which takes an Rng implementing SeedableRng and returns a lambda
/// which returns newly seeded Rng's with seeds derived from this one.
/// This matches the `rng_maker` constraints in the above traits, and can be used
/// in tests when we want all the Rng's to be seeded.
pub fn rng_maker<R: RngCore + CryptoRng + SeedableRng + 'static>(
    mut source: R,
) -> impl FnMut() -> R + 'static {
    move || {
        let mut seed = R::Seed::default();
        source.fill_bytes(seed.as_mut());
        R::from_seed(seed)
    }
}