1use crate::{
2 backend::{TeeBackend, WrappedKey},
3 cache::SecureCache,
4 error::Result,
5 recovery::{BackupBundle, RecoveryStrategy},
6 security_level::SecurityLevel,
7};
8use serde::{Deserialize, Serialize};
9
10pub struct HydeContext {
12 backend: Box<dyn TeeBackend>,
13 security_level: SecurityLevel,
14 cache: Option<SecureCache>,
15}
16
17#[derive(Debug, Clone)]
18pub enum FallbackPolicy {
19 Deny,
21 Warn,
23 Software,
25}
26
27impl HydeContext {
28 pub fn with_backend(backend: Box<dyn TeeBackend>) -> Result<Self> {
31 Self::with_backend_and_security(backend, SecurityLevel::Paranoid)
32 }
33
34 pub fn with_backend_and_security(
36 mut backend: Box<dyn TeeBackend>,
37 security_level: SecurityLevel,
38 ) -> Result<Self> {
39 backend.initialize_primary_key()?;
40
41 let cache = if security_level.caches_data_key() {
42 Some(SecureCache::new())
43 } else {
44 None
45 };
46
47 Ok(Self {
48 backend,
49 security_level,
50 cache,
51 })
52 }
53
54 pub fn protect(&mut self, data: &[u8]) -> Result<ProtectedData> {
57 let key = self.backend.generate_data_key()?;
58 let ciphertext = self.backend.seal(&key, data)?;
59 Ok(ProtectedData {
60 key,
61 ciphertext,
62 version: 1,
63 })
64 }
65
66 pub fn unprotect(&mut self, protected: &ProtectedData) -> Result<Vec<u8>> {
68 self.unprotect_with_level(protected, self.security_level)
69 }
70
71 pub fn unprotect_with(
75 &mut self,
76 protected: &ProtectedData,
77 level: SecurityLevel,
78 ) -> Result<Vec<u8>> {
79 self.unprotect_with_level(protected, level)
80 }
81
82 fn unprotect_with_level(
83 &mut self,
84 protected: &ProtectedData,
85 level: SecurityLevel,
86 ) -> Result<Vec<u8>> {
87 match level {
88 SecurityLevel::Paranoid => {
89 self.backend.unseal(&protected.key, &protected.ciphertext)
91 }
92 SecurityLevel::Standard { ttl } => {
93 self.unprotect_standard(protected, ttl)
94 }
95 SecurityLevel::Performance { ttl } => {
96 self.unprotect_performance(protected, ttl)
97 }
98 }
99 }
100
101 fn unprotect_standard(
102 &mut self,
103 protected: &ProtectedData,
104 ttl: std::time::Duration,
105 ) -> Result<Vec<u8>> {
106 let cache = self.cache.get_or_insert_with(SecureCache::new);
107
108 if let Some(data_key) = cache.get_data_key(&protected.key.blob) {
110 let result = crate::passphrase::aes_gcm_decrypt(&data_key, &protected.ciphertext);
112 return result;
113 }
114
115 let plaintext = self.backend.unseal(&protected.key, &protected.ciphertext)?;
117
118 cache.insert_plaintext(
129 &protected.key.blob,
130 &protected.ciphertext,
131 plaintext.clone(),
132 ttl,
133 );
134
135 Ok(plaintext)
136 }
137
138 fn unprotect_performance(
139 &mut self,
140 protected: &ProtectedData,
141 ttl: std::time::Duration,
142 ) -> Result<Vec<u8>> {
143 let cache = self.cache.get_or_insert_with(SecureCache::new);
144
145 if let Some(plaintext) = cache.get_plaintext(&protected.key.blob, &protected.ciphertext) {
147 return Ok(plaintext);
148 }
149
150 let plaintext = self.backend.unseal(&protected.key, &protected.ciphertext)?;
152
153 cache.insert_plaintext(
155 &protected.key.blob,
156 &protected.ciphertext,
157 plaintext.clone(),
158 ttl,
159 );
160
161 Ok(plaintext)
162 }
163
164 pub fn flush_cache(&mut self) {
166 if let Some(cache) = &mut self.cache {
167 cache.flush();
168 }
169 }
170
171 pub fn set_security_level(&mut self, level: SecurityLevel) {
173 self.flush_cache();
174 self.security_level = level;
175
176 if level.caches_data_key() && self.cache.is_none() {
177 self.cache = Some(SecureCache::new());
178 } else if !level.caches_data_key() {
179 self.cache = None;
180 }
181 }
182
183 pub fn security_level(&self) -> SecurityLevel {
185 self.security_level
186 }
187
188 pub fn backup(
190 &self,
191 protected: &ProtectedData,
192 strategy: &dyn RecoveryStrategy,
193 secret: Option<&[u8]>,
194 ) -> Result<BackupBundle> {
195 strategy.backup(&protected.key, secret)
196 }
197
198 pub fn restore(
200 &self,
201 bundle: &BackupBundle,
202 ciphertext: &[u8],
203 strategy: &dyn RecoveryStrategy,
204 secret: &[u8],
205 ) -> Result<ProtectedData> {
206 let key = strategy.restore(bundle, secret)?;
207 Ok(ProtectedData {
208 key,
209 ciphertext: ciphertext.to_vec(),
210 version: 1,
211 })
212 }
213}
214
215#[derive(Debug, Clone, Serialize, Deserialize)]
218pub struct ProtectedData {
219 key: WrappedKey,
220 pub ciphertext: Vec<u8>,
221 version: u8,
222}