1use std::collections::HashMap;
2use std::fmt;
3
4use secrecy::{ExposeSecret, SecretString};
5use serde::{Deserialize, Serialize};
6use zeroize::{Zeroize, ZeroizeOnDrop};
7
8use super::redaction::{RedactionLevel, redact, redaction_level};
9
10#[derive(Debug, Serialize, Default, Clone)]
11pub struct TransitKeyParams {
12 #[serde(rename = "type", skip_serializing_if = "Option::is_none")]
13 pub key_type: Option<String>,
14 #[serde(skip_serializing_if = "Option::is_none")]
15 pub derived: Option<bool>,
16 #[serde(skip_serializing_if = "Option::is_none")]
17 pub convergent_encryption: Option<bool>,
18 #[serde(skip_serializing_if = "Option::is_none")]
19 pub exportable: Option<bool>,
20 #[serde(skip_serializing_if = "Option::is_none")]
21 pub allow_plaintext_backup: Option<bool>,
22 #[serde(skip_serializing_if = "Option::is_none")]
23 pub auto_rotate_period: Option<String>,
24 #[serde(skip_serializing_if = "Option::is_none")]
25 pub key_size: Option<u32>,
26}
27
28#[derive(Debug, Deserialize, Clone)]
29#[non_exhaustive]
30pub struct TransitKeyInfo {
31 #[serde(rename = "type")]
32 pub key_type: String,
33 pub deletion_allowed: bool,
34 pub derived: bool,
35 pub exportable: bool,
36 pub allow_plaintext_backup: bool,
37 #[serde(default)]
38 pub keys: HashMap<String, serde_json::Value>,
39 pub min_decryption_version: u64,
40 pub min_encryption_version: u64,
41 pub name: String,
42 pub supports_encryption: bool,
43 pub supports_decryption: bool,
44 pub supports_derivation: bool,
45 pub supports_signing: bool,
46 #[serde(default)]
47 pub auto_rotate_period: u64,
48 pub latest_version: u64,
49}
50
51#[derive(Debug, Serialize, Default, Clone)]
52pub struct TransitKeyConfig {
53 #[serde(skip_serializing_if = "Option::is_none")]
54 pub min_decryption_version: Option<u64>,
55 #[serde(skip_serializing_if = "Option::is_none")]
56 pub min_encryption_version: Option<u64>,
57 #[serde(skip_serializing_if = "Option::is_none")]
58 pub deletion_allowed: Option<bool>,
59 #[serde(skip_serializing_if = "Option::is_none")]
60 pub exportable: Option<bool>,
61 #[serde(skip_serializing_if = "Option::is_none")]
62 pub allow_plaintext_backup: Option<bool>,
63 #[serde(skip_serializing_if = "Option::is_none")]
64 pub auto_rotate_period: Option<String>,
65}
66
67#[derive(Debug, Deserialize)]
68pub(crate) struct TransitEncryptResponse {
69 pub ciphertext: String,
70}
71
72#[derive(Deserialize, Zeroize, ZeroizeOnDrop)]
73pub(crate) struct TransitDecryptResponse {
74 pub plaintext: SecretString,
75}
76
77impl fmt::Debug for TransitDecryptResponse {
78 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
79 f.debug_struct("TransitDecryptResponse")
80 .field("plaintext", &redact(self.plaintext.expose_secret()))
81 .finish()
82 }
83}
84
85#[derive(Debug, Deserialize)]
86pub(crate) struct TransitRewrapResponse {
87 pub ciphertext: String,
88}
89
90#[derive(Serialize, Zeroize, ZeroizeOnDrop)]
91pub struct TransitBatchPlaintext {
92 #[serde(serialize_with = "super::serde_secret::serialize")]
93 pub plaintext: SecretString,
94 #[serde(skip_serializing_if = "Option::is_none")]
95 pub context: Option<String>,
96}
97
98impl Clone for TransitBatchPlaintext {
99 fn clone(&self) -> Self {
100 Self {
101 plaintext: self.plaintext.clone(),
102 context: self.context.clone(),
103 }
104 }
105}
106
107impl fmt::Debug for TransitBatchPlaintext {
108 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
109 f.debug_struct("TransitBatchPlaintext")
110 .field("plaintext", &"[REDACTED]")
111 .field("context", &self.context)
112 .finish()
113 }
114}
115
116#[derive(Debug, Deserialize, Serialize, Clone)]
117pub struct TransitBatchCiphertext {
118 pub ciphertext: String,
119 #[serde(default, skip_serializing_if = "String::is_empty")]
120 pub error: String,
121}
122
123#[derive(Debug, Serialize, Default, Clone)]
124pub struct TransitSignParams {
125 #[serde(skip_serializing_if = "Option::is_none")]
126 pub hash_algorithm: Option<String>,
127 #[serde(skip_serializing_if = "Option::is_none")]
128 pub signature_algorithm: Option<String>,
129 #[serde(skip_serializing_if = "Option::is_none")]
130 pub marshaling_algorithm: Option<String>,
131 #[serde(skip_serializing_if = "Option::is_none")]
132 pub prehashed: Option<bool>,
133 #[serde(skip_serializing_if = "Option::is_none")]
134 pub salt_length: Option<String>,
135}
136
137#[derive(Debug, Deserialize)]
138pub(crate) struct TransitSignResponse {
139 pub signature: String,
140}
141
142#[derive(Debug, Deserialize)]
143pub(crate) struct TransitVerifyResponse {
144 pub valid: bool,
145}
146
147#[derive(Debug, Deserialize)]
148pub(crate) struct TransitHashResponse {
149 pub sum: String,
150}
151
152#[derive(Debug, Deserialize)]
153pub(crate) struct TransitHmacResponse {
154 pub hmac: String,
155}
156
157#[derive(Debug, Deserialize)]
158pub(crate) struct TransitRandomResponse {
159 pub random_bytes: String,
160}
161
162#[derive(Deserialize, Zeroize, ZeroizeOnDrop)]
163#[non_exhaustive]
164pub struct TransitDataKey {
165 pub ciphertext: String,
166 pub plaintext: Option<SecretString>,
167}
168
169impl Clone for TransitDataKey {
170 fn clone(&self) -> Self {
171 Self {
172 ciphertext: self.ciphertext.clone(),
173 plaintext: self.plaintext.clone(),
174 }
175 }
176}
177
178impl fmt::Debug for TransitDataKey {
179 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
180 f.debug_struct("TransitDataKey")
181 .field("ciphertext", &self.ciphertext)
182 .field(
183 "plaintext",
184 &self.plaintext.as_ref().map(|s| redact(s.expose_secret())),
185 )
186 .finish()
187 }
188}
189
190#[derive(Deserialize, Zeroize, ZeroizeOnDrop)]
191#[non_exhaustive]
192pub struct TransitExportedKey {
193 pub name: String,
194 #[zeroize(skip)]
195 pub keys: HashMap<String, SecretString>,
196 #[serde(rename = "type")]
197 pub key_type: String,
198}
199
200impl Clone for TransitExportedKey {
201 fn clone(&self) -> Self {
202 Self {
203 name: self.name.clone(),
204 keys: self.keys.clone(),
205 key_type: self.key_type.clone(),
206 }
207 }
208}
209
210impl fmt::Debug for TransitExportedKey {
211 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
212 match redaction_level() {
213 RedactionLevel::Full => {
214 let summary = format!("[REDACTED; {} versions]", self.keys.len());
215 f.debug_struct("TransitExportedKey")
216 .field("name", &self.name)
217 .field("keys", &summary)
218 .field("key_type", &self.key_type)
219 .finish()
220 }
221 _ => {
222 let map: HashMap<String, String> = self
223 .keys
224 .iter()
225 .map(|(k, v)| (k.clone(), redact(v.expose_secret())))
226 .collect();
227 f.debug_struct("TransitExportedKey")
228 .field("name", &self.name)
229 .field("keys", &map)
230 .field("key_type", &self.key_type)
231 .finish()
232 }
233 }
234 }
235}
236
237#[derive(Debug, Deserialize, Clone)]
238#[non_exhaustive]
239pub struct TransitCacheConfig {
240 pub size: u64,
241}
242
243#[derive(Debug, Deserialize)]
244pub(crate) struct TransitBatchEncryptResponse {
245 #[serde(default)]
246 pub batch_results: Vec<TransitBatchCiphertext>,
247}
248
249#[derive(Debug, Deserialize)]
250pub(crate) struct TransitBatchDecryptResponse {
251 #[serde(default)]
252 pub batch_results: Vec<TransitBatchDecryptItem>,
253}
254
255#[derive(Deserialize, Zeroize, ZeroizeOnDrop)]
256#[non_exhaustive]
257pub struct TransitBatchDecryptItem {
258 pub plaintext: Option<SecretString>,
259 #[serde(default)]
260 pub error: String,
261}
262
263impl Clone for TransitBatchDecryptItem {
264 fn clone(&self) -> Self {
265 Self {
266 plaintext: self.plaintext.clone(),
267 error: self.error.clone(),
268 }
269 }
270}
271
272impl fmt::Debug for TransitBatchDecryptItem {
273 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
274 f.debug_struct("TransitBatchDecryptItem")
275 .field(
276 "plaintext",
277 &self.plaintext.as_ref().map(|s| redact(s.expose_secret())),
278 )
279 .field("error", &self.error)
280 .finish()
281 }
282}
283
284#[derive(Deserialize, Zeroize, ZeroizeOnDrop)]
285pub(crate) struct TransitBackupResponse {
286 pub backup: SecretString,
287}
288
289impl fmt::Debug for TransitBackupResponse {
290 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291 f.debug_struct("TransitBackupResponse")
292 .field("backup", &redact(self.backup.expose_secret()))
293 .finish()
294 }
295}
296
297#[derive(Debug, Serialize, Clone)]
300pub struct TransitBatchSignInput {
301 pub input: String,
302 #[serde(skip_serializing_if = "Option::is_none")]
303 pub context: Option<String>,
304}
305
306#[derive(Debug, Deserialize, Clone)]
307#[non_exhaustive]
308pub struct TransitBatchSignResult {
309 pub signature: String,
310 #[serde(default)]
311 pub error: String,
312}
313
314#[derive(Debug, Serialize, Clone)]
315pub struct TransitBatchVerifyInput {
316 pub input: String,
317 pub signature: String,
318 #[serde(skip_serializing_if = "Option::is_none")]
319 pub context: Option<String>,
320}
321
322#[derive(Debug, Deserialize, Clone)]
323#[non_exhaustive]
324pub struct TransitBatchVerifyResult {
325 pub valid: bool,
326 #[serde(default)]
327 pub error: String,
328}
329
330#[derive(Debug, Deserialize)]
331pub(crate) struct TransitBatchSignResponse {
332 #[serde(default)]
333 pub batch_results: Vec<TransitBatchSignResult>,
334}
335
336#[derive(Debug, Deserialize)]
337pub(crate) struct TransitBatchVerifyResponse {
338 #[serde(default)]
339 pub batch_results: Vec<TransitBatchVerifyResult>,
340}