1use std::alloc::{alloc, Layout};
6use std::borrow::Cow;
7use std::convert::TryFrom;
8use std::fmt::{self, Debug, Formatter};
9use std::io::Error;
10use std::str::FromStr;
11use std::sync::Arc;
12
13use openssl::{rand, symm};
14
15pub const DATA_UNIT_LENGTH: usize = 16;
17pub const AES_XTS_IV_LENGTH: usize = 16;
19pub const AES_128_XTS_KEY_LENGTH: usize = 32;
21pub const AES_256_XTS_KEY_LENGTH: usize = 64;
23pub const AES_256_GCM_KEY_LENGTH: usize = 32;
25
26pub const PADDING_MAGIC_END: [u8; 2] = [0x78, 0x90];
28pub const PADDING_LENGTH: usize = 18;
30const DEFAULT_CE_KEY: [u8; 32] = [
33 0xac, 0xed, 0x14, 0x69, 0x94, 0x23, 0x1e, 0xca, 0x44, 0x8c, 0xed, 0x2f, 0x6b, 0x40, 0x0c, 0x00,
34 0xfd, 0xbb, 0x3f, 0xac, 0xdd, 0xc7, 0xd9, 0xee, 0x83, 0xf6, 0x5c, 0xd9, 0x3c, 0xaa, 0x28, 0x7c,
35];
36const DEFAULT_CE_KEY_64: [u8; 64] = [
37 0xac, 0xed, 0x14, 0x69, 0x94, 0x23, 0x1e, 0xca, 0x44, 0x8c, 0xed, 0x2f, 0x6b, 0x40, 0x0c, 0x00,
38 0xfd, 0xbb, 0x3f, 0xac, 0xdd, 0xc7, 0xd9, 0xee, 0x83, 0xf6, 0x5c, 0xd9, 0x3c, 0xaa, 0x28, 0x7c,
39 0xfd, 0xbb, 0x3f, 0xac, 0xdd, 0xc7, 0xd9, 0xee, 0x83, 0xf6, 0x5c, 0xd9, 0x3c, 0xaa, 0x28, 0x7c,
40 0xac, 0xed, 0x14, 0x69, 0x94, 0x23, 0x1e, 0xca, 0x44, 0x8c, 0xed, 0x2f, 0x6b, 0x40, 0x0c, 0x00,
41];
42
43#[repr(u32)]
45#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
46pub enum Algorithm {
47 #[default]
48 None = 0,
49 Aes128Xts = 1,
50 Aes256Xts = 2,
51 Aes256Gcm = 3,
52}
53
54impl Algorithm {
55 pub fn new_cipher(&self) -> Result<Cipher, Error> {
57 match self {
58 Algorithm::None => Ok(Cipher::None),
59 Algorithm::Aes128Xts => {
60 let cipher = symm::Cipher::aes_128_xts();
61 Ok(Cipher::Aes128Xts(cipher))
62 }
63 Algorithm::Aes256Xts => {
64 let cipher = symm::Cipher::aes_256_xts();
65 Ok(Cipher::Aes256Xts(cipher))
66 }
67 Algorithm::Aes256Gcm => {
68 let cipher = symm::Cipher::aes_256_gcm();
69 Ok(Cipher::Aes256Gcm(cipher))
70 }
71 }
72 }
73
74 pub fn is_encryption_enabled(&self) -> bool {
76 *self != Algorithm::None
77 }
78
79 pub fn is_aead(&self) -> bool {
81 match self {
82 Algorithm::None => false,
83 Algorithm::Aes128Xts => false,
84 Algorithm::Aes256Xts => false,
85 Algorithm::Aes256Gcm => true,
86 }
87 }
88
89 pub fn tag_size(&self) -> usize {
91 match self {
92 Algorithm::None => 0,
93 Algorithm::Aes128Xts => 0,
94 Algorithm::Aes256Xts => 0,
95 Algorithm::Aes256Gcm => 12,
96 }
97 }
98
99 pub fn key_length(&self) -> usize {
101 match self {
102 Algorithm::None => 0,
103 Algorithm::Aes128Xts => AES_128_XTS_KEY_LENGTH,
104 Algorithm::Aes256Xts => AES_256_XTS_KEY_LENGTH,
105 Algorithm::Aes256Gcm => AES_256_GCM_KEY_LENGTH,
106 }
107 }
108}
109
110impl fmt::Display for Algorithm {
111 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
112 write!(f, "{:?}", self)
113 }
114}
115
116impl FromStr for Algorithm {
117 type Err = Error;
118
119 fn from_str(s: &str) -> Result<Self, Self::Err> {
120 match s {
121 "none" => Ok(Self::None),
122 "aes128xts" => Ok(Self::Aes128Xts),
123 "aes256xts" => Ok(Self::Aes256Xts),
124 "aes256gcm" => Ok(Self::Aes256Gcm),
125 _ => Err(einval!("cypher algorithm should be none or aes_gcm")),
126 }
127 }
128}
129
130impl TryFrom<u32> for Algorithm {
131 type Error = ();
132
133 fn try_from(value: u32) -> Result<Self, Self::Error> {
134 if value == Algorithm::None as u32 {
135 Ok(Algorithm::None)
136 } else if value == Algorithm::Aes128Xts as u32 {
137 Ok(Algorithm::Aes128Xts)
138 } else if value == Algorithm::Aes256Xts as u32 {
139 Ok(Algorithm::Aes256Xts)
140 } else if value == Algorithm::Aes256Gcm as u32 {
141 Ok(Algorithm::Aes256Gcm)
142 } else {
143 Err(())
144 }
145 }
146}
147
148impl TryFrom<u64> for Algorithm {
149 type Error = ();
150
151 fn try_from(value: u64) -> Result<Self, Self::Error> {
152 if value == Algorithm::None as u64 {
153 Ok(Algorithm::None)
154 } else if value == Algorithm::Aes128Xts as u64 {
155 Ok(Algorithm::Aes128Xts)
156 } else if value == Algorithm::Aes256Xts as u64 {
157 Ok(Algorithm::Aes256Xts)
158 } else if value == Algorithm::Aes256Gcm as u64 {
159 Ok(Algorithm::Aes256Gcm)
160 } else {
161 Err(())
162 }
163 }
164}
165
166#[derive(Default)]
168pub enum Cipher {
169 #[default]
170 None,
171 Aes128Xts(symm::Cipher),
172 Aes256Xts(symm::Cipher),
173 Aes256Gcm(symm::Cipher),
174}
175
176impl Debug for Cipher {
177 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
178 match self {
179 Cipher::None => write!(f, "cipher: none"),
180 Cipher::Aes128Xts(_) => write!(f, "cypher: aes128_xts"),
181 Cipher::Aes256Xts(_) => write!(f, "cypher: aes256_xts"),
182 Cipher::Aes256Gcm(_) => write!(f, "cipher: aes256_gcm"),
183 }
184 }
185}
186
187impl Cipher {
188 pub fn encrypt<'a>(
193 &self,
194 key: &[u8],
195 iv: Option<&[u8]>,
196 data: &'a [u8],
197 ) -> Result<Cow<'a, [u8]>, Error> {
198 match self {
199 Cipher::None => Ok(Cow::from(data)),
200 Cipher::Aes128Xts(cipher) => {
201 assert_eq!(key.len(), AES_128_XTS_KEY_LENGTH);
202 let mut buf;
203 let data = if data.len() >= DATA_UNIT_LENGTH {
204 data
205 } else {
206 let val = (DATA_UNIT_LENGTH - data.len()) as u8;
210 buf = [val; PADDING_LENGTH];
211 buf[..data.len()].copy_from_slice(data);
212 buf[DATA_UNIT_LENGTH..PADDING_LENGTH].copy_from_slice(&PADDING_MAGIC_END);
213 &buf
214 };
215 Self::cipher(*cipher, symm::Mode::Encrypt, key, iv, data)
216 .map(Cow::from)
217 .map_err(|e| eother!(format!("failed to encrypt data, {}", e)))
218 }
219 Cipher::Aes256Xts(cipher) => {
220 assert_eq!(key.len(), AES_256_XTS_KEY_LENGTH);
221 let mut buf;
222 let data = if data.len() >= DATA_UNIT_LENGTH {
223 data
224 } else {
225 let val = (DATA_UNIT_LENGTH - data.len()) as u8;
226 buf = [val; PADDING_LENGTH];
227 buf[..data.len()].copy_from_slice(data);
228 buf[DATA_UNIT_LENGTH..PADDING_LENGTH].copy_from_slice(&PADDING_MAGIC_END);
229 &buf
230 };
231 Self::cipher(*cipher, symm::Mode::Encrypt, key, iv, data)
232 .map(Cow::from)
233 .map_err(|e| eother!(format!("failed to encrypt data, {}", e)))
234 }
235 Cipher::Aes256Gcm(_cipher) => {
236 Err(einval!("Cipher::encrypt() doesn't support Aes256Gcm"))
237 }
238 }
239 }
240
241 pub fn decrypt(&self, key: &[u8], iv: Option<&[u8]>, data: &[u8]) -> Result<Vec<u8>, Error> {
243 let mut data = match self {
244 Cipher::None => Ok(data.to_vec()),
245 Cipher::Aes128Xts(cipher) => Self::cipher(*cipher, symm::Mode::Decrypt, key, iv, data)
246 .map_err(|e| eother!(format!("failed to decrypt data, {}", e))),
247 Cipher::Aes256Xts(cipher) => Self::cipher(*cipher, symm::Mode::Decrypt, key, iv, data)
248 .map_err(|e| eother!(format!("failed to decrypt data, {}", e))),
249 Cipher::Aes256Gcm(_cipher) => {
250 Err(einval!("Cipher::decrypt() doesn't support Aes256Gcm"))
251 }
252 }?;
253
254 if data.len() == PADDING_LENGTH
256 && data[PADDING_LENGTH - PADDING_MAGIC_END.len()..PADDING_LENGTH] == PADDING_MAGIC_END
257 {
258 let val = data[DATA_UNIT_LENGTH - 1] as usize;
259 if val < DATA_UNIT_LENGTH {
260 data.truncate(DATA_UNIT_LENGTH - val);
261 } else {
262 return Err(einval!(format!(
263 "Cipher::decrypt: invalid padding data, value {}",
264 val,
265 )));
266 }
267 };
268
269 Ok(data)
270 }
271
272 pub fn encrypt_aead(
274 &self,
275 key: &[u8],
276 iv: Option<&[u8]>,
277 data: &[u8],
278 tag: &mut [u8],
279 ) -> Result<Vec<u8>, Error> {
280 match self {
281 Cipher::Aes256Gcm(cipher) => symm::encrypt_aead(*cipher, key, iv, &[], data, tag)
282 .map_err(|e| eother!(format!("failed to encrypt data, {}", e))),
283 _ => Err(einval!("invalid algorithm for encrypt_aead()")),
284 }
285 }
286
287 pub fn decrypt_aead(
289 &self,
290 key: &[u8],
291 iv: Option<&[u8]>,
292 data: &[u8],
293 tag: &[u8],
294 ) -> Result<Vec<u8>, Error> {
295 match self {
296 Cipher::Aes256Gcm(cipher) => symm::decrypt_aead(*cipher, key, iv, &[], data, tag)
297 .map_err(|e| eother!(format!("failed to encrypt data, {}", e))),
298 _ => Err(einval!("invalid algorithm for decrypt_aead()")),
299 }
300 }
301
302 pub fn tag_size(&self) -> usize {
304 match self {
305 Cipher::Aes256Gcm(_) => 12,
306 _ => 0,
307 }
308 }
309
310 pub fn encrypted_size(&self, plaintext_size: usize) -> usize {
312 match self {
313 Cipher::None => plaintext_size,
314 Cipher::Aes128Xts(_) | Cipher::Aes256Xts(_) => {
315 if plaintext_size < DATA_UNIT_LENGTH {
316 DATA_UNIT_LENGTH
317 } else {
318 plaintext_size
319 }
320 }
321 Cipher::Aes256Gcm(_) => {
322 assert!(plaintext_size.checked_add(12).is_some());
323 plaintext_size + 12
324 }
325 }
326 }
327
328 pub fn tweak_key_for_xts(key: &[u8]) -> Cow<[u8]> {
330 let len = key.len() >> 1;
331 if key[..len] == key[len..] {
332 let mut buf = if key[len] == 0xa5 {
333 vec![0x5a; key.len()]
334 } else {
335 vec![0xa5; key.len()]
336 };
337 buf[len..].copy_from_slice(&key[len..]);
338 Cow::from(buf)
339 } else {
340 Cow::from(key)
341 }
342 }
343
344 fn cipher(
345 t: symm::Cipher,
346 mode: symm::Mode,
347 key: &[u8],
348 iv: Option<&[u8]>,
349 data: &[u8],
350 ) -> Result<Vec<u8>, Error> {
351 let mut c = symm::Crypter::new(t, mode, key, iv)?;
352 let mut out = alloc_buf(data.len() + t.block_size());
353 let count = c.update(data, &mut out)?;
354 let rest = c.finalize(&mut out[count..])?;
355 out.truncate(count + rest);
356 Ok(out)
357 }
358
359 pub fn generate_random_key(cipher_algo: Algorithm) -> Result<Vec<u8>, Error> {
360 let length = cipher_algo.key_length();
361 let mut buf = vec![0u8; length];
362 if let Err(e) = rand::rand_bytes(&mut buf) {
363 Err(eother!(format!(
364 "failed to generate key for {}, {}",
365 cipher_algo, e
366 )))
367 } else {
368 Ok(Self::tweak_key_for_xts(&buf).to_vec())
369 }
370 }
371
372 pub fn generate_random_iv() -> Result<Vec<u8>, Error> {
373 let mut buf = vec![0u8; AES_XTS_IV_LENGTH];
374 if let Err(e) = rand::rand_bytes(&mut buf) {
375 Err(eother!(format!("failed to generate iv, {}", e)))
376 } else {
377 Ok(buf)
378 }
379 }
380}
381
382#[derive(Default, Debug, Clone)]
384pub struct CipherContext {
385 key: Vec<u8>,
386 iv: Vec<u8>,
387 convergent_encryption: bool,
388 cipher_algo: Algorithm,
389}
390
391impl CipherContext {
392 pub fn new(
394 key: Vec<u8>,
395 iv: Vec<u8>,
396 convergent_encryption: bool,
397 cipher_algo: Algorithm,
398 ) -> Result<Self, Error> {
399 let key_length = key.len();
400 if key_length != cipher_algo.key_length() {
401 return Err(einval!(format!(
402 "invalid key length {} for {} encryption",
403 key_length, cipher_algo
404 )));
405 } else if key[0..key_length >> 1] == key[key_length >> 1..key_length] {
406 return Err(einval!("invalid symmetry key for encryption"));
407 }
408
409 Ok(CipherContext {
410 key,
411 iv,
412 convergent_encryption,
413 cipher_algo,
414 })
415 }
416
417 pub fn generate_cipher_meta<'a>(&'a self, data: &'a [u8]) -> (&'a [u8], Vec<u8>) {
419 let length = data.len();
420 assert_eq!(length, self.cipher_algo.key_length());
421 let iv = vec![0u8; AES_XTS_IV_LENGTH];
422 if self.convergent_encryption {
423 if length == AES_128_XTS_KEY_LENGTH && data[0..length >> 1] == data[length >> 1..length]
424 {
425 (&DEFAULT_CE_KEY, iv)
426 } else if length == AES_256_XTS_KEY_LENGTH
427 && data[0..length >> 1] == data[length >> 1..length]
428 {
429 (&DEFAULT_CE_KEY_64, iv)
430 } else {
431 (data, iv)
432 }
433 } else {
434 (&self.key, iv)
435 }
436 }
437
438 pub fn get_cipher_meta(&self) -> (&[u8], &[u8]) {
440 (&self.key, &self.iv)
441 }
442}
443
444fn alloc_buf(size: usize) -> Vec<u8> {
446 assert!(size < isize::MAX as usize);
447 let layout = Layout::from_size_align(size, 0x1000)
448 .unwrap()
449 .pad_to_align();
450 let ptr = unsafe { alloc(layout) };
451 unsafe { Vec::from_raw_parts(ptr, size, layout.size()) }
452}
453
454pub fn encrypt_with_context<'a>(
456 data: &'a [u8],
457 cipher_obj: &Arc<Cipher>,
458 cipher_ctx: &Option<CipherContext>,
459 encrypted: bool,
460) -> Result<Cow<'a, [u8]>, Error> {
461 if encrypted {
462 if let Some(cipher_ctx) = cipher_ctx {
463 let (key, iv) = cipher_ctx.get_cipher_meta();
464 Ok(cipher_obj.encrypt(key, Some(iv), data)?)
465 } else {
466 Err(einval!("the encrypt context can not be none"))
467 }
468 } else {
469 Ok(Cow::Borrowed(data))
470 }
471}
472
473pub fn decrypt_with_context<'a>(
475 data: &'a [u8],
476 cipher_obj: &Arc<Cipher>,
477 cipher_ctx: &Option<CipherContext>,
478 encrypted: bool,
479) -> Result<Cow<'a, [u8]>, Error> {
480 if encrypted {
481 if let Some(cipher_ctx) = cipher_ctx {
482 let (key, iv) = cipher_ctx.get_cipher_meta();
483 Ok(Cow::from(cipher_obj.decrypt(key, Some(iv), data)?))
484 } else {
485 Err(einval!("the decrypt context can not be none"))
486 }
487 } else {
488 Ok(Cow::Borrowed(data))
489 }
490}
491
492#[cfg(test)]
493mod tests {
494 use super::*;
495
496 #[test]
497 fn test_aes_128_xts_encrypt() {
498 let mut key = [0xcu8; 32];
499 key[31] = 0xa;
500
501 let cipher = Algorithm::Aes128Xts.new_cipher().unwrap();
502 assert_eq!(cipher.encrypted_size(1), 16);
503 assert_eq!(cipher.encrypted_size(16), 16);
504 assert_eq!(cipher.encrypted_size(17), 17);
505
506 let ciphertext1 = cipher
507 .encrypt(key.as_slice(), Some(&[0u8; 16]), b"1")
508 .unwrap();
509 let ciphertext2 = cipher
510 .encrypt(key.as_slice(), Some(&[0u8; 16]), b"1")
511 .unwrap();
512 assert_eq!(ciphertext1, ciphertext2);
513 assert_eq!(ciphertext2.len(), PADDING_LENGTH);
514
515 let ciphertext3 = cipher
516 .encrypt(key.as_slice(), Some(&[0u8; 16]), b"11111111111111111")
517 .unwrap();
518 assert_eq!(ciphertext3.len(), 17);
519
520 let ciphertext4 = cipher
521 .encrypt(key.as_slice(), Some(&[1u8; 16]), b"11111111111111111")
522 .unwrap();
523 assert_eq!(ciphertext4.len(), 17);
524 assert_ne!(ciphertext4, ciphertext3);
525
526 let ciphertext5 = cipher
527 .encrypt(key.as_slice(), Some(&[1u8; 16]), b"21111111111111111")
528 .unwrap();
529 assert_eq!(ciphertext5.len(), 17);
530 assert_ne!(ciphertext5, ciphertext4);
531 }
532
533 #[test]
534 fn test_aes_256_xts_encrypt() {
535 let mut key = [0xcu8; 64];
536 key[31] = 0xa;
537
538 let cipher = Algorithm::Aes256Xts.new_cipher().unwrap();
539 let ciphertext1 = cipher
540 .encrypt(key.as_slice(), Some(&[0u8; 16]), b"1")
541 .unwrap();
542 let ciphertext2 = cipher
543 .encrypt(key.as_slice(), Some(&[0u8; 16]), b"1")
544 .unwrap();
545 assert_eq!(ciphertext1, ciphertext2);
546 assert_eq!(ciphertext2.len(), PADDING_LENGTH);
547
548 let ciphertext3 = cipher
549 .encrypt(key.as_slice(), Some(&[0u8; 16]), b"11111111111111111")
550 .unwrap();
551 assert_eq!(ciphertext3.len(), 17);
552
553 let ciphertext4 = cipher
554 .encrypt(key.as_slice(), Some(&[1u8; 16]), b"11111111111111111")
555 .unwrap();
556 assert_eq!(ciphertext4.len(), 17);
557 assert_ne!(ciphertext4, ciphertext3);
558
559 let ciphertext5 = cipher
560 .encrypt(key.as_slice(), Some(&[1u8; 16]), b"21111111111111111")
561 .unwrap();
562 assert_eq!(ciphertext5.len(), 17);
563 assert_ne!(ciphertext5, ciphertext4);
564 }
565
566 #[test]
567 fn test_aes_128_xts_decrypt() {
568 let mut key = [0xcu8; 32];
569 key[31] = 0xa;
570
571 let cipher = Algorithm::Aes128Xts.new_cipher().unwrap();
572 let ciphertext1 = cipher
573 .encrypt(key.as_slice(), Some(&[0u8; 16]), b"1")
574 .unwrap();
575 let plaintext1 = cipher
576 .decrypt(key.as_slice(), Some(&[0u8; 16]), &ciphertext1)
577 .unwrap();
578 assert_eq!(&plaintext1, b"1");
579
580 let ciphertext2 = cipher
581 .encrypt(key.as_slice(), Some(&[0u8; 16]), b"11111111111111111")
582 .unwrap();
583 let plaintext2 = cipher
584 .decrypt(key.as_slice(), Some(&[0u8; 16]), &ciphertext2)
585 .unwrap();
586 assert_eq!(&plaintext2, b"11111111111111111");
587
588 let ciphertext3 = cipher
589 .encrypt(key.as_slice(), Some(&[1u8; 16]), b"11111111111111111")
590 .unwrap();
591 let plaintext3 = cipher
592 .decrypt(key.as_slice(), Some(&[1u8; 16]), &ciphertext3)
593 .unwrap();
594 assert_eq!(&plaintext3, b"11111111111111111");
595 }
596
597 #[test]
598 fn test_aes_256_xts_decrypt() {
599 let mut key = [0xcu8; 64];
600 key[31] = 0xa;
601
602 let cipher = Algorithm::Aes256Xts.new_cipher().unwrap();
603 let ciphertext1 = cipher
604 .encrypt(key.as_slice(), Some(&[0u8; 16]), b"1")
605 .unwrap();
606 let plaintext1 = cipher
607 .decrypt(key.as_slice(), Some(&[0u8; 16]), &ciphertext1)
608 .unwrap();
609 assert_eq!(&plaintext1, b"1");
610
611 let ciphertext2 = cipher
612 .encrypt(key.as_slice(), Some(&[0u8; 16]), b"11111111111111111")
613 .unwrap();
614 let plaintext2 = cipher
615 .decrypt(key.as_slice(), Some(&[0u8; 16]), &ciphertext2)
616 .unwrap();
617 assert_eq!(&plaintext2, b"11111111111111111");
618
619 let ciphertext3 = cipher
620 .encrypt(key.as_slice(), Some(&[1u8; 16]), b"11111111111111111")
621 .unwrap();
622 let plaintext3 = cipher
623 .decrypt(key.as_slice(), Some(&[1u8; 16]), &ciphertext3)
624 .unwrap();
625 assert_eq!(&plaintext3, b"11111111111111111");
626 }
627
628 #[test]
629 fn test_aes_256_gcm() {
630 let key = [0xcu8; 32];
631 let mut tag = vec![0u8; 12];
632
633 let cipher = Algorithm::Aes256Gcm.new_cipher().unwrap();
634 assert_eq!(cipher.tag_size(), 12);
635 assert_eq!(cipher.encrypted_size(1), 13);
636
637 let ciphertext1 = cipher
638 .encrypt_aead(key.as_slice(), Some(&[0u8; 16]), b"1", &mut tag)
639 .unwrap();
640 assert_eq!(ciphertext1.len(), 1);
641 assert_eq!(tag.len(), 12);
642 let plaintext1 = cipher
643 .decrypt_aead(key.as_slice(), Some(&[0u8; 16]), &ciphertext1, &tag)
644 .unwrap();
645 assert_eq!(&plaintext1, b"1");
646
647 let ciphertext2 = cipher
648 .encrypt_aead(
649 key.as_slice(),
650 Some(&[0u8; 16]),
651 b"11111111111111111",
652 &mut tag,
653 )
654 .unwrap();
655 assert_eq!(ciphertext2.len(), 17);
656 assert_eq!(tag.len(), 12);
657 let plaintext2 = cipher
658 .decrypt_aead(key.as_slice(), Some(&[0u8; 16]), &ciphertext2, &tag)
659 .unwrap();
660 assert_eq!(&plaintext2, b"11111111111111111");
661
662 let ciphertext3 = cipher
663 .encrypt_aead(
664 key.as_slice(),
665 Some(&[1u8; 16]),
666 b"11111111111111111",
667 &mut tag,
668 )
669 .unwrap();
670 assert_ne!(ciphertext3, ciphertext2);
671 assert_eq!(ciphertext3.len(), 17);
672 assert_eq!(tag.len(), 12);
673 let plaintext3 = cipher
674 .decrypt_aead(key.as_slice(), Some(&[1u8; 16]), &ciphertext3, &tag)
675 .unwrap();
676 assert_eq!(&plaintext3, b"11111111111111111");
677 }
678
679 #[test]
680 fn test_tweak_key_for_xts() {
681 let buf = vec![0x0; 32];
682 let buf2 = Cipher::tweak_key_for_xts(&buf);
683 assert_eq!(buf2[0], 0xa5);
684 assert_eq!(buf2[16], 0x0);
685
686 let buf = vec![0xa5; 32];
687 let buf2 = Cipher::tweak_key_for_xts(&buf);
688 assert_eq!(buf2[0], 0x5a);
689 assert_eq!(buf2[16], 0xa5);
690 }
691
692 #[test]
693 fn test_attribute() {
694 let none = Algorithm::None.new_cipher().unwrap();
695 let aes128xts = Algorithm::Aes128Xts.new_cipher().unwrap();
696 let aes256xts = Algorithm::Aes256Xts.new_cipher().unwrap();
697 let aes256gcm = Algorithm::Aes256Gcm.new_cipher().unwrap();
698
699 assert!(!Algorithm::None.is_encryption_enabled());
700 assert!(Algorithm::Aes128Xts.is_encryption_enabled());
701 assert!(Algorithm::Aes256Xts.is_encryption_enabled());
702 assert!(Algorithm::Aes256Gcm.is_encryption_enabled());
703
704 assert!(!Algorithm::None.is_aead());
705 assert!(!Algorithm::Aes128Xts.is_aead());
706 assert!(!Algorithm::Aes256Xts.is_aead());
707 assert!(Algorithm::Aes256Gcm.is_aead());
708
709 assert_eq!(Algorithm::None.tag_size(), 0);
710 assert_eq!(Algorithm::Aes128Xts.tag_size(), 0);
711 assert_eq!(Algorithm::Aes256Xts.tag_size(), 0);
712 assert_eq!(Algorithm::Aes256Gcm.tag_size(), 12);
713
714 assert_eq!(Algorithm::None.key_length(), 0);
715 assert_eq!(Algorithm::Aes128Xts.key_length(), AES_128_XTS_KEY_LENGTH);
716 assert_eq!(Algorithm::Aes256Xts.key_length(), AES_256_XTS_KEY_LENGTH);
717 assert_eq!(Algorithm::Aes256Gcm.key_length(), AES_256_GCM_KEY_LENGTH);
718
719 print!("{}", Algorithm::Aes128Xts);
720 assert!(Algorithm::from_str("none").is_ok());
721 assert!(Algorithm::from_str("aes128xts").is_ok());
722 assert!(Algorithm::from_str("aes256xts").is_ok());
723 assert!(Algorithm::from_str("aes256gcm").is_ok());
724 assert!(Algorithm::from_str("non-exist").is_err());
725
726 assert!(Algorithm::try_from(Algorithm::None as u32).is_ok());
727 assert!(Algorithm::try_from(Algorithm::Aes128Xts as u32).is_ok());
728 assert!(Algorithm::try_from(Algorithm::Aes256Xts as u32).is_ok());
729 assert!(Algorithm::try_from(Algorithm::Aes256Gcm as u32).is_ok());
730 assert!(Algorithm::try_from(u32::MAX).is_err());
731
732 assert!(Algorithm::try_from(Algorithm::None as u64).is_ok());
733 assert!(Algorithm::try_from(Algorithm::Aes128Xts as u64).is_ok());
734 assert!(Algorithm::try_from(Algorithm::Aes256Xts as u64).is_ok());
735 assert!(Algorithm::try_from(Algorithm::Aes256Gcm as u64).is_ok());
736 assert!(Algorithm::try_from(u64::MAX).is_err());
737
738 println!("{:?},{:?},{:?},{:?}", none, aes128xts, aes256xts, aes256gcm);
739 }
740
741 #[test]
742 fn test_crypt_with_context() {
743 let error_key = [0xcu8, 64];
744 let symmetry_key = [0xcu8, 32];
745 let mut key = [0xcu8; 32];
746 key[31] = 0xa;
747 let iv = [0u8; 16];
748 let data = b"11111111111111111";
749 assert!(
751 CipherContext::new(error_key.to_vec(), iv.to_vec(), true, Algorithm::Aes128Xts)
752 .is_err()
753 );
754 assert!(CipherContext::new(
756 symmetry_key.to_vec(),
757 iv.to_vec(),
758 true,
759 Algorithm::Aes128Xts
760 )
761 .is_err());
762
763 let ctx =
765 CipherContext::new(key.to_vec(), iv.to_vec(), false, Algorithm::Aes128Xts).unwrap();
766 let obj = Arc::new(Algorithm::Aes128Xts.new_cipher().unwrap());
767 assert!(encrypt_with_context(data, &obj, &None, true).is_err());
768 assert!(decrypt_with_context(b"somedata", &obj, &None, true).is_err());
769
770 let no_change = encrypt_with_context(data, &obj, &Some(ctx.clone()), false).unwrap();
772 assert_eq!(no_change.clone().into_owned(), data);
773 let bind = no_change.into_owned();
774 let plain_text_no_change =
775 decrypt_with_context(&bind, &obj, &Some(ctx.clone()), false).unwrap();
776 assert_eq!(plain_text_no_change.into_owned(), data);
777
778 let encrypt_text = encrypt_with_context(data, &obj, &Some(ctx.clone()), true).unwrap();
780 let bind = encrypt_text.into_owned();
781 let plain_text = decrypt_with_context(&bind, &obj, &Some(ctx), true).unwrap();
782 assert_eq!(&plain_text.into_owned(), data);
783 }
784
785 fn test_gen_key(convergent_encryption: bool) {
786 let mut key = [0xcu8; 32];
787 key[31] = 0xa;
788 let iv = [0u8; 16];
789 let data = b"11111111111111111";
790 let ctx = CipherContext::new(
791 key.to_vec(),
792 iv.to_vec(),
793 convergent_encryption,
794 Algorithm::Aes128Xts,
795 )
796 .unwrap();
797 let obj = Arc::new(Algorithm::Aes128Xts.new_cipher().unwrap());
798 let (gen_key, gen_iv) = ctx.generate_cipher_meta(&key);
799 let ciphertext = obj.encrypt(gen_key, Some(&gen_iv), data).unwrap();
800 let plaintext = obj.decrypt(gen_key, Some(&gen_iv), &ciphertext).unwrap();
801 assert_eq!(&plaintext, data);
802 }
803
804 #[test]
805 fn test_generate_cipher_meta() {
806 test_gen_key(true);
807 test_gen_key(false);
808 }
809}