From cf2a472a34588c453f10efa0263ec51e0c860988 Mon Sep 17 00:00:00 2001 From: Justus Winter Date: Mon, 14 Feb 2022 16:31:11 +0100 Subject: openpgp: Decouple mem::Encrypted from OpenPGP's AEAD mechanism. - Use a custom schedule, which is a simple counter nonce, no AAD except for the final chunk which digests the plaintext size. --- openpgp/src/crypto/mem.rs | 61 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 43 insertions(+), 18 deletions(-) diff --git a/openpgp/src/crypto/mem.rs b/openpgp/src/crypto/mem.rs index fa2adb0b..d09eb3a8 100644 --- a/openpgp/src/crypto/mem.rs +++ b/openpgp/src/crypto/mem.rs @@ -213,7 +213,6 @@ impl fmt::Debug for Protected { #[derive(Clone, Debug)] pub struct Encrypted { ciphertext: Protected, - iv: Box<[u8]>, } assert_send_and_sync!(Encrypted); @@ -282,29 +281,15 @@ mod has_access_to_prekey { sk } - /// Returns the schedule for use with the AEAD encryption. - fn schedule(iv: &[u8]) -> impl aead::Schedule { - aead::AEDv1Schedule::new( - SYMMETRIC_ALGO, - AEAD_ALGO, - 4096, - iv).expect("valid parameters") - } - /// Encrypts the given chunk of memory. pub fn new(p: Protected) -> Self { - let mut iv = - vec![0; AEAD_ALGO.iv_size() - .expect("Mandatory algorithm unsupported")]; - crate::crypto::random(&mut iv); - let mut ciphertext = Vec::new(); { let mut encryptor = aead::Encryptor::new(SYMMETRIC_ALGO, AEAD_ALGO, 4096, - Self::schedule(&iv), + CounterSchedule::default(), Self::sealing_key(), &mut ciphertext) .expect("Mandatory algorithm unsupported"); @@ -314,7 +299,6 @@ mod has_access_to_prekey { Encrypted { ciphertext: ciphertext.into(), - iv: iv.into(), } } @@ -332,7 +316,7 @@ mod has_access_to_prekey { SYMMETRIC_ALGO, AEAD_ALGO, 4096, - Self::schedule(&self.iv), + CounterSchedule::default(), Self::sealing_key(), Box::new(ciphertext)) .expect("Mandatory algorithm unsupported"); @@ -342,6 +326,47 @@ mod has_access_to_prekey { fun(&plaintext) } } + + #[derive(Default)] + struct CounterSchedule {} + + impl aead::Schedule for CounterSchedule { + fn next_chunk(&self, index: u64, mut fun: F) -> R + where + F: FnMut(&[u8], &[u8]) -> R, + { + // The nonce is a simple counter. + let mut nonce_store = [0u8; aead::MAX_NONCE_LEN]; + let nonce_len = AEAD_ALGO.iv_size() + .expect("Mandatory algorithm unsupported"); + assert!(nonce_len >= 8); + let nonce = &mut nonce_store[..nonce_len]; + let index_be: [u8; 8] = index.to_be_bytes(); + nonce[nonce_len - 8..].copy_from_slice(&index_be); + + // No AAD. + fun(nonce, &[]) + } + + fn final_chunk(&self, index: u64, length: u64, mut fun: F) -> R + where + F: FnMut(&[u8], &[u8]) -> R + { + // The nonce is a simple counter. + let mut nonce_store = [0u8; aead::MAX_NONCE_LEN]; + let nonce_len = AEAD_ALGO.iv_size() + .expect("Mandatory algorithm unsupported"); + assert!(nonce_len >= 8); + let nonce = &mut nonce_store[..nonce_len]; + let index_be: [u8; 8] = index.to_be_bytes(); + nonce[nonce_len - 8..].copy_from_slice(&index_be); + + // Plaintext bytes as AAD to prevent truncation. + let aad: [u8; 8] = length.to_be_bytes(); + + fun(nonce, &aad) + } + } } /// Time-constant comparison. -- cgit v1.2.3