Skip to content

Commit

Permalink
Messages for noise protocol exchanges with explicit nonces (#2461)
Browse files Browse the repository at this point in the history
* attest::NonceMessage, EnclaveNonceMessage, add handling to attest-ake

* Rustfmt fixes
  • Loading branch information
James Cape authored Sep 2, 2022
1 parent 0376e4f commit de00b8e
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 5 deletions.
34 changes: 34 additions & 0 deletions attest/ake/src/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -351,3 +351,37 @@ impl MealyInput for Ciphertext<'_, '_> {}

/// Our outputs may be simple vectors for the proto-inside-grpc use case.
impl MealyOutput for Vec<u8> {}

/// 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,
}

impl<'aad, 'msg> NoncePlaintext<'aad, 'msg> {
pub fn new(aad: &'aad [u8], msg: &'msg [u8], nonce: u64) -> Self {
Self { aad, msg, nonce }
}
}

/// Plaintext may be provided to an FST for encryption into a vector
impl MealyInput for NoncePlaintext<'_, '_> {}

/// 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 nonce: u64,
}

impl<'aad, 'msg> NonceCiphertext<'aad, 'msg> {
pub fn new(aad: &'aad [u8], msg: &'msg [u8], nonce: u64) -> Self {
Self { aad, msg, nonce }
}
}

/// Plaintext may be provided to an FST for encryption into a vector
impl MealyInput for NonceCiphertext<'_, '_> {}
38 changes: 37 additions & 1 deletion attest/ake/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
//! Common transitions between initiator and responder.
use crate::{
event::{Ciphertext, Plaintext},
event::{Ciphertext, NonceCiphertext, NoncePlaintext, Plaintext},
mealy::Transition,
state::Ready,
};
Expand Down Expand Up @@ -46,3 +46,39 @@ where
Ok((retval, ciphertext))
}
}

/// Ready + NonceCiphertext => Ready + Vec
impl<Cipher> Transition<Ready<Cipher>, NonceCiphertext<'_, '_>, Vec<u8>> for Ready<Cipher>
where
Cipher: NoiseCipher,
{
type Error = CipherError;

fn try_next<R: CryptoRng + RngCore>(
self,
_csprng: &mut R,
input: NonceCiphertext<'_, '_>,
) -> Result<(Ready<Cipher>, Vec<u8>), Self::Error> {
let mut retval = self;
let plaintext = retval.decrypt_with_nonce(input.aad, input.msg, input.nonce)?;
Ok((retval, plaintext))
}
}

/// Ready + NoncePlaintext => Ready + Vec
impl<Cipher> Transition<Ready<Cipher>, NoncePlaintext<'_, '_>, Vec<u8>> for Ready<Cipher>
where
Cipher: NoiseCipher,
{
type Error = CipherError;

fn try_next<R: CryptoRng + RngCore>(
self,
_csprng: &mut R,
input: NoncePlaintext<'_, '_>,
) -> Result<(Ready<Cipher>, Vec<u8>), Self::Error> {
let mut retval = self;
let ciphertext = retval.encrypt_with_nonce(input.aad, input.msg, input.nonce)?;
Ok((retval, ciphertext))
}
}
23 changes: 23 additions & 0 deletions attest/ake/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ where
pub fn binding(&self) -> &[u8] {
self.binding.as_ref()
}

/// Using the writer cipher, encrypt the given plaintext.
pub fn encrypt(&mut self, aad: &[u8], plaintext: &[u8]) -> Result<Vec<u8>, CipherError> {
self.writer.encrypt_with_ad(aad, plaintext)
Expand All @@ -83,6 +84,28 @@ where
pub fn decrypt(&mut self, aad: &[u8], ciphertext: &[u8]) -> Result<Vec<u8>, CipherError> {
self.reader.decrypt_with_ad(aad, ciphertext)
}

/// Using the writer cipher, encrypt the given plaintext for the nonce.
pub fn encrypt_with_nonce(
&mut self,
aad: &[u8],
plaintext: &[u8],
nonce: u64,
) -> Result<Vec<u8>, CipherError> {
self.writer.set_nonce(nonce);
self.encrypt(aad, plaintext)
}

/// Using the reader cipher, decrypt the provided ciphertext for the nonce.
pub fn decrypt_with_nonce(
&mut self,
aad: &[u8],
ciphertext: &[u8],
nonce: u64,
) -> Result<Vec<u8>, CipherError> {
self.reader.set_nonce(nonce);
self.decrypt(aad, ciphertext)
}
}

impl<Cipher> State for Ready<Cipher> where Cipher: NoiseCipher {}
17 changes: 17 additions & 0 deletions attest/api/proto/attest.proto
Original file line number Diff line number Diff line change
Expand Up @@ -48,3 +48,20 @@ message Message {
/// for use in the enclave.
bytes data = 3;
}

/// An AEAD message with an explicit nonce.
///
/// This message is technically compatible with [`Message`], but exists to
// ensure generated code doesn't use Message.
message NonceMessage {
/// A byte array containing plaintext authenticated data.
bytes aad = 1;
/// An byte array containing the channel ID this message is
/// associated with. A zero-length channel ID is not valid.
bytes channel_id = 2;
/// A potentially encrypted bytestream containing opaque data intended
/// for use in the enclave.
bytes data = 3;
/// The explicit nonce.
fixed64 nonce = 4;
}
30 changes: 26 additions & 4 deletions attest/api/src/conversions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@

//! Conversions from gRPC message types into consensus_enclave_api types.
use crate::attest::{AuthMessage, Message};
use crate::attest::{AuthMessage, Message, NonceMessage};
use mc_attest_ake::{AuthRequestOutput, AuthResponseOutput};
use mc_attest_enclave_api::{
ClientAuthRequest, ClientAuthResponse, EnclaveMessage, PeerAuthRequest, PeerAuthResponse,
Session,
ClientAuthRequest, ClientAuthResponse, EnclaveMessage, EnclaveNonceMessage, PeerAuthRequest,
PeerAuthResponse, Session,
};
use mc_crypto_keys::Kex;
use mc_crypto_noise::{HandshakePattern, NoiseCipher, NoiseDigest};
Expand Down Expand Up @@ -103,8 +103,30 @@ impl<S: Session> From<EnclaveMessage<S>> for Message {
fn from(src: EnclaveMessage<S>) -> Message {
let mut retval = Message::default();
retval.set_aad(src.aad);
retval.set_channel_id(src.channel_id.clone().into());
retval.set_channel_id(src.channel_id.into());
retval.set_data(src.data);
retval
}
}

impl<S: Session> From<NonceMessage> for EnclaveNonceMessage<S> {
fn from(src: NonceMessage) -> EnclaveNonceMessage<S> {
EnclaveNonceMessage {
aad: src.aad,
channel_id: S::from(&src.channel_id),
data: src.data,
nonce: src.nonce,
}
}
}

impl<S: Session> From<EnclaveNonceMessage<S>> for NonceMessage {
fn from(src: EnclaveNonceMessage<S>) -> NonceMessage {
let mut retval = NonceMessage::default();
retval.set_aad(src.aad);
retval.set_channel_id(src.channel_id.into());
retval.set_data(src.data);
retval.set_nonce(src.nonce);
retval
}
}
13 changes: 13 additions & 0 deletions attest/enclave-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,19 @@ pub struct EnclaveMessage<S: Session> {
pub data: Vec<u8>,
}

/// Inbound and outbound messages to/from an enclave with an explicit nonce.
#[derive(Clone, Debug, Default, Deserialize, Eq, Hash, Ord, PartialEq, PartialOrd, Serialize)]
pub struct EnclaveNonceMessage<S: Session> {
/// Authenticated data, if any.
pub aad: Vec<u8>,
/// The channel ID of this message.
pub channel_id: S,
/// The encrypted payload data of this message.
pub data: Vec<u8>,
/// The explicit nonce for this message.
pub nonce: u64,
}

/// The response to a request for a new report. The enclave will expect the
/// QuoteNonce to be used when the report is quoted, and both the quote and
/// report to be returned to the enclave during the verify_quote() phase.
Expand Down

0 comments on commit de00b8e

Please sign in to comment.