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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
// Copyright (c) Meta Platforms, Inc. and affiliates.
//
// This source code is dual-licensed under either the MIT license found in the
// LICENSE-MIT file in the root directory of this source tree or the Apache
// License, Version 2.0 found in the LICENSE-APACHE file in the root directory
// of this source tree. You may select, at your option, one of the above-listed licenses.
//! An implementation of Oblivious RAM (ORAM) for the secure enclave setting.
//!
//! ⚠️ **Warning**: This implementation has not been audited. Use at your own risk!
//!
//! # Overview
//!
//! This crate implements an oblivious RAM protocol (ORAM) for (secure) enclave applications.
//!
//! This crate assumes that ORAM clients are running inside a secure enclave architecture that provides memory encryption.
//! It does not perform encryption-on-write and thus is **not** secure without memory encryption.
//!
//! # Design
//!
//! This crate implements the Path ORAM protocol, with oblivious
//! client data structures based on the [Oblix paper](https://people.eecs.berkeley.edu/~raluca/oblix.pdf).
//! See the [Path ORAM retrospective paper](http://elaineshi.com/docs/pathoram-retro.pdf)
//! for a high-level introduction to ORAM and Path ORAM, and for more detailed references.
//!
//! # Example
//!
//! The below example reads a database from memory into an ORAM, thus permitting secret-dependent accesses.
//!
//! ```
//! use oram::{Address, BlockSize, BlockValue, Oram, DefaultOram};
//! # use oram::OramError;
//!
//! const BLOCK_SIZE: BlockSize = 64;
//! const DB_SIZE: Address = 64;
//! # const DATABASE: [[u8; BLOCK_SIZE as usize]; DB_SIZE as usize] =
//! # [[0; BLOCK_SIZE as usize]; DB_SIZE as usize];
//! let mut rng = rand::rngs::OsRng;
//!
//! // Initialize an ORAM to store 64 blocks of 64 bytes each.
//! let mut oram = DefaultOram::<BlockValue<BLOCK_SIZE>>::new(DB_SIZE, &mut rng)?;
//!
//! // Read a database (here, an array of byte arrays) into the ORAM.
//! for (i, bytes) in DATABASE.iter().enumerate() {
//! oram.write(i as Address, BlockValue::new(*bytes), &mut rng)?;
//! }
//!
//! // Now you can safely make secret-dependent accesses to your database.
//! let secret = 42;
//! let _ = oram.read(secret, &mut rng)?;
//! # Ok::<(), OramError>(())
//! ```
//!
//! # Advanced
//!
//! ORAMs can store arbitrary structs implementing `OramBlock`.
//! We provide implementations of `OramBlock` for `u8`, `u16`, `u32`, `u64`, `i8`, `i16`, `i32`, `i64`,
//! and `BlockValue<const B: BlockSize>`.
//!
//! The `DefaultOram` used in the above example should have good performance in most use cases.
//! But the underlying algorithms have several tunable parameters that impact performance.
//! The following example instantiates the same ORAM struct as above, but using the `PathOram`
//! interface which exposes these parameters.
//!
//! ```
//! use oram::{Address, BlockSize, BlockValue, BucketSize,
//! Oram, PathOram, StashSize, RecursionCutoff};
//! use oram::path_oram::{DEFAULT_BLOCKS_PER_BUCKET, DEFAULT_RECURSION_CUTOFF,
//! DEFAULT_POSITIONS_PER_BLOCK, DEFAULT_STASH_OVERFLOW_SIZE};
//! # use oram::OramError;
//! # let mut rng = rand::rngs::OsRng;
//! # const BLOCK_SIZE: BlockSize = 64;
//! # const DB_SIZE: Address = 64;
//!
//! const RECURSION_CUTOFF: RecursionCutoff = DEFAULT_RECURSION_CUTOFF;
//! const BUCKET_SIZE: BucketSize = DEFAULT_BLOCKS_PER_BUCKET;
//! const POSITIONS_PER_BLOCK: BlockSize = DEFAULT_POSITIONS_PER_BLOCK;
//! const INITIAL_STASH_OVERFLOW_SIZE: StashSize = DEFAULT_STASH_OVERFLOW_SIZE;
//!
//! let mut oram = PathOram::<
//! BlockValue<BLOCK_SIZE>,
//! BUCKET_SIZE,
//! POSITIONS_PER_BLOCK,
//! >::new_with_parameters(DB_SIZE, &mut rng, INITIAL_STASH_OVERFLOW_SIZE, RECURSION_CUTOFF)?;
//! # Ok::<(), OramError>(())
//! ```
//!
//! See [`PathOram`] for an explanation of these parameters and their possible settings.
use TryFromIntError;
use ;
use ConditionallySelectable;
use Error;
pub
pub
pub
pub
pub use crateBlockValue;
pub use crateDefaultOram;
pub use cratePathOram;
/// The numeric type used to specify the size of an ORAM block in bytes.
pub type BlockSize = usize;
/// The numeric type used to specify the size of an ORAM in blocks, and to index into the ORAM.
pub type Address = u64;
/// The numeric type used to specify the size of an ORAM bucket in blocks.
pub type BucketSize = usize;
/// The numeric type used to specify the cutoff size
/// below which `PathOram` uses a linear position map instead of a recursive one.
pub type RecursionCutoff = u64;
/// Numeric type used to represent the size of a Path ORAM stash in blocks.
pub type StashSize = u64;
/// A "trait alias" for ORAM blocks: the values read and written by ORAMs.
/// A list of error types which are produced during ORAM protocol execution.
/// Represents an oblivious RAM (ORAM) mapping addresses of type `Address` to values of type `V: OramBlock`.