From bfbae0a1f9179b2a0b207f25aa6984beab4cec79 Mon Sep 17 00:00:00 2001 From: James Cape Date: Fri, 2 Sep 2022 16:03:00 -0700 Subject: [PATCH 1/3] Don't expose encryption w/ user-specified nonces, expose nonces when encrypting --- attest/ake/src/event.rs | 33 ++++++++++++++++++++++---------- attest/ake/src/shared.rs | 13 +++++++------ attest/ake/src/state.rs | 11 ++++++----- crypto/noise/src/cipher_state.rs | 19 +++++++++++++++++- 4 files changed, 54 insertions(+), 22 deletions(-) diff --git a/attest/ake/src/event.rs b/attest/ake/src/event.rs index c38277522b..1651b00297 100644 --- a/attest/ake/src/event.rs +++ b/attest/ake/src/event.rs @@ -354,32 +354,45 @@ impl MealyOutput for Vec {} /// A type similar to [`aead::Payload`] used to distinguish writer inputs from /// outputs when there's an explicit nonce. -pub struct NoncePlaintext<'aad, 'msg> { - pub aad: &'aad [u8], - pub msg: &'msg [u8], - pub nonce: u64, -} +pub struct NoncePlaintext<'aad, 'msg>(Plaintext<'aad, 'msg>); impl<'aad, 'msg> NoncePlaintext<'aad, 'msg> { - pub fn new(aad: &'aad [u8], msg: &'msg [u8], nonce: u64) -> Self { - Self { aad, msg, nonce } + /// Create a new NoncePlaintext object from the given slices. + pub fn new(aad: &'aad [u8], msg: &'msg [u8]) -> Self { + Self(Plaintext::new(aad, msg)) + } + + /// Grab a reference to the internal `aad` slice. + pub fn aad(&self) -> &[u8] { + self.0.aad + } + + /// Grab a reference to the internal `msg` slice. + pub fn msg(&self) -> &[u8] { + self.0.msg } } /// Plaintext may be provided to an FST for encryption into a vector impl MealyInput for NoncePlaintext<'_, '_> {} +/// A tuple of bytes and a u64 can be output from an FST for the +/// encrypt-for-explicit nonce case. +impl MealyOutput for (Vec, u64) {} + /// A type similar to [`aead::Payload`] used to distinguish reader inputs from /// outputs when there's an explicit nonce. pub struct NonceCiphertext<'aad, 'msg> { - pub aad: &'aad [u8], - pub msg: &'msg [u8], + pub ciphertext: Ciphertext<'aad, 'msg>, pub nonce: u64, } impl<'aad, 'msg> NonceCiphertext<'aad, 'msg> { pub fn new(aad: &'aad [u8], msg: &'msg [u8], nonce: u64) -> Self { - Self { aad, msg, nonce } + Self { + ciphertext: Ciphertext::new(aad, msg), + nonce, + } } } diff --git a/attest/ake/src/shared.rs b/attest/ake/src/shared.rs index 2c8e19b36a..3d46e98a18 100644 --- a/attest/ake/src/shared.rs +++ b/attest/ake/src/shared.rs @@ -60,13 +60,14 @@ where input: NonceCiphertext<'_, '_>, ) -> Result<(Ready, Vec), Self::Error> { let mut retval = self; - let plaintext = retval.decrypt_with_nonce(input.aad, input.msg, input.nonce)?; + let plaintext = + retval.decrypt_with_nonce(input.ciphertext.aad, input.ciphertext.msg, input.nonce)?; Ok((retval, plaintext)) } } -/// Ready + NoncePlaintext => Ready + Vec -impl Transition, NoncePlaintext<'_, '_>, Vec> for Ready +/// Ready + NoncePlaintext => Ready + (Vec + u64) +impl Transition, NoncePlaintext<'_, '_>, (Vec, u64)> for Ready where Cipher: NoiseCipher, { @@ -76,9 +77,9 @@ where self, _csprng: &mut R, input: NoncePlaintext<'_, '_>, - ) -> Result<(Ready, Vec), Self::Error> { + ) -> Result<(Ready, (Vec, u64)), Self::Error> { let mut retval = self; - let ciphertext = retval.encrypt_with_nonce(input.aad, input.msg, input.nonce)?; - Ok((retval, ciphertext)) + let output = retval.encrypt_with_nonce(input.aad(), input.msg())?; + Ok((retval, output)) } } diff --git a/attest/ake/src/state.rs b/attest/ake/src/state.rs index 4d9e7ed28c..0178fda804 100644 --- a/attest/ake/src/state.rs +++ b/attest/ake/src/state.rs @@ -85,15 +85,16 @@ where self.reader.decrypt_with_ad(aad, ciphertext) } - /// Using the writer cipher, encrypt the given plaintext for the nonce. + /// Using the writer cipher, encrypt the given plaintext and return the + /// nonce. pub fn encrypt_with_nonce( &mut self, aad: &[u8], plaintext: &[u8], - nonce: u64, - ) -> Result, CipherError> { - self.writer.set_nonce(nonce); - self.encrypt(aad, plaintext) + ) -> Result<(Vec, u64), CipherError> { + let nonce = self.writer.next_nonce(); + let ciphertext = self.encrypt(aad, plaintext)?; + Ok((ciphertext, nonce)) } /// Using the reader cipher, decrypt the provided ciphertext for the nonce. diff --git a/crypto/noise/src/cipher_state.rs b/crypto/noise/src/cipher_state.rs index 039cca2b6c..dfcc8917e8 100644 --- a/crypto/noise/src/cipher_state.rs +++ b/crypto/noise/src/cipher_state.rs @@ -161,12 +161,19 @@ impl CipherState { self.cipher.is_some() } + /// Retrieve the nonce value which will be used in the next operation. + /// + /// This is an extension of the noise protocol to allow for implicit-nonce + /// writers with explicit-nonce readers to co-exist in the same stream. + pub fn next_nonce(&self) -> u64 { + self.nonce + } + /// The noise protocol `SetNonce()` operation. /// /// This will irrevocably override the current nonce value. pub fn set_nonce(&mut self, nonce: u64) { self.nonce = nonce; - // TODO: return current nonce? We don't provide any access otherwise... } /// The noise protocol `EncryptWithAd()` operation. @@ -393,4 +400,14 @@ mod test { assert_eq!(encryptor.nonce, 2); assert_eq!(encryptor.bytes_sent, key.len() as u64); } + + /// Try to set the nonce, and retrieve it. + #[test] + fn set_nonce() { + let mut encryptor = CipherState::::default(); + let expected = 1234; + encryptor.set_nonce(expected); + let actual = encryptor.nonce(); + assert_eq!(expected, actual); + } } From d658159860cda524cda2e9e56ad62e49e154eada Mon Sep 17 00:00:00 2001 From: James Cape Date: Fri, 2 Sep 2022 16:12:02 -0700 Subject: [PATCH 2/3] Minor doc update --- attest/ake/src/shared.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/attest/ake/src/shared.rs b/attest/ake/src/shared.rs index 3d46e98a18..55aa65f0ec 100644 --- a/attest/ake/src/shared.rs +++ b/attest/ake/src/shared.rs @@ -66,7 +66,7 @@ where } } -/// Ready + NoncePlaintext => Ready + (Vec + u64) +/// Ready + NoncePlaintext => Ready + (Vec, u64) impl Transition, NoncePlaintext<'_, '_>, (Vec, u64)> for Ready where Cipher: NoiseCipher, From 7b4835c16ff5b404cda7010e7ca8636b1cf80a47 Mon Sep 17 00:00:00 2001 From: James Cape Date: Tue, 6 Sep 2022 17:22:24 -0700 Subject: [PATCH 3/3] Fix test issue. --- crypto/noise/src/cipher_state.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crypto/noise/src/cipher_state.rs b/crypto/noise/src/cipher_state.rs index dfcc8917e8..b6ff807be7 100644 --- a/crypto/noise/src/cipher_state.rs +++ b/crypto/noise/src/cipher_state.rs @@ -407,7 +407,7 @@ mod test { let mut encryptor = CipherState::::default(); let expected = 1234; encryptor.set_nonce(expected); - let actual = encryptor.nonce(); + let actual = encryptor.next_nonce(); assert_eq!(expected, actual); } }