]> git.proxmox.com Git - proxmox-backup.git/blame - pbs-client/src/tools/key_source.rs
auth: add locking to `PbsAuthenticator` to avoid race conditions
[proxmox-backup.git] / pbs-client / src / tools / key_source.rs
CommitLineData
2711e94e 1use std::io::{IsTerminal, Read};
bdfa6370
TL
2use std::os::unix::io::{FromRawFd, RawFd};
3use std::path::PathBuf;
ff8945fd
SR
4
5use anyhow::{bail, format_err, Error};
6use serde_json::Value;
7
6ef1b649 8use proxmox_schema::*;
bdfa6370
TL
9use proxmox_sys::fs::file_get_contents;
10use proxmox_sys::linux::tty;
ff8945fd 11
2b7f8dd5 12use pbs_api_types::CryptMode;
ff8945fd
SR
13
14pub const DEFAULT_ENCRYPTION_KEY_FILE_NAME: &str = "encryption-key.json";
15pub const DEFAULT_MASTER_PUBKEY_FILE_NAME: &str = "master-public.pem";
16
17pub const KEYFILE_SCHEMA: Schema =
18 StringSchema::new("Path to encryption key. All data will be encrypted using this key.")
19 .schema();
20
21pub const KEYFD_SCHEMA: Schema =
22 IntegerSchema::new("Pass an encryption key via an already opened file descriptor.")
23 .minimum(0)
24 .schema();
25
26pub const MASTER_PUBKEY_FILE_SCHEMA: Schema = StringSchema::new(
27 "Path to master public key. The encryption key used for a backup will be encrypted using this key and appended to the backup.")
28 .schema();
29
30pub const MASTER_PUBKEY_FD_SCHEMA: Schema =
31 IntegerSchema::new("Pass a master public key via an already opened file descriptor.")
32 .minimum(0)
33 .schema();
34
35#[derive(Clone, Debug, Eq, PartialEq)]
36pub enum KeySource {
37 DefaultKey,
38 Fd,
39 Path(String),
40}
41
42pub fn format_key_source(source: &KeySource, key_type: &str) -> String {
43 match source {
44 KeySource::DefaultKey => format!("Using default {} key..", key_type),
45 KeySource::Fd => format!("Using {} key from file descriptor..", key_type),
46 KeySource::Path(path) => format!("Using {} key from '{}'..", key_type, path),
47 }
48}
49
50#[derive(Clone, Debug, Eq, PartialEq)]
51pub struct KeyWithSource {
52 pub source: KeySource,
53 pub key: Vec<u8>,
54}
55
56impl KeyWithSource {
57 pub fn from_fd(key: Vec<u8>) -> Self {
58 Self {
59 source: KeySource::Fd,
60 key,
61 }
62 }
63
64 pub fn from_default(key: Vec<u8>) -> Self {
65 Self {
66 source: KeySource::DefaultKey,
67 key,
68 }
69 }
70
71 pub fn from_path(path: String, key: Vec<u8>) -> Self {
72 Self {
73 source: KeySource::Path(path),
74 key,
75 }
76 }
77}
78
79#[derive(Debug, Eq, PartialEq)]
80pub struct CryptoParams {
81 pub mode: CryptMode,
82 pub enc_key: Option<KeyWithSource>,
83 // FIXME switch to openssl::rsa::rsa<openssl::pkey::Public> once that is Eq?
84 pub master_pubkey: Option<KeyWithSource>,
85}
86
87pub fn crypto_parameters(param: &Value) -> Result<CryptoParams, Error> {
9d8ab627
SR
88 do_crypto_parameters(param, false)
89}
90
91pub fn crypto_parameters_keep_fd(param: &Value) -> Result<CryptoParams, Error> {
92 do_crypto_parameters(param, true)
93}
94
95fn do_crypto_parameters(param: &Value, keep_keyfd_open: bool) -> Result<CryptoParams, Error> {
ff8945fd
SR
96 let keyfile = match param.get("keyfile") {
97 Some(Value::String(keyfile)) => Some(keyfile),
98 Some(_) => bail!("bad --keyfile parameter type"),
99 None => None,
100 };
101
102 let key_fd = match param.get("keyfd") {
103 Some(Value::Number(key_fd)) => Some(
bdfa6370
TL
104 RawFd::try_from(
105 key_fd
106 .as_i64()
107 .ok_or_else(|| format_err!("bad key fd: {:?}", key_fd))?,
ff8945fd 108 )
bdfa6370 109 .map_err(|err| format_err!("bad key fd: {:?}: {}", key_fd, err))?,
ff8945fd
SR
110 ),
111 Some(_) => bail!("bad --keyfd parameter type"),
112 None => None,
113 };
114
115 let master_pubkey_file = match param.get("master-pubkey-file") {
116 Some(Value::String(keyfile)) => Some(keyfile),
117 Some(_) => bail!("bad --master-pubkey-file parameter type"),
118 None => None,
119 };
120
121 let master_pubkey_fd = match param.get("master-pubkey-fd") {
122 Some(Value::Number(key_fd)) => Some(
bdfa6370
TL
123 RawFd::try_from(
124 key_fd
125 .as_i64()
126 .ok_or_else(|| format_err!("bad master public key fd: {:?}", key_fd))?,
ff8945fd 127 )
bdfa6370 128 .map_err(|err| format_err!("bad public master key fd: {:?}: {}", key_fd, err))?,
ff8945fd
SR
129 ),
130 Some(_) => bail!("bad --master-pubkey-fd parameter type"),
131 None => None,
132 };
133
134 let mode: Option<CryptMode> = match param.get("crypt-mode") {
38774184 135 Some(mode) => Some(serde::Deserialize::deserialize(mode)?),
ff8945fd
SR
136 None => None,
137 };
138
139 let key = match (keyfile, key_fd) {
140 (None, None) => None,
141 (Some(_), Some(_)) => bail!("--keyfile and --keyfd are mutually exclusive"),
142 (Some(keyfile), None) => Some(KeyWithSource::from_path(
143 keyfile.clone(),
144 file_get_contents(keyfile)?,
145 )),
146 (None, Some(fd)) => {
9d8ab627 147 let mut input = unsafe { std::fs::File::from_raw_fd(fd) };
ff8945fd 148 let mut data = Vec::new();
9d8ab627 149 let _len: usize = input.read_to_end(&mut data).map_err(|err| {
ff8945fd
SR
150 format_err!("error reading encryption key from fd {}: {}", fd, err)
151 })?;
9d8ab627
SR
152 if keep_keyfd_open {
153 // don't close fd if requested, and try to reset seek position
154 std::mem::forget(input);
bdfa6370
TL
155 unsafe {
156 libc::lseek(fd, 0, libc::SEEK_SET);
157 }
9d8ab627 158 }
ff8945fd
SR
159 Some(KeyWithSource::from_fd(data))
160 }
161 };
162
163 let master_pubkey = match (master_pubkey_file, master_pubkey_fd) {
164 (None, None) => None,
165 (Some(_), Some(_)) => bail!("--keyfile and --keyfd are mutually exclusive"),
166 (Some(keyfile), None) => Some(KeyWithSource::from_path(
167 keyfile.clone(),
168 file_get_contents(keyfile)?,
169 )),
170 (None, Some(fd)) => {
171 let input = unsafe { std::fs::File::from_raw_fd(fd) };
172 let mut data = Vec::new();
173 let _len: usize = { input }
174 .read_to_end(&mut data)
175 .map_err(|err| format_err!("error reading master key from fd {}: {}", fd, err))?;
176 Some(KeyWithSource::from_fd(data))
177 }
178 };
179
180 let res = match mode {
181 // no crypt mode, enable encryption if keys are available
182 None => match (key, master_pubkey) {
183 // only default keys if available
184 (None, None) => match read_optional_default_encryption_key()? {
185 None => CryptoParams { mode: CryptMode::None, enc_key: None, master_pubkey: None },
186 enc_key => {
187 let master_pubkey = read_optional_default_master_pubkey()?;
188 CryptoParams {
189 mode: CryptMode::Encrypt,
190 enc_key,
191 master_pubkey,
192 }
193 },
194 },
195
196 // explicit master key, default enc key needed
197 (None, master_pubkey) => match read_optional_default_encryption_key()? {
198 None => bail!("--master-pubkey-file/--master-pubkey-fd specified, but no key available"),
199 enc_key => {
200 CryptoParams {
201 mode: CryptMode::Encrypt,
202 enc_key,
203 master_pubkey,
204 }
205 },
206 },
207
208 // explicit keyfile, maybe default master key
209 (enc_key, None) => CryptoParams { mode: CryptMode::Encrypt, enc_key, master_pubkey: read_optional_default_master_pubkey()? },
210
211 // explicit keyfile and master key
212 (enc_key, master_pubkey) => CryptoParams { mode: CryptMode::Encrypt, enc_key, master_pubkey },
213 },
214
215 // explicitly disabled encryption
216 Some(CryptMode::None) => match (key, master_pubkey) {
217 // no keys => OK, no encryption
218 (None, None) => CryptoParams { mode: CryptMode::None, enc_key: None, master_pubkey: None },
219
220 // --keyfile and --crypt-mode=none
221 (Some(_), _) => bail!("--keyfile/--keyfd and --crypt-mode=none are mutually exclusive"),
222
223 // --master-pubkey-file and --crypt-mode=none
224 (_, Some(_)) => bail!("--master-pubkey-file/--master-pubkey-fd and --crypt-mode=none are mutually exclusive"),
225 },
226
227 // explicitly enabled encryption
228 Some(mode) => match (key, master_pubkey) {
229 // no key, maybe master key
230 (None, master_pubkey) => match read_optional_default_encryption_key()? {
231 None => bail!("--crypt-mode without --keyfile and no default key file available"),
232 enc_key => {
e10fccf5 233 log::info!("Encrypting with default encryption key!");
ff8945fd
SR
234 let master_pubkey = match master_pubkey {
235 None => read_optional_default_master_pubkey()?,
236 master_pubkey => master_pubkey,
237 };
238
239 CryptoParams {
240 mode,
241 enc_key,
242 master_pubkey,
243 }
244 },
245 },
246
247 // --keyfile and --crypt-mode other than none
248 (enc_key, master_pubkey) => {
249 let master_pubkey = match master_pubkey {
250 None => read_optional_default_master_pubkey()?,
251 master_pubkey => master_pubkey,
252 };
253
254 CryptoParams { mode, enc_key, master_pubkey }
255 },
256 },
257 };
258
259 Ok(res)
260}
261
262pub fn find_default_master_pubkey() -> Result<Option<PathBuf>, Error> {
263 super::find_xdg_file(
264 DEFAULT_MASTER_PUBKEY_FILE_NAME,
265 "default master public key file",
266 )
267}
268
269pub fn place_default_master_pubkey() -> Result<PathBuf, Error> {
270 super::place_xdg_file(
271 DEFAULT_MASTER_PUBKEY_FILE_NAME,
272 "default master public key file",
273 )
274}
275
276pub fn find_default_encryption_key() -> Result<Option<PathBuf>, Error> {
277 super::find_xdg_file(
278 DEFAULT_ENCRYPTION_KEY_FILE_NAME,
279 "default encryption key file",
280 )
281}
282
283pub fn place_default_encryption_key() -> Result<PathBuf, Error> {
284 super::place_xdg_file(
285 DEFAULT_ENCRYPTION_KEY_FILE_NAME,
286 "default encryption key file",
287 )
288}
289
290#[cfg(not(test))]
291pub(crate) fn read_optional_default_encryption_key() -> Result<Option<KeyWithSource>, Error> {
292 find_default_encryption_key()?
293 .map(|path| file_get_contents(path).map(KeyWithSource::from_default))
294 .transpose()
295}
296
297#[cfg(not(test))]
298pub(crate) fn read_optional_default_master_pubkey() -> Result<Option<KeyWithSource>, Error> {
299 find_default_master_pubkey()?
300 .map(|path| file_get_contents(path).map(KeyWithSource::from_default))
301 .transpose()
302}
303
304#[cfg(test)]
305static mut TEST_DEFAULT_ENCRYPTION_KEY: Result<Option<Vec<u8>>, Error> = Ok(None);
306
307#[cfg(test)]
308pub(crate) fn read_optional_default_encryption_key() -> Result<Option<KeyWithSource>, Error> {
309 // not safe when multiple concurrent test cases end up here!
310 unsafe {
311 match &TEST_DEFAULT_ENCRYPTION_KEY {
312 Ok(Some(key)) => Ok(Some(KeyWithSource::from_default(key.clone()))),
313 Ok(None) => Ok(None),
314 Err(_) => bail!("test error"),
315 }
316 }
317}
318
319#[cfg(test)]
320// not safe when multiple concurrent test cases end up here!
321pub(crate) unsafe fn set_test_encryption_key(value: Result<Option<Vec<u8>>, Error>) {
322 TEST_DEFAULT_ENCRYPTION_KEY = value;
323}
324
325#[cfg(test)]
326static mut TEST_DEFAULT_MASTER_PUBKEY: Result<Option<Vec<u8>>, Error> = Ok(None);
327
328#[cfg(test)]
329pub(crate) fn read_optional_default_master_pubkey() -> Result<Option<KeyWithSource>, Error> {
330 // not safe when multiple concurrent test cases end up here!
331 unsafe {
332 match &TEST_DEFAULT_MASTER_PUBKEY {
333 Ok(Some(key)) => Ok(Some(KeyWithSource::from_default(key.clone()))),
334 Ok(None) => Ok(None),
335 Err(_) => bail!("test error"),
336 }
337 }
338}
339
340#[cfg(test)]
341// not safe when multiple concurrent test cases end up here!
342pub(crate) unsafe fn set_test_default_master_pubkey(value: Result<Option<Vec<u8>>, Error>) {
343 TEST_DEFAULT_MASTER_PUBKEY = value;
344}
345
346pub fn get_encryption_key_password() -> Result<Vec<u8>, Error> {
347 // fixme: implement other input methods
348
16a01c19
DM
349 if let Some(password) = super::get_secret_from_env("PBS_ENCRYPTION_PASSWORD")? {
350 return Ok(password.as_bytes().to_vec());
ff8945fd
SR
351 }
352
353 // If we're on a TTY, query the user for a password
2711e94e 354 if std::io::stdin().is_terminal() {
dcf5a0f6 355 return tty::read_password("Encryption Key Password: ");
ff8945fd
SR
356 }
357
358 bail!("no password input mechanism available");
359}
360
a3399f43
WB
361#[cfg(test)]
362fn create_testdir(name: &str) -> Result<String, Error> {
4d04cd9a
WB
363 // FIXME:
364 //let mut testdir: PathBuf = format!("{}/testout", env!("CARGO_TARGET_TMPDIR")).into();
365 let mut testdir: PathBuf = "./target/testout".to_string().into();
a3399f43
WB
366 testdir.push(std::module_path!());
367 testdir.push(name);
368
369 let _ = std::fs::remove_dir_all(&testdir);
370 let _ = std::fs::create_dir_all(&testdir);
371
372 Ok(testdir.to_str().unwrap().to_string())
373}
374
ff8945fd
SR
375#[test]
376// WARNING: there must only be one test for crypto_parameters as the default key handling is not
377// safe w.r.t. concurrency
378fn test_crypto_parameters_handling() -> Result<(), Error> {
25877d05 379 use proxmox_sys::fs::{replace_file, CreateOptions};
bdfa6370 380 use serde_json::json;
ff8945fd 381
bdfa6370
TL
382 let some_key = vec![1; 1];
383 let default_key = vec![2; 1];
ff8945fd 384
bdfa6370
TL
385 let some_master_key = vec![3; 1];
386 let default_master_key = vec![4; 1];
ff8945fd 387
a3399f43
WB
388 let testdir = create_testdir("key_source")?;
389
390 let keypath = format!("{}/keyfile.test", testdir);
391 let master_keypath = format!("{}/masterkeyfile.test", testdir);
392 let invalid_keypath = format!("{}/invalid_keyfile.test", testdir);
ff8945fd
SR
393
394 let no_key_res = CryptoParams {
395 enc_key: None,
396 master_pubkey: None,
397 mode: CryptMode::None,
398 };
399 let some_key_res = CryptoParams {
400 enc_key: Some(KeyWithSource::from_path(
401 keypath.to_string(),
402 some_key.clone(),
403 )),
404 master_pubkey: None,
405 mode: CryptMode::Encrypt,
406 };
407 let some_key_some_master_res = CryptoParams {
408 enc_key: Some(KeyWithSource::from_path(
409 keypath.to_string(),
410 some_key.clone(),
411 )),
412 master_pubkey: Some(KeyWithSource::from_path(
413 master_keypath.to_string(),
414 some_master_key.clone(),
415 )),
416 mode: CryptMode::Encrypt,
417 };
418 let some_key_default_master_res = CryptoParams {
419 enc_key: Some(KeyWithSource::from_path(
420 keypath.to_string(),
421 some_key.clone(),
422 )),
423 master_pubkey: Some(KeyWithSource::from_default(default_master_key.clone())),
424 mode: CryptMode::Encrypt,
425 };
426
427 let some_key_sign_res = CryptoParams {
428 enc_key: Some(KeyWithSource::from_path(
429 keypath.to_string(),
430 some_key.clone(),
431 )),
432 master_pubkey: None,
433 mode: CryptMode::SignOnly,
434 };
435 let default_key_res = CryptoParams {
436 enc_key: Some(KeyWithSource::from_default(default_key.clone())),
437 master_pubkey: None,
438 mode: CryptMode::Encrypt,
439 };
440 let default_key_sign_res = CryptoParams {
441 enc_key: Some(KeyWithSource::from_default(default_key.clone())),
442 master_pubkey: None,
443 mode: CryptMode::SignOnly,
444 };
445
e0a19d33 446 replace_file(&keypath, &some_key, CreateOptions::default(), false)?;
bdfa6370
TL
447 replace_file(
448 &master_keypath,
449 &some_master_key,
450 CreateOptions::default(),
451 false,
452 )?;
ff8945fd
SR
453
454 // no params, no default key == no key
455 let res = crypto_parameters(&json!({}));
456 assert_eq!(res.unwrap(), no_key_res);
457
458 // keyfile param == key from keyfile
bdfa6370 459 let res = crypto_parameters(&json!({ "keyfile": keypath }));
ff8945fd
SR
460 assert_eq!(res.unwrap(), some_key_res);
461
462 // crypt mode none == no key
463 let res = crypto_parameters(&json!({"crypt-mode": "none"}));
464 assert_eq!(res.unwrap(), no_key_res);
465
466 // crypt mode encrypt/sign-only, no keyfile, no default key == Error
467 assert!(crypto_parameters(&json!({"crypt-mode": "sign-only"})).is_err());
468 assert!(crypto_parameters(&json!({"crypt-mode": "encrypt"})).is_err());
469
470 // crypt mode none with explicit key == Error
471 assert!(crypto_parameters(&json!({"crypt-mode": "none", "keyfile": keypath})).is_err());
472
473 // crypt mode sign-only/encrypt with keyfile == key from keyfile with correct mode
474 let res = crypto_parameters(&json!({"crypt-mode": "sign-only", "keyfile": keypath}));
475 assert_eq!(res.unwrap(), some_key_sign_res);
476 let res = crypto_parameters(&json!({"crypt-mode": "encrypt", "keyfile": keypath}));
477 assert_eq!(res.unwrap(), some_key_res);
478
479 // invalid keyfile parameter always errors
bdfa6370 480 assert!(crypto_parameters(&json!({ "keyfile": invalid_keypath })).is_err());
ff8945fd 481 assert!(crypto_parameters(&json!({"keyfile": invalid_keypath, "crypt-mode": "none"})).is_err());
bdfa6370
TL
482 assert!(
483 crypto_parameters(&json!({"keyfile": invalid_keypath, "crypt-mode": "sign-only"})).is_err()
484 );
485 assert!(
486 crypto_parameters(&json!({"keyfile": invalid_keypath, "crypt-mode": "encrypt"})).is_err()
487 );
ff8945fd
SR
488
489 // now set a default key
bdfa6370
TL
490 unsafe {
491 set_test_encryption_key(Ok(Some(default_key)));
492 }
ff8945fd
SR
493
494 // and repeat
495
496 // no params but default key == default key
497 let res = crypto_parameters(&json!({}));
498 assert_eq!(res.unwrap(), default_key_res);
499
500 // keyfile param == key from keyfile
bdfa6370 501 let res = crypto_parameters(&json!({ "keyfile": keypath }));
ff8945fd
SR
502 assert_eq!(res.unwrap(), some_key_res);
503
504 // crypt mode none == no key
505 let res = crypto_parameters(&json!({"crypt-mode": "none"}));
506 assert_eq!(res.unwrap(), no_key_res);
507
508 // crypt mode encrypt/sign-only, no keyfile, default key == default key with correct mode
509 let res = crypto_parameters(&json!({"crypt-mode": "sign-only"}));
510 assert_eq!(res.unwrap(), default_key_sign_res);
511 let res = crypto_parameters(&json!({"crypt-mode": "encrypt"}));
512 assert_eq!(res.unwrap(), default_key_res);
513
514 // crypt mode none with explicit key == Error
515 assert!(crypto_parameters(&json!({"crypt-mode": "none", "keyfile": keypath})).is_err());
516
517 // crypt mode sign-only/encrypt with keyfile == key from keyfile with correct mode
518 let res = crypto_parameters(&json!({"crypt-mode": "sign-only", "keyfile": keypath}));
519 assert_eq!(res.unwrap(), some_key_sign_res);
520 let res = crypto_parameters(&json!({"crypt-mode": "encrypt", "keyfile": keypath}));
521 assert_eq!(res.unwrap(), some_key_res);
522
523 // invalid keyfile parameter always errors
bdfa6370 524 assert!(crypto_parameters(&json!({ "keyfile": invalid_keypath })).is_err());
ff8945fd 525 assert!(crypto_parameters(&json!({"keyfile": invalid_keypath, "crypt-mode": "none"})).is_err());
bdfa6370
TL
526 assert!(
527 crypto_parameters(&json!({"keyfile": invalid_keypath, "crypt-mode": "sign-only"})).is_err()
528 );
529 assert!(
530 crypto_parameters(&json!({"keyfile": invalid_keypath, "crypt-mode": "encrypt"})).is_err()
531 );
ff8945fd
SR
532
533 // now make default key retrieval error
bdfa6370
TL
534 unsafe {
535 set_test_encryption_key(Err(format_err!("test error")));
536 }
ff8945fd
SR
537
538 // and repeat
539
540 // no params, default key retrieval errors == Error
541 assert!(crypto_parameters(&json!({})).is_err());
542
543 // keyfile param == key from keyfile
bdfa6370 544 let res = crypto_parameters(&json!({ "keyfile": keypath }));
ff8945fd
SR
545 assert_eq!(res.unwrap(), some_key_res);
546
547 // crypt mode none == no key
548 let res = crypto_parameters(&json!({"crypt-mode": "none"}));
549 assert_eq!(res.unwrap(), no_key_res);
550
551 // crypt mode encrypt/sign-only, no keyfile, default key error == Error
552 assert!(crypto_parameters(&json!({"crypt-mode": "sign-only"})).is_err());
553 assert!(crypto_parameters(&json!({"crypt-mode": "encrypt"})).is_err());
554
555 // crypt mode none with explicit key == Error
556 assert!(crypto_parameters(&json!({"crypt-mode": "none", "keyfile": keypath})).is_err());
557
558 // crypt mode sign-only/encrypt with keyfile == key from keyfile with correct mode
559 let res = crypto_parameters(&json!({"crypt-mode": "sign-only", "keyfile": keypath}));
560 assert_eq!(res.unwrap(), some_key_sign_res);
561 let res = crypto_parameters(&json!({"crypt-mode": "encrypt", "keyfile": keypath}));
562 assert_eq!(res.unwrap(), some_key_res);
563
564 // invalid keyfile parameter always errors
bdfa6370 565 assert!(crypto_parameters(&json!({ "keyfile": invalid_keypath })).is_err());
ff8945fd 566 assert!(crypto_parameters(&json!({"keyfile": invalid_keypath, "crypt-mode": "none"})).is_err());
bdfa6370
TL
567 assert!(
568 crypto_parameters(&json!({"keyfile": invalid_keypath, "crypt-mode": "sign-only"})).is_err()
569 );
570 assert!(
571 crypto_parameters(&json!({"keyfile": invalid_keypath, "crypt-mode": "encrypt"})).is_err()
572 );
ff8945fd
SR
573
574 // now remove default key again
bdfa6370
TL
575 unsafe {
576 set_test_encryption_key(Ok(None));
577 }
ff8945fd 578 // set a default master key
bdfa6370
TL
579 unsafe {
580 set_test_default_master_pubkey(Ok(Some(default_master_key)));
581 }
ff8945fd
SR
582
583 // and use an explicit master key
bdfa6370 584 assert!(crypto_parameters(&json!({ "master-pubkey-file": master_keypath })).is_err());
ff8945fd
SR
585 // just a default == no key
586 let res = crypto_parameters(&json!({}));
587 assert_eq!(res.unwrap(), no_key_res);
588
589 // keyfile param == key from keyfile
590 let res = crypto_parameters(&json!({"keyfile": keypath, "master-pubkey-file": master_keypath}));
591 assert_eq!(res.unwrap(), some_key_some_master_res);
592 // same with fallback to default master key
bdfa6370 593 let res = crypto_parameters(&json!({ "keyfile": keypath }));
ff8945fd
SR
594 assert_eq!(res.unwrap(), some_key_default_master_res);
595
596 // crypt mode none == error
bdfa6370
TL
597 assert!(crypto_parameters(
598 &json!({"crypt-mode": "none", "master-pubkey-file": master_keypath})
599 )
600 .is_err());
ff8945fd
SR
601 // with just default master key == no key
602 let res = crypto_parameters(&json!({"crypt-mode": "none"}));
603 assert_eq!(res.unwrap(), no_key_res);
604
605 // crypt mode encrypt without enc key == error
bdfa6370
TL
606 assert!(crypto_parameters(
607 &json!({"crypt-mode": "encrypt", "master-pubkey-file": master_keypath})
608 )
609 .is_err());
ff8945fd
SR
610 assert!(crypto_parameters(&json!({"crypt-mode": "encrypt"})).is_err());
611
612 // crypt mode none with explicit key == Error
bdfa6370
TL
613 assert!(crypto_parameters(
614 &json!({"crypt-mode": "none", "keyfile": keypath, "master-pubkey-file": master_keypath})
615 )
616 .is_err());
ff8945fd
SR
617 assert!(crypto_parameters(&json!({"crypt-mode": "none", "keyfile": keypath})).is_err());
618
619 // crypt mode encrypt with keyfile == key from keyfile with correct mode
bdfa6370
TL
620 let res = crypto_parameters(
621 &json!({"crypt-mode": "encrypt", "keyfile": keypath, "master-pubkey-file": master_keypath}),
622 );
ff8945fd
SR
623 assert_eq!(res.unwrap(), some_key_some_master_res);
624 let res = crypto_parameters(&json!({"crypt-mode": "encrypt", "keyfile": keypath}));
625 assert_eq!(res.unwrap(), some_key_default_master_res);
626
627 // invalid master keyfile parameter always errors when a key is passed, even with a valid
628 // default master key
bdfa6370
TL
629 assert!(
630 crypto_parameters(&json!({"keyfile": keypath, "master-pubkey-file": invalid_keypath}))
631 .is_err()
632 );
633 assert!(crypto_parameters(
634 &json!({"keyfile": keypath, "master-pubkey-file": invalid_keypath,"crypt-mode": "none"})
635 )
636 .is_err());
ff8945fd 637 assert!(crypto_parameters(&json!({"keyfile": keypath, "master-pubkey-file": invalid_keypath,"crypt-mode": "sign-only"})).is_err());
bdfa6370
TL
638 assert!(crypto_parameters(
639 &json!({"keyfile": keypath, "master-pubkey-file": invalid_keypath,"crypt-mode": "encrypt"})
640 )
641 .is_err());
ff8945fd
SR
642
643 Ok(())
644}