PyORAm
[iotcloud.git] / PyORAM / src / pyoram / encrypted_storage / encrypted_heap_storage.py
diff --git a/PyORAM/src/pyoram/encrypted_storage/encrypted_heap_storage.py b/PyORAM/src/pyoram/encrypted_storage/encrypted_heap_storage.py
new file mode 100644 (file)
index 0000000..763ac93
--- /dev/null
@@ -0,0 +1,172 @@
+__all__ = ('EncryptedHeapStorage',)
+
+import struct
+
+from pyoram.util.virtual_heap import SizedVirtualHeap
+from pyoram.storage.heap_storage import \
+    (HeapStorageInterface,
+     HeapStorage)
+from pyoram.encrypted_storage.encrypted_block_storage import \
+    (EncryptedBlockStorageInterface,
+     EncryptedBlockStorage)
+
+class EncryptedHeapStorageInterface(HeapStorageInterface):
+
+    #
+    # Abstract Interface
+    #
+
+    @property
+    def key(self, *args, **kwds):
+        raise NotImplementedError                      # pragma: no cover
+    @property
+    def raw_storage(self, *args, **kwds):
+        raise NotImplementedError                      # pragma: no cover
+
+class EncryptedHeapStorage(HeapStorage,
+                           EncryptedHeapStorageInterface):
+
+    def __init__(self, storage, **kwds):
+
+        if isinstance(storage, EncryptedBlockStorageInterface):
+            if len(kwds):
+                raise ValueError(
+                    "Keywords not used when initializing "
+                    "with a storage device: %s"
+                    % (str(kwds)))
+        else:
+            storage = EncryptedBlockStorage(storage, **kwds)
+
+        super(EncryptedHeapStorage, self).__init__(storage)
+
+    #
+    # Define EncryptedHeapStorageInterface Methods
+    #
+
+    @property
+    def key(self):
+        return self._storage.key
+
+    @property
+    def raw_storage(self):
+        return self._storage.raw_storage
+
+    #
+    # Define HeapStorageInterface Methods
+    # (override what is defined on HeapStorage)
+
+    def clone_device(self):
+        return EncryptedHeapStorage(self._storage.clone_device())
+
+    @classmethod
+    def compute_storage_size(cls,
+                             block_size,
+                             heap_height,
+                             blocks_per_bucket=1,
+                             heap_base=2,
+                             ignore_header=False,
+                             **kwds):
+        assert (block_size > 0) and (block_size == int(block_size))
+        assert heap_height >= 0
+        assert blocks_per_bucket >= 1
+        assert heap_base >= 2
+        assert 'block_count' not in kwds
+        vheap = SizedVirtualHeap(
+            heap_base,
+            heap_height,
+            blocks_per_bucket=blocks_per_bucket)
+        if ignore_header:
+            return EncryptedBlockStorage.compute_storage_size(
+                vheap.blocks_per_bucket * block_size,
+                vheap.bucket_count(),
+                ignore_header=True,
+                **kwds)
+        else:
+            return cls._header_offset + \
+                   EncryptedBlockStorage.compute_storage_size(
+                       vheap.blocks_per_bucket * block_size,
+                       vheap.bucket_count(),
+                       ignore_header=False,
+                       **kwds)
+
+    @classmethod
+    def setup(cls,
+              storage_name,
+              block_size,
+              heap_height,
+              blocks_per_bucket=1,
+              heap_base=2,
+              **kwds):
+        if 'block_count' in kwds:
+            raise ValueError("'block_count' keyword is not accepted")
+        if heap_height < 0:
+            raise ValueError(
+                "heap height must be 0 or greater. Invalid value: %s"
+                % (heap_height))
+        if blocks_per_bucket < 1:
+            raise ValueError(
+                "blocks_per_bucket must be 1 or greater. "
+                "Invalid value: %s" % (blocks_per_bucket))
+        if heap_base < 2:
+            raise ValueError(
+                "heap base must be 2 or greater. Invalid value: %s"
+                % (heap_base))
+
+        vheap = SizedVirtualHeap(
+            heap_base,
+            heap_height,
+            blocks_per_bucket=blocks_per_bucket)
+
+        user_header_data = kwds.pop('header_data', bytes())
+        if type(user_header_data) is not bytes:
+            raise TypeError(
+                "'header_data' must be of type bytes. "
+                "Invalid type: %s" % (type(user_header_data)))
+        kwds['header_data'] = \
+            struct.pack(cls._header_struct_string,
+                        heap_base,
+                        heap_height,
+                        blocks_per_bucket) + \
+            user_header_data
+
+        return EncryptedHeapStorage(
+            EncryptedBlockStorage.setup(
+                storage_name,
+                vheap.blocks_per_bucket * block_size,
+                vheap.bucket_count(),
+                **kwds))
+
+    #@property
+    #def header_data(...)
+
+    #@property
+    #def bucket_count(...)
+
+    #@property
+    #def bucket_size(...)
+
+    #@property
+    #def blocks_per_bucket(...)
+
+    #@property
+    #def storage_name(...)
+
+    #@property
+    #def virtual_heap(...)
+
+    #@property
+    #def bucket_storage(...)
+
+    #def update_header_data(...)
+
+    #def close(...)
+
+    #def read_path(...)
+
+    #def write_path(...)
+
+    #@property
+    #def bytes_sent(...)
+
+    #@property
+    #def bytes_received(...)