summaryrefslogtreecommitdiffstats
path: root/openpgp/src/crypto/backend/rust/aead.rs
diff options
context:
space:
mode:
Diffstat (limited to 'openpgp/src/crypto/backend/rust/aead.rs')
-rw-r--r--openpgp/src/crypto/backend/rust/aead.rs134
1 files changed, 134 insertions, 0 deletions
diff --git a/openpgp/src/crypto/backend/rust/aead.rs b/openpgp/src/crypto/backend/rust/aead.rs
new file mode 100644
index 00000000..ab2ca208
--- /dev/null
+++ b/openpgp/src/crypto/backend/rust/aead.rs
@@ -0,0 +1,134 @@
+//! Implementation of AEAD using pure Rust cryptographic libraries.
+
+use std::cmp;
+
+use cipher::{BlockCipher, NewBlockCipher};
+use cipher::block::Block;
+use cipher::consts::U16;
+use eax::online::{Eax, Encrypt, Decrypt};
+use generic_array::{ArrayLength, GenericArray};
+
+use crate::{Error, Result};
+use crate::crypto::aead::{Aead, CipherOp};
+use crate::seal;
+use crate::types::{AEADAlgorithm, SymmetricAlgorithm};
+
+trait GenericArrayExt {
+ const LEN: usize;
+}
+
+impl<T, N: ArrayLength<T>> GenericArrayExt for GenericArray<T, N> {
+ const LEN: usize = N::USIZE;
+}
+
+impl<Cipher> Aead for Eax<Cipher, Encrypt>
+where
+ Cipher: BlockCipher<BlockSize = U16> + NewBlockCipher + Clone,
+ Cipher::ParBlocks: ArrayLength<Block<Cipher>>,
+{
+ fn update(&mut self, ad: &[u8]) {
+ self.update_assoc(ad)
+ }
+
+ fn digest_size(&self) -> usize {
+ eax::Tag::LEN
+ }
+
+ fn digest(&mut self, digest: &mut [u8]) {
+ let tag = self.tag_clone();
+ digest[..tag.len()].copy_from_slice(&tag[..]);
+ }
+
+ fn encrypt(&mut self, dst: &mut [u8], src: &[u8]) {
+ let len = cmp::min(dst.len(), src.len());
+ dst[..len].copy_from_slice(&src[..len]);
+ Self::encrypt(self, &mut dst[..len])
+ }
+
+ fn decrypt(&mut self, _dst: &mut [u8], _src: &[u8]) {
+ panic!("AEAD decryption called in the encryption context")
+ }
+}
+
+impl<Cipher> Aead for Eax<Cipher, Decrypt>
+where
+ Cipher: BlockCipher<BlockSize = U16> + NewBlockCipher + Clone,
+ Cipher::ParBlocks: ArrayLength<Block<Cipher>>,
+{
+ fn update(&mut self, ad: &[u8]) {
+ self.update_assoc(ad)
+ }
+
+ fn digest_size(&self) -> usize {
+ eax::Tag::LEN
+ }
+
+ fn digest(&mut self, digest: &mut [u8]) {
+ let tag = self.tag_clone();
+ digest[..tag.len()].copy_from_slice(&tag[..]);
+ }
+
+ fn encrypt(&mut self, _dst: &mut [u8], _src: &[u8]) {
+ panic!("AEAD encryption called in the decryption context")
+ }
+
+ fn decrypt(&mut self, dst: &mut [u8], src: &[u8]) {
+ let len = core::cmp::min(dst.len(), src.len());
+ dst[..len].copy_from_slice(&src[..len]);
+ self.decrypt_unauthenticated_hazmat(&mut dst[..len])
+ }
+}
+
+impl<Cipher, Op> seal::Sealed for Eax<Cipher, Op>
+where
+ Cipher: BlockCipher<BlockSize = U16> + NewBlockCipher + Clone,
+ Cipher::ParBlocks: ArrayLength<Block<Cipher>>,
+ Op: eax::online::CipherOp,
+{}
+
+impl AEADAlgorithm {
+ pub(crate) fn context(
+ &self,
+ sym_algo: SymmetricAlgorithm,
+ key: &[u8],
+ nonce: &[u8],
+ op: CipherOp,
+ ) -> Result<Box<dyn Aead>> {
+ match self {
+ AEADAlgorithm::EAX => match sym_algo {
+ SymmetricAlgorithm::AES128 => match op {
+ CipherOp::Encrypt => Ok(Box::new(
+ Eax::<aes::Aes128, Encrypt>::with_key_and_nonce(key.into(), nonce.into()))),
+ CipherOp::Decrypt => Ok(Box::new(
+ Eax::<aes::Aes128, Decrypt>::with_key_and_nonce(key.into(), nonce.into()))),
+ }
+ SymmetricAlgorithm::AES192 => match op {
+ CipherOp::Encrypt => Ok(Box::new(
+ Eax::<aes::Aes192, Encrypt>::with_key_and_nonce(key.into(), nonce.into()))),
+ CipherOp::Decrypt => Ok(Box::new(
+ Eax::<aes::Aes192, Decrypt>::with_key_and_nonce(key.into(), nonce.into()))),
+ }
+ SymmetricAlgorithm::AES256 => match op {
+ CipherOp::Encrypt => Ok(Box::new(
+ Eax::<aes::Aes256, Encrypt>::with_key_and_nonce(key.into(), nonce.into()))),
+ CipherOp::Decrypt => Ok(Box::new(
+ Eax::<aes::Aes256, Decrypt>::with_key_and_nonce(key.into(), nonce.into()))),
+ }
+ | SymmetricAlgorithm::IDEA
+ | SymmetricAlgorithm::TripleDES
+ | SymmetricAlgorithm::CAST5
+ | SymmetricAlgorithm::Blowfish
+ | SymmetricAlgorithm::Twofish
+ | SymmetricAlgorithm::Camellia128
+ | SymmetricAlgorithm::Camellia192
+ | SymmetricAlgorithm::Camellia256
+ | SymmetricAlgorithm::Private(_)
+ | SymmetricAlgorithm::Unknown(_)
+ | SymmetricAlgorithm::Unencrypted =>
+ Err(Error::UnsupportedSymmetricAlgorithm(sym_algo).into()),
+ },
+ AEADAlgorithm::OCB | AEADAlgorithm::Private(_) | AEADAlgorithm::Unknown(_) =>
+ Err(Error::UnsupportedAEADAlgorithm(*self).into()),
+ }
+ }
+}