diff --git a/implementations/rust/ockam/ockam_api/src/authority_node/authority.rs b/implementations/rust/ockam/ockam_api/src/authority_node/authority.rs index fe660ebf83d..d8792900e9a 100644 --- a/implementations/rust/ockam/ockam_api/src/authority_node/authority.rs +++ b/implementations/rust/ockam/ockam_api/src/authority_node/authority.rs @@ -12,8 +12,7 @@ use crate::authenticator::{ }; use ockam::identity::utils::now; use ockam::identity::{ - Identifier, Identities, SecureChannelListenerOptions, SecureChannelSqlxDatabase, - SecureChannels, TrustEveryonePolicy, + Identifier, Identities, SecureChannelListenerOptions, SecureChannels, TrustEveryonePolicy, }; use ockam::tcp::{TcpListenerOptions, TcpTransport}; use ockam_core::compat::sync::Arc; @@ -75,14 +74,12 @@ impl Authority { let members = Arc::new(AuthorityMembersSqlxDatabase::new(database.clone())); let tokens = Arc::new(AuthorityEnrollmentTokenSqlxDatabase::new(database.clone())); - let secure_channel_repository = Arc::new(SecureChannelSqlxDatabase::new(database.clone())); Self::bootstrap_repository(members.clone(), configuration).await?; let identities = Identities::create_with_node(database, node_name).build(); - let secure_channels = - SecureChannels::from_identities(identities.clone(), secure_channel_repository); + let secure_channels = SecureChannels::from_identities(identities.clone()); let identifier = configuration.identifier(); info!(identifier=%identifier, "retrieved the authority identifier"); diff --git a/implementations/rust/ockam/ockam_api/src/cli_state/secure_channels.rs b/implementations/rust/ockam/ockam_api/src/cli_state/secure_channels.rs index 9abc218fae9..7ce2b06d5fa 100644 --- a/implementations/rust/ockam/ockam_api/src/cli_state/secure_channels.rs +++ b/implementations/rust/ockam/ockam_api/src/cli_state/secure_channels.rs @@ -2,7 +2,7 @@ use std::sync::Arc; use crate::cli_state::CliState; use crate::cli_state::Result; -use ockam::identity::{Identities, SecureChannelSqlxDatabase, SecureChannels}; +use ockam::identity::{Identities, SecureChannels}; use ockam_node::Context; impl CliState { @@ -17,9 +17,6 @@ impl CliState { let identities = Identities::create_with_node(self.database(), node_name) .with_vault(vault) .build(); - Ok(SecureChannels::from_identities( - identities, - Arc::new(SecureChannelSqlxDatabase::new(self.database())), - )) + Ok(SecureChannels::from_identities(identities)) } } diff --git a/implementations/rust/ockam/ockam_api/src/cli_state/vaults.rs b/implementations/rust/ockam/ockam_api/src/cli_state/vaults.rs index 6f252fa6984..2a3a0d73241 100644 --- a/implementations/rust/ockam/ockam_api/src/cli_state/vaults.rs +++ b/implementations/rust/ockam/ockam_api/src/cli_state/vaults.rs @@ -1,7 +1,7 @@ use colorful::Colorful; use ockam::identity::{ - Identifier, Identities, RemoteCredentialRetrieverInfo, SecureChannelRegistry, - SecureChannelSqlxDatabase, SecureChannels, Vault, + Identifier, Identities, RemoteCredentialRetrieverInfo, SecureChannelRegistry, SecureChannels, + Vault, }; use ockam_core::errcode::{Kind, Origin}; use ockam_core::{AsyncTryClone, Error}; @@ -398,7 +398,6 @@ impl CliState { let secure_channels = Arc::new(SecureChannels::new( identities, SecureChannelRegistry::default(), //TODO: inherit registry from the node - Arc::new(SecureChannelSqlxDatabase::new(self.database())), )); let credential_retriever_creator = credential_retriever_options diff --git a/implementations/rust/ockam/ockam_api/src/nodes/service.rs b/implementations/rust/ockam/ockam_api/src/nodes/service.rs index 03fed806739..5bb1929e5bd 100644 --- a/implementations/rust/ockam/ockam_api/src/nodes/service.rs +++ b/implementations/rust/ockam/ockam_api/src/nodes/service.rs @@ -28,7 +28,6 @@ mod trust; mod worker; pub use manager::*; -pub use secure_channel::SecureChannelType; pub use trust::*; pub use worker::*; diff --git a/implementations/rust/ockam/ockam_api/src/nodes/service/manager.rs b/implementations/rust/ockam/ockam_api/src/nodes/service/manager.rs index 74d55bf820e..267e65d6923 100644 --- a/implementations/rust/ockam/ockam_api/src/nodes/service/manager.rs +++ b/implementations/rust/ockam/ockam_api/src/nodes/service/manager.rs @@ -10,7 +10,6 @@ use crate::nodes::registry::Registry; use crate::nodes::service::http::HttpServer; use crate::nodes::service::{ CredentialRetrieverCreators, CredentialRetrieverOptions, NodeManagerTrustOptions, - SecureChannelType, }; use crate::cli_state::journeys::{NODE_NAME, USER_EMAIL, USER_NAME}; @@ -205,7 +204,6 @@ impl NodeManager { None, // Not checking identifiers here in favor of credential check None, ctx, - SecureChannelType::KeyExchangeAndMessages, ) .await?; diff --git a/implementations/rust/ockam/ockam_api/src/nodes/service/relay.rs b/implementations/rust/ockam/ockam_api/src/nodes/service/relay.rs index af7b3429da1..6066e8fb49b 100644 --- a/implementations/rust/ockam/ockam_api/src/nodes/service/relay.rs +++ b/implementations/rust/ockam/ockam_api/src/nodes/service/relay.rs @@ -21,7 +21,6 @@ use crate::nodes::models::secure_channel::{ }; use crate::nodes::registry::RegistryRelayInfo; use crate::nodes::service::in_memory_node::InMemoryNode; -use crate::nodes::service::secure_channel::SecureChannelType; use crate::nodes::BackgroundNodeClient; use crate::session::replacer::{ReplacerOutcome, ReplacerOutputKind, SessionReplacer}; use crate::session::session::Session; @@ -440,7 +439,6 @@ impl SecureChannelsCreation for InMemoryNode { Some(vec![authorized]), credential, timeout, - SecureChannelType::KeyExchangeAndMessages, ) .await .into_diagnostic() diff --git a/implementations/rust/ockam/ockam_api/src/nodes/service/secure_channel.rs b/implementations/rust/ockam/ockam_api/src/nodes/service/secure_channel.rs index 5826178aa9e..2d747064b86 100644 --- a/implementations/rust/ockam/ockam_api/src/nodes/service/secure_channel.rs +++ b/implementations/rust/ockam/ockam_api/src/nodes/service/secure_channel.rs @@ -1,13 +1,13 @@ use std::time::Duration; use ockam::identity::models::CredentialAndPurposeKey; +use ockam::identity::TrustEveryonePolicy; use ockam::identity::Vault; use ockam::identity::{ Identifier, Identities, SecureChannelListenerOptions, SecureChannelOptions, SecureChannels, TrustMultiIdentifiersPolicy, }; use ockam::identity::{SecureChannel, SecureChannelListener}; -use ockam::identity::{SecureChannelSqlxDatabase, TrustEveryonePolicy}; use ockam::{Address, Result, Route}; use ockam_core::api::{Error, Response}; use ockam_core::compat::sync::Arc; @@ -29,12 +29,6 @@ use crate::nodes::registry::SecureChannelInfo; use crate::nodes::service::default_address::DefaultAddress; use crate::nodes::{NodeManager, NodeManagerWorker}; -#[derive(PartialOrd, PartialEq, Debug)] -pub enum SecureChannelType { - KeyExchangeAndMessages, - KeyExchangeOnly, -} - /// SECURE CHANNELS impl NodeManagerWorker { pub async fn list_secure_channels(&self) -> Result>, Response> { @@ -64,7 +58,6 @@ impl NodeManagerWorker { authorized_identifiers, credential, timeout, - SecureChannelType::KeyExchangeAndMessages, ) .await .map(|secure_channel| { @@ -124,13 +117,7 @@ impl NodeManagerWorker { let response = self .node_manager - .create_secure_channel_listener( - addr, - authorized_identifiers, - identity_name, - ctx, - SecureChannelType::KeyExchangeAndMessages, - ) + .create_secure_channel_listener(addr, authorized_identifiers, identity_name, ctx) .await .map(|_| Response::ok())?; Ok(response) @@ -177,7 +164,6 @@ impl NodeManager { authorized_identifiers: Option>, credential: Option, timeout: Option, - secure_channel_type: SecureChannelType, ) -> Result { let identifier = self.get_identifier_by_name(identity_name.clone()).await?; @@ -192,7 +178,6 @@ impl NodeManager { authorized_identifiers, credential, timeout, - secure_channel_type, ) .await?; @@ -209,7 +194,6 @@ impl NodeManager { authorized_identifiers: Option>, credential: Option, timeout: Option, - secure_channel_type: SecureChannelType, ) -> Result { debug!(%sc_route, "Creating secure channel"); let options = SecureChannelOptions::new(); @@ -240,13 +224,6 @@ impl NodeManager { None => options.with_trust_policy(TrustEveryonePolicy), }; - let options = if secure_channel_type == SecureChannelType::KeyExchangeOnly { - // TODO: Should key exchange channels be persisted automatically? - options.key_exchange_only().persist()? - } else { - options - }; - let sc = self .secure_channels .create_secure_channel(ctx, identifier, sc_route.clone(), options) @@ -303,35 +280,12 @@ impl NodeManager { /// SECURE CHANNEL LISTENERS impl NodeManager { - //TODO: remove everything about key exchange service from secure channel - #[allow(dead_code)] - pub(crate) async fn start_key_exchanger_service( - &self, - context: &Context, - address: Address, - ) -> Result { - // skip creation if it already exists - if let Some(listener) = self.registry.secure_channel_listeners.get(&address).await { - return Ok(listener); - } - - self.create_secure_channel_listener( - address.clone(), - None, - None, - context, - SecureChannelType::KeyExchangeOnly, - ) - .await - } - pub async fn create_secure_channel_listener( &self, address: Address, authorized_identifiers: Option>, identity_name: Option, ctx: &Context, - secure_channel_type: SecureChannelType, ) -> Result { debug!( "Handling request to create a new secure channel listener: {}", @@ -381,13 +335,6 @@ impl NodeManager { } }; - let options = if secure_channel_type == SecureChannelType::KeyExchangeOnly { - // TODO: Should key exchange channels be persisted automatically? - options.key_exchange_only().persist()? - } else { - options - }; - let listener = secure_channels .create_secure_channel_listener(ctx, &identifier, address.clone(), options) .await?; @@ -399,27 +346,25 @@ impl NodeManager { .insert(address.clone(), listener.clone()) .await; - if secure_channel_type == SecureChannelType::KeyExchangeAndMessages { - // TODO: Clean - // Add Echoer as a consumer by default - ctx.flow_controls() - .add_consumer(DefaultAddress::ECHO_SERVICE, listener.flow_control_id()); - - // TODO: PUNCTURE Make optional? - ctx.flow_controls().add_consumer( - DefaultAddress::UDP_PUNCTURE_NEGOTIATION_LISTENER, - listener.flow_control_id(), - ); - - // Add ourselves to allow tunneling - ctx.flow_controls() - .add_consumer(address, listener.flow_control_id()); - - ctx.flow_controls().add_consumer( - DefaultAddress::UPPERCASE_SERVICE, - listener.flow_control_id(), - ); - } + // TODO: Clean + // Add Echoer as a consumer by default + ctx.flow_controls() + .add_consumer(DefaultAddress::ECHO_SERVICE, listener.flow_control_id()); + + // TODO: PUNCTURE Make optional? + ctx.flow_controls().add_consumer( + DefaultAddress::UDP_PUNCTURE_NEGOTIATION_LISTENER, + listener.flow_control_id(), + ); + + // Add ourselves to allow tunneling + ctx.flow_controls() + .add_consumer(address, listener.flow_control_id()); + + ctx.flow_controls().add_consumer( + DefaultAddress::UPPERCASE_SERVICE, + listener.flow_control_id(), + ); Ok(listener) } @@ -477,7 +422,6 @@ impl NodeManager { Ok(Arc::new(SecureChannels::new( identities, self.secure_channels.secure_channel_registry(), - Arc::new(SecureChannelSqlxDatabase::new(self.cli_state.database())), ))) } } diff --git a/implementations/rust/ockam/ockam_api/src/nodes/service/tcp_inlets/session_replacer.rs b/implementations/rust/ockam/ockam_api/src/nodes/service/tcp_inlets/session_replacer.rs index 9fb91fe0052..ef7000b2945 100644 --- a/implementations/rust/ockam/ockam_api/src/nodes/service/tcp_inlets/session_replacer.rs +++ b/implementations/rust/ockam/ockam_api/src/nodes/service/tcp_inlets/session_replacer.rs @@ -20,7 +20,6 @@ use ockam_transport_tcp::TcpInlet; use crate::error::ApiError; use crate::nodes::connection::Connection; -use crate::nodes::service::SecureChannelType; use crate::nodes::NodeManager; use crate::session::replacer::{ AdditionalSessionReplacer, CurrentInletStatus, ReplacerOutcome, ReplacerOutputKind, @@ -356,7 +355,6 @@ impl AdditionalSessionReplacer for InletSessionReplacer { None, // TODO: Have a dedicated timeout Some(Duration::from_secs(10)), - SecureChannelType::KeyExchangeAndMessages, ) .await?; let additional_sc = self.additional_secure_channel.insert(additional_sc); diff --git a/implementations/rust/ockam/ockam_api/tests/credential_issuer.rs b/implementations/rust/ockam/ockam_api/tests/credential_issuer.rs index ec1bd9eef36..a771f302a40 100644 --- a/implementations/rust/ockam/ockam_api/tests/credential_issuer.rs +++ b/implementations/rust/ockam/ockam_api/tests/credential_issuer.rs @@ -1,7 +1,7 @@ use minicbor::bytes::ByteSlice; +use ockam::identity::identities; use ockam::identity::models::CredentialAndPurposeKey; use ockam::identity::utils::now; -use ockam::identity::{identities, SecureChannelSqlxDatabase}; use ockam::identity::{ Identities, SecureChannelListenerOptions, SecureChannelOptions, SecureChannels, }; @@ -55,10 +55,7 @@ async fn credential(ctx: &mut Context) -> Result<()> { .with_purpose_keys_repository(identities.purpose_keys_repository()) .with_cached_credential_repository(identities.cached_credentials_repository()) .build(); - let secure_channels = SecureChannels::from_identities( - identities.clone(), - Arc::new(SecureChannelSqlxDatabase::create().await?), - ); + let secure_channels = SecureChannels::from_identities(identities.clone()); let identities_verification = identities.identities_verification(); // Create the CredentialIssuer: diff --git a/implementations/rust/ockam/ockam_api/tests/latency.rs b/implementations/rust/ockam/ockam_api/tests/latency.rs index 7ed6b3d5a24..53e5128573d 100644 --- a/implementations/rust/ockam/ockam_api/tests/latency.rs +++ b/implementations/rust/ockam/ockam_api/tests/latency.rs @@ -1,6 +1,5 @@ #![recursion_limit = "256"] -use ockam_api::nodes::service::SecureChannelType; use std::sync::Arc; use std::time::{Duration, Instant}; @@ -48,7 +47,6 @@ pub fn measure_message_latency_two_nodes() -> ockam_core::Result<()> { None, None, None, - SecureChannelType::KeyExchangeAndMessages, ) .await .unwrap(); diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channel/api.rs b/implementations/rust/ockam/ockam_identity/src/secure_channel/api.rs index bd3e3b94831..a0fc95b3125 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channel/api.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channel/api.rs @@ -1,47 +1,20 @@ -use ockam_core::compat::vec::Vec; -use ockam_core::Error; -use ockam_core::Message; -use serde::{Deserialize, Serialize}; +use minicbor::{CborLen, Decode, Encode}; +use ockam_vault::AeadSecretKeyHandle; -/// Request type for `EncryptorWorker` API Address -#[derive(Serialize, Deserialize, Message)] -pub enum EncryptionRequest { - /// Encrypt data - Encrypt(Vec), - /// Trigger a manual rekey - Rekey, - /// Derive new key - DeriveNewKey, +/// Request type for `SecureChannel` API Address +#[derive(Encode, Decode, CborLen)] +#[rustfmt::skip] +pub enum SecureChannelApiRequest { + /// Derive a new key from current key and shutdown the worker + #[n(0)] ExtractKey, } -/// Response type for `EncryptorWorker` API Address -#[derive(Serialize, Deserialize, Message)] -pub enum EncryptionResponse { +/// Response type for `SecureChannel` API Address +#[derive(Encode, Decode, CborLen)] +#[rustfmt::skip] +pub enum SecureChannelApiResponse { /// Success - Ok(Vec), + #[n(0)] Ok(#[n(0)] AeadSecretKeyHandle), /// Error - Err(Error), -} - -/// Request type for `Decryptor` API Address (the `Decryptor` is accessible through the `HandshakeWorker`) -#[derive(Serialize, Deserialize, Message)] -pub enum DecryptionRequest { - /// Decrypt data - Decrypt { - /// Ciphertext to decrypt - ciphertext: Vec, - /// Rekey counter - rekey_counter: Option, - }, - /// Derive new key - DeriveNewKey, -} - -/// Response type for `Decryptor` API Address (the `Decryptor` is accessible through the `HandshakeWorker`) -#[derive(Serialize, Deserialize, Message)] -pub enum DecryptionResponse { - /// Success - Ok(Vec), - /// Error - Err(Error), + #[n(1)] Err(#[n(0)] String), } diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channel/decryptor.rs b/implementations/rust/ockam/ockam_identity/src/secure_channel/decryptor.rs index 857a1208795..9971eb9c5ad 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channel/decryptor.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channel/decryptor.rs @@ -1,7 +1,7 @@ use core::sync::atomic::Ordering; use ockam_core::compat::sync::Arc; +use ockam_core::{cbor_encode_preallocate, LocalMessage, NeutralMessage}; use ockam_core::{route, Any, OnDrop, Result, Route, Routed, SecureChannelLocalInfo}; -use ockam_core::{Decodable, LocalMessage}; use ockam_node::Context; use crate::models::Identifier; @@ -11,17 +11,15 @@ use crate::secure_channel::key_tracker::KeyTracker; use crate::secure_channel::nonce_tracker::NonceTracker; use crate::secure_channel::{Addresses, Role}; use crate::{ - DecryptionRequest, DecryptionResponse, Identities, IdentityError, Nonce, - PlaintextPayloadMessage, RefreshCredentialsMessage, SecureChannelMessage, + Identities, IdentityError, Nonce, PlaintextPayloadMessage, RefreshCredentialsMessage, + SecureChannelApiRequest, SecureChannelApiResponse, SecureChannelMessage, SecureChannelPaddedMessage, NOISE_NONCE_LEN, }; use crate::secure_channel::encryptor_worker::SecureChannelSharedState; -use ockam_core::errcode::{Kind, Origin}; use ockam_vault::{AeadSecretKeyHandle, VaultForSecureChannels}; use tracing::{debug, info, trace, warn}; use tracing_attributes::instrument; -use zeroize::Zeroize; pub(crate) struct DecryptorHandler { //for debug purposes only @@ -41,24 +39,17 @@ impl DecryptorHandler { identities: Arc, authority: Option, role: Role, - key_exchange_only: bool, addresses: Addresses, key: AeadSecretKeyHandle, vault: Arc, their_identity_id: Identifier, shared_state: SecureChannelSharedState, ) -> Self { - let decryptor = if key_exchange_only { - Decryptor::new_naive(key, vault) - } else { - Decryptor::new(key, vault) - }; - Self { role, addresses, their_identity_id, - decryptor, + decryptor: Decryptor::new(key, vault), identities, authority, shared_state, @@ -66,11 +57,7 @@ impl DecryptorHandler { } #[instrument(skip_all)] - pub(crate) async fn handle_decrypt_api( - &mut self, - ctx: &mut Context, - msg: Routed, - ) -> Result<()> { + pub(crate) async fn handle_api(&mut self, ctx: &mut Context, msg: Routed) -> Result<()> { trace!( "SecureChannel {} received Decrypt API {}", self.role, @@ -81,34 +68,22 @@ impl DecryptorHandler { let return_route = msg.return_route; // Decode raw payload binary - let request = DecryptionRequest::decode(&msg.payload)?; + let request = minicbor::decode(msg.payload.as_slice())?; let response = match request { - DecryptionRequest::Decrypt { - mut ciphertext, - rekey_counter, - } => { - let decrypted_payload = if let Some(rekey_counter) = rekey_counter { - self.decryptor - .decrypt_with_rekey_counter(&mut ciphertext, rekey_counter) - .await - } else { - self.decryptor.decrypt(&mut ciphertext).await - }; - - match decrypted_payload { - Ok((payload, _nonce)) => DecryptionResponse::Ok(payload.to_vec()), - Err(err) => DecryptionResponse::Err(err), - } - } - DecryptionRequest::DeriveNewKey => { - todo!() + SecureChannelApiRequest::ExtractKey => { + let handle = self.decryptor.derive_new_key().await?; + SecureChannelApiResponse::Ok(handle) } }; + let response = NeutralMessage::from(cbor_encode_preallocate(&response)?); // Send reply to the caller ctx.send_from_address(return_route, response, self.addresses.decryptor_api.clone()) .await?; + // Once we have extracted the key, we can't use it anymore + ctx.stop_worker(self.addresses.encryptor.clone()).await?; + Ok(()) } @@ -227,7 +202,7 @@ impl DecryptorHandler { match decrypted_msg.message { SecureChannelMessage::Payload(decrypted_msg) => { - payload.set_zeroize(decrypted_msg.on_drop); + //TODO: payload.set_zeroize(decrypted_msg.on_drop); self.handle_payload(ctx, decrypted_msg, nonce, encrypted_msg_return_route) .await? } @@ -249,8 +224,7 @@ impl DecryptorHandler { pub(crate) struct Decryptor { vault: Arc, key_tracker: KeyTracker, - nonce_tracker: Option, - rekey_cache: Option<(u16, AeadSecretKeyHandle)>, + nonce_tracker: NonceTracker, } impl Decryptor { @@ -258,18 +232,7 @@ impl Decryptor { Self { vault, key_tracker: KeyTracker::new(key, KEY_RENEWAL_INTERVAL), - nonce_tracker: Some(NonceTracker::new()), - rekey_cache: None, - } - } - - /// Creates a new Decryptor without rekeying and nonce tracking - pub fn new_naive(key: AeadSecretKeyHandle, vault: Arc) -> Self { - Self { - vault, - key_tracker: KeyTracker::new(key, KEY_RENEWAL_INTERVAL), - nonce_tracker: None, - rekey_cache: None, + nonce_tracker: NonceTracker::new(), } } @@ -280,16 +243,11 @@ impl Decryptor { } let nonce = Nonce::try_from(&payload[..NOISE_NONCE_LEN])?; - let nonce_tracker = if let Some(nonce_tracker) = &self.nonce_tracker { - Some(nonce_tracker.mark(nonce)?) - } else { - None - }; + let nonce_tracker = self.nonce_tracker.mark(nonce)?; let rekey_key; - let rekeying = self.nonce_tracker.is_some(); - let key = if rekeying { + let key = // get the key corresponding to the current nonce and // rekey if necessary if let Some(key) = self.key_tracker.get_key(nonce)? { @@ -297,10 +255,7 @@ impl Decryptor { } else { rekey_key = self.vault.rekey(&self.key_tracker.current_key, 1).await?; &rekey_key - } - } else { - &self.key_tracker.current_key - }; + }; // to improve protection against connection disruption attacks, we want to validate the // message with a decryption _before_ committing to the new state @@ -328,89 +283,8 @@ impl Decryptor { } #[instrument(skip_all)] - pub async fn decrypt_with_rekey_counter<'a>( - &mut self, - payload: &'a mut [u8], - rekey_counter: u16, - ) -> Result<(&'a [u8], Nonce)> { - if payload.len() < 8 { - return Err(IdentityError::InvalidNonce)?; - } - - let nonce = Nonce::try_from(&payload[..8])?; - let nonce_tracker = if let Some(nonce_tracker) = &self.nonce_tracker { - Some(nonce_tracker.mark(nonce)?) - } else { - None - }; - - let key_handle = - if let Some((cached_rekey_counter, cached_key_handle)) = self.rekey_cache.clone() { - if cached_rekey_counter == rekey_counter { - Some(cached_key_handle) - } else { - self.rekey_cache = None; - self.vault - .delete_aead_secret_key(cached_key_handle.clone()) - .await?; - None - } - } else { - None - }; - - let key_handle = match key_handle { - Some(key) => key, - None => { - let current_number_of_rekeys = self.key_tracker.number_of_rekeys(); - if current_number_of_rekeys > rekey_counter as u64 { - return Err(ockam_core::Error::new( - Origin::Channel, - Kind::Invalid, - "cannot rekey backwards", - )); - } else if current_number_of_rekeys > u16::MAX as u64 { - return Err(ockam_core::Error::new( - Origin::Channel, - Kind::Invalid, - "rekey counter overflow", - )); - } else { - let n_rekying = rekey_counter - current_number_of_rekeys as u16; - if n_rekying > 0 { - let key_handle = self - .vault - .rekey(&self.key_tracker.current_key, n_rekying) - .await?; - self.rekey_cache = Some((rekey_counter, key_handle.clone())); - key_handle - } else { - self.key_tracker.current_key.clone() - } - } - } - }; - - // to improve protection against connection disruption attacks, we want to validate the - // message with a decryption _before_ committing to the new state - let result = self - .vault - .aead_decrypt( - &key_handle, - &mut payload[NOISE_NONCE_LEN..], - &nonce.to_aes_gcm_nonce(), - &[], - ) - .await; - - if result.is_ok() { - self.nonce_tracker = nonce_tracker; - if let Some(key_to_delete) = self.key_tracker.update_key(&key_handle)? { - self.vault.delete_aead_secret_key(key_to_delete).await?; - } - } - - result.map(|payload| (&*payload, nonce)) + pub async fn derive_new_key(&mut self) -> Result { + self.vault.rekey(&self.key_tracker.current_key, 1).await } /// Remove the channel keys on shutdown @@ -426,12 +300,6 @@ impl Decryptor { .await?; }; - if let Some((_, key_handle)) = &self.rekey_cache { - self.vault - .delete_aead_secret_key(key_handle.clone()) - .await?; - } - Ok(()) } } diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channel/encryptor.rs b/implementations/rust/ockam/ockam_identity/src/secure_channel/encryptor.rs index 7a6fa90cec7..8723cb896d3 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channel/encryptor.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channel/encryptor.rs @@ -10,7 +10,6 @@ pub(crate) struct Encryptor { key: AeadSecretKeyHandle, nonce: Nonce, vault: Arc, - rekeying: bool, } // To simplify the implementation, we use the same constant for the size of the message @@ -25,10 +24,7 @@ impl Encryptor { self.nonce.increment()?; - if self.rekeying - && current_nonce.value() > 0 - && current_nonce.value() % KEY_RENEWAL_INTERVAL == 0 - { + if current_nonce.value() > 0 && current_nonce.value() % KEY_RENEWAL_INTERVAL == 0 { let new_key = self.vault.rekey(&self.key, 1).await?; let old_key = core::mem::replace(&mut self.key, new_key); self.vault.delete_aead_secret_key(old_key).await?; @@ -49,25 +45,16 @@ impl Encryptor { } #[instrument(skip_all)] - pub async fn manual_rekey(&mut self) -> Result<()> { - let new_key = self.vault.rekey(&self.key, 1).await?; - let old_key = core::mem::replace(&mut self.key, new_key); - self.vault.delete_aead_secret_key(old_key).await?; - Ok(()) + pub async fn derive_new_key(&mut self) -> Result { + self.vault.rekey(&self.key, 1).await } pub fn new( key: AeadSecretKeyHandle, nonce: Nonce, vault: Arc, - rekeying: bool, ) -> Self { - Self { - key, - nonce, - vault, - rekeying, - } + Self { key, nonce, vault } } #[instrument(skip_all)] diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channel/encryptor_worker.rs b/implementations/rust/ockam/ockam_identity/src/secure_channel/encryptor_worker.rs index 1123fffd86a..e7e65659417 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channel/encryptor_worker.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channel/encryptor_worker.rs @@ -1,11 +1,10 @@ use core::sync::atomic::{AtomicBool, Ordering}; - use ockam_core::compat::boxed::Box; use ockam_core::compat::sync::{Arc, RwLock}; use ockam_core::compat::vec::Vec; use ockam_core::errcode::{Kind, Origin}; use ockam_core::{ - async_trait, route, CowBytes, Decodable, Error, LocalMessage, MaybeZeroizeOnDrop, + async_trait, cbor_encode_preallocate, route, CowBytes, Error, LocalMessage, MaybeZeroizeOnDrop, NeutralMessage, OnDrop, Route, }; use ockam_core::{Any, Result, Routed, Worker}; @@ -15,7 +14,7 @@ use tracing_attributes::instrument; use crate::models::CredentialAndPurposeKey; use crate::secure_channel::addresses::Addresses; -use crate::secure_channel::api::{EncryptionRequest, EncryptionResponse}; +use crate::secure_channel::api::{SecureChannelApiRequest, SecureChannelApiResponse}; use crate::secure_channel::encryptor::Encryptor; use crate::secure_channel::handshake::handshake::AES_GCM_TAGSIZE; use crate::{ @@ -57,7 +56,6 @@ pub(crate) struct SecureChannelSharedState { pub(crate) struct EncryptorWorker { role: &'static str, // For debug purposes only - key_exchange_only: bool, addresses: Addresses, encryptor: Encryptor, my_identifier: Identifier, @@ -71,7 +69,6 @@ impl EncryptorWorker { #[allow(clippy::too_many_arguments)] pub fn new( role: &'static str, - key_exchange_only: bool, addresses: Addresses, encryptor: Encryptor, my_identifier: Identifier, @@ -82,7 +79,6 @@ impl EncryptorWorker { ) -> Self { Self { role, - key_exchange_only, addresses, encryptor, my_identifier, @@ -125,7 +121,7 @@ impl EncryptorWorker { } #[instrument(skip_all)] - async fn handle_encrypt_api( + async fn handle_api( &mut self, ctx: &mut ::Context, msg: Routed<::Message>, @@ -139,60 +135,24 @@ impl EncryptorWorker { let return_route = msg.return_route; // Decode raw payload binary - let request = EncryptionRequest::decode(&msg.payload)?; + let request = minicbor::decode(msg.payload.as_slice())?; // If encryption fails, that means we have some internal error, // and we may be in an invalid state, it's better to stop the Worker - let mut should_stop = false; let response = match request { - EncryptionRequest::Encrypt(plaintext) => { - let len = NOISE_NONCE_LEN + plaintext.len() + AES_GCM_TAGSIZE; - let mut encrypted_payload = vec![0u8; len]; - encrypted_payload[NOISE_NONCE_LEN..len - AES_GCM_TAGSIZE] - .copy_from_slice(&plaintext); - - // Encrypt the message - match self - .encryptor - .encrypt(encrypted_payload.as_mut_slice()) - .await - { - Ok(()) => EncryptionResponse::Ok(encrypted_payload), - // If encryption failed, that means we have some internal error, - // and we may be in an invalid state, it's better to stop the Worker - Err(err) => { - should_stop = true; - error!( - "Error while encrypting: {err} at: {}", - self.addresses.encryptor - ); - EncryptionResponse::Err(err) - } - } - } - EncryptionRequest::Rekey => match self.encryptor.manual_rekey().await { - Ok(()) => EncryptionResponse::Ok(Vec::new()), - Err(err) => { - should_stop = true; - error!( - "Error while rekeying: {err} at: {}", - self.addresses.encryptor - ); - EncryptionResponse::Err(err) - } - }, - EncryptionRequest::DeriveNewKey => { - todo!() + SecureChannelApiRequest::ExtractKey => { + let handle = self.encryptor.derive_new_key().await?; + SecureChannelApiResponse::Ok(handle) } }; + let response = NeutralMessage::from(cbor_encode_preallocate(&response)?); // Send the reply to the caller ctx.send_from_address(return_route, response, self.addresses.encryptor_api.clone()) .await?; - if should_stop { - ctx.stop_worker(self.addresses.encryptor.clone()).await?; - } + // Once we have extracted the key, we can't use it anymore + ctx.stop_worker(self.addresses.encryptor.clone()).await?; Ok(()) } @@ -374,16 +334,10 @@ impl Worker for EncryptorWorker { ) -> Result<()> { let msg_addr = msg.msg_addr(); - if self.key_exchange_only { - if msg_addr == self.addresses.encryptor_api { - self.handle_encrypt_api(ctx, msg).await?; - } else { - return Err(IdentityError::UnknownChannelMsgDestination)?; - } - } else if msg_addr == self.addresses.encryptor { + if msg_addr == self.addresses.encryptor { self.handle_encrypt(ctx, msg).await?; } else if msg_addr == self.addresses.encryptor_api { - self.handle_encrypt_api(ctx, msg).await?; + self.handle_api(ctx, msg).await?; } else if msg_addr == self.addresses.encryptor_internal { self.handle_refresh_credentials(ctx).await?; } else { diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channel/handshake/handshake_worker.rs b/implementations/rust/ockam/ockam_identity/src/secure_channel/handshake/handshake_worker.rs index 0a6865ff2c9..ba09fd1ef81 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channel/handshake/handshake_worker.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channel/handshake/handshake_worker.rs @@ -10,8 +10,7 @@ use ockam_core::{ use ockam_core::{Result, Worker}; use ockam_node::callback::CallbackSender; use ockam_node::{Context, WorkerBuilder}; -use ockam_vault::AeadSecretKeyHandle; -use tracing::{debug, error, info, warn}; +use tracing::{debug, error, info}; use tracing_attributes::instrument; use crate::models::Identifier; @@ -31,9 +30,8 @@ use crate::secure_channel::handshake::initiator_state_machine::InitiatorStateMac use crate::secure_channel::handshake::responder_state_machine::ResponderStateMachine; use crate::secure_channel::{Addresses, Role}; use crate::{ - ChangeHistoryRepository, CredentialRetriever, IdentityError, PersistedSecureChannel, - SecureChannelPurposeKey, SecureChannelRegistryEntry, SecureChannelRepository, SecureChannels, - TrustPolicy, + ChangeHistoryRepository, CredentialRetriever, IdentityError, SecureChannelPurposeKey, + SecureChannelRegistryEntry, SecureChannels, TrustPolicy, }; /// This struct implements a Worker receiving and sending messages @@ -45,7 +43,6 @@ pub(crate) struct HandshakeWorker { my_identifier: Identifier, addresses: Addresses, role: Role, - key_exchange_only: bool, remote_route: Option, decryptor_handler: Option, @@ -54,8 +51,6 @@ pub(crate) struct HandshakeWorker { credential_retriever: Option>, - secure_channel_repository: Option>, - shared_state: SecureChannelSharedState, } @@ -145,8 +140,6 @@ impl HandshakeWorker { remote_route: Option, timeout: Option, role: Role, - key_exchange_only: bool, - secure_channel_repository: Option>, encryptor_remote_route: Arc>, ) -> Result> { let vault = secure_channels.identities.vault().secure_channel_vault; @@ -197,14 +190,12 @@ impl HandshakeWorker { state_machine: Some(state_machine), my_identifier: my_identifier.clone(), role, - key_exchange_only, remote_route: remote_route.clone(), addresses: addresses.clone(), decryptor_handler: None, credential_retriever, authority, change_history_repository: identities.change_history_repository(), - secure_channel_repository, shared_state, }; @@ -318,16 +309,10 @@ impl HandshakeWorker { let decryptor_handler = self.decryptor_handler.as_mut().unwrap(); let msg_addr = message.msg_addr(); - if self.key_exchange_only { - if msg_addr == self.addresses.decryptor_api { - decryptor_handler.handle_decrypt_api(context, message).await - } else { - Err(IdentityError::UnknownChannelMsgDestination)? - } - } else if msg_addr == self.addresses.decryptor_remote { + if msg_addr == self.addresses.decryptor_remote { decryptor_handler.handle_decrypt(context, message).await } else if msg_addr == self.addresses.decryptor_api { - decryptor_handler.handle_decrypt_api(context, message).await + decryptor_handler.handle_api(context, message).await } else { Err(IdentityError::UnknownChannelMsgDestination)? } @@ -387,7 +372,6 @@ impl HandshakeWorker { self.secure_channels.identities.clone(), self.authority.clone(), self.role, - self.key_exchange_only, self.addresses.clone(), handshake_results.handshake_keys.decryption_key.clone(), self.secure_channels.identities.vault().secure_channel_vault, @@ -397,27 +381,18 @@ impl HandshakeWorker { // create a separate encryptor worker which will be started independently { - let (rekeying, credential_retriever) = if self.key_exchange_only { - // only the initial exchange is needed for key exchange only - (false, None) - } else { - (true, self.credential_retriever.clone()) - }; - self.shared_state.remote_route.write().unwrap().route = self.remote_route()?; let encryptor = EncryptorWorker::new( self.role.str(), - self.key_exchange_only, self.addresses.clone(), Encryptor::new( handshake_results.handshake_keys.encryption_key, 0.into(), self.secure_channels.identities.vault().secure_channel_vault, - rekeying, ), self.my_identifier.clone(), self.change_history_repository.clone(), - credential_retriever, + self.credential_retriever.clone(), handshake_results.presented_credential, self.shared_state.clone(), ); @@ -453,12 +428,6 @@ impl HandshakeWorker { .await?; } - self.persist( - their_identifier, - &handshake_results.handshake_keys.decryption_key, - ) - .await; - info!( "Initialized SecureChannel {} at local: {}, remote: {}", self.role.str(), @@ -490,88 +459,4 @@ impl HandshakeWorker { Ok(decryptor) } - - async fn persist(&self, their_identifier: Identifier, decryption_key: &AeadSecretKeyHandle) { - let Some(repository) = &self.secure_channel_repository else { - info!( - "Skipping persistence. Local: {}, Remote: {}", - self.addresses.encryptor, &self.addresses.decryptor_remote - ); - return; - }; - - let sc = PersistedSecureChannel::new( - self.role, - self.my_identifier.clone(), - their_identifier, - self.addresses.decryptor_remote.clone(), - self.addresses.decryptor_api.clone(), - decryption_key.clone(), - ); - match repository.put(sc).await { - Ok(_) => { - info!( - "Successfully persisted secure channel. Local: {}, Remote: {}", - self.addresses.encryptor, &self.addresses.decryptor_remote, - ); - } - Err(err) => { - warn!( - "Error while persisting secure channel: {err}. Local: {}, Remote: {}", - self.addresses.encryptor, &self.addresses.decryptor_remote - ); - - return; - } - } - - if let Err(err) = self - .secure_channels - .identities - .vault() - .secure_channel_vault - .persist_aead_key(decryption_key) - .await - { - warn!( - "Error persisting secure channel key: {err}. Local: {}, Remote: {}", - self.addresses.encryptor, &self.addresses.decryptor_remote - ); - }; - } - - #[allow(clippy::too_many_arguments)] - pub(crate) fn new( - secure_channels: Arc, - callback_sender: Option>, - state_machine: Option>, - my_identifier: Identifier, - addresses: Addresses, - role: Role, - key_exchange_only: bool, - remote_route: Option, - decryptor_handler: Option, - authority: Option, - change_history_repository: Arc, - credential_retriever: Option>, - secure_channel_repository: Option>, - shared_state: SecureChannelSharedState, - ) -> Self { - Self { - secure_channels, - callback_sender, - state_machine, - my_identifier, - addresses, - role, - key_exchange_only, - remote_route, - decryptor_handler, - authority, - change_history_repository, - credential_retriever, - secure_channel_repository, - shared_state, - } - } } diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channel/key_tracker.rs b/implementations/rust/ockam/ockam_identity/src/secure_channel/key_tracker.rs index d600a4c7837..d0c48339e65 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channel/key_tracker.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channel/key_tracker.rs @@ -23,10 +23,6 @@ impl KeyTracker { renewal_interval, } } - - pub(crate) fn number_of_rekeys(&self) -> u64 { - self.number_of_rekeys - } } impl KeyTracker { diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channel/listener.rs b/implementations/rust/ockam/ockam_identity/src/secure_channel/listener.rs index 31a9838360e..6c5f62c4b62 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channel/listener.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channel/listener.rs @@ -10,13 +10,11 @@ use crate::secure_channel::handshake_worker::HandshakeWorker; use crate::secure_channel::options::SecureChannelListenerOptions; use crate::secure_channel::role::Role; use crate::secure_channels::secure_channels::SecureChannels; -use crate::SecureChannelRepository; pub(crate) struct SecureChannelListenerWorker { secure_channels: Arc, identifier: Identifier, options: SecureChannelListenerOptions, - secure_channel_repository: Option>, } impl SecureChannelListenerWorker { @@ -25,17 +23,10 @@ impl SecureChannelListenerWorker { identifier: Identifier, options: SecureChannelListenerOptions, ) -> Self { - let secure_channel_repository = if options.is_persistent { - Some(secure_channels.secure_channel_repository()) - } else { - None - }; - Self { secure_channels, identifier, options, - secure_channel_repository, } } @@ -110,8 +101,6 @@ impl Worker for SecureChannelListenerWorker { None, None, Role::Responder, - self.options.key_exchange_only, - self.secure_channel_repository.clone(), RemoteRoute::create(), ) .await?; diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channel/mod.rs b/implementations/rust/ockam/ockam_identity/src/secure_channel/mod.rs index 438cf5396fa..92f90966911 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channel/mod.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channel/mod.rs @@ -21,7 +21,6 @@ pub mod trust_policy; pub use access_control::*; pub(crate) use addresses::*; pub use api::*; -pub(crate) use decryptor::*; pub(crate) use encryptor_worker::*; pub(crate) use handshake::*; pub(crate) use listener::*; @@ -194,7 +193,7 @@ mod tests { let key_on_v2 = vault2.convert_secret_buffer_to_aead_key(key_on_v2).await?; Ok(( - Encryptor::new(key_on_v1, 0.into(), vault1, true), + Encryptor::new(key_on_v1, 0.into(), vault1), Decryptor::new(key_on_v2, vault2), )) } diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channel/options.rs b/implementations/rust/ockam/ockam_identity/src/secure_channel/options.rs index 9166ee4e11d..4489525beb8 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channel/options.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channel/options.rs @@ -34,9 +34,6 @@ pub struct SecureChannelOptions { // To obtain our credentials pub(crate) credential_retriever_creator: Option>, pub(crate) timeout: Duration, - pub(crate) key_exchange_only: bool, - // Secure Channel will be persisted (currently only supported for key_exchange_only = true) - pub(crate) is_persistent: bool, } impl fmt::Debug for SecureChannelOptions { @@ -55,8 +52,6 @@ impl SecureChannelOptions { authority: None, credential_retriever_creator: None, timeout: DEFAULT_TIMEOUT, - key_exchange_only: false, - is_persistent: false, } } @@ -101,24 +96,6 @@ impl SecureChannelOptions { pub fn producer_flow_control_id(&self) -> FlowControlId { self.flow_control_id.clone() } - - /// The secure channel will be used to exchange key only. - /// In this mode, the secure channel cannot be used to exchange messages, and key rotation - /// is disabled along with automatic credential refresh. - pub fn key_exchange_only(mut self) -> Self { - self.key_exchange_only = true; - self - } - - /// Secure Channel will be persisted after a successful handshake - /// NOTE: Currently only supported after setting key_exchange_only = true - pub fn persist(mut self) -> Result { - if !self.key_exchange_only { - return Err(IdentityError::PersistentSupportIsLimited.into()); - } - self.is_persistent = true; - Ok(self) - } } impl SecureChannelOptions { @@ -182,9 +159,6 @@ pub struct SecureChannelListenerOptions { pub(crate) authority: Option, // To obtain our credentials pub(crate) credential_retriever_creator: Option>, - pub(crate) key_exchange_only: bool, - // Secure Channel will be persisted (currently only supported for key_exchange_only = true) - pub(crate) is_persistent: bool, } impl fmt::Debug for SecureChannelListenerOptions { @@ -205,8 +179,6 @@ impl SecureChannelListenerOptions { trust_policy: Arc::new(TrustEveryonePolicy), authority: None, credential_retriever_creator: None, - key_exchange_only: false, - is_persistent: false, } } @@ -254,24 +226,6 @@ impl SecureChannelListenerOptions { pub fn spawner_flow_control_id(&self) -> FlowControlId { self.flow_control_id.clone() } - - /// The listener will be used to exchange key only. - /// In this mode, the secure channel cannot be used to exchange messages, and key rotation - /// is disabled along with automatic credential refresh. - pub fn key_exchange_only(mut self) -> Self { - self.key_exchange_only = true; - self - } - - /// Secure Channel will be persisted after a successful handshake - /// NOTE: Currently only supported after setting key_exchange_only = true - pub fn persist(mut self) -> Result { - if !self.key_exchange_only { - return Err(IdentityError::PersistentSupportIsLimited.into()); - } - self.is_persistent = true; - Ok(self) - } } impl SecureChannelListenerOptions { diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channels/common.rs b/implementations/rust/ockam/ockam_identity/src/secure_channels/common.rs index 5171ff0acc4..5c27af6d864 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channels/common.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channels/common.rs @@ -15,7 +15,6 @@ pub struct SecureChannel { their_identifier: Identifier, encryptor_remote_route: Arc>, addresses: Addresses, - is_key_exchange_only: bool, flow_control_id: FlowControlId, } @@ -42,7 +41,6 @@ impl SecureChannel { their_identifier: Identifier, encryptor_remote_route: Arc>, addresses: Addresses, - is_key_exchange_only: bool, flow_control_id: FlowControlId, ) -> Self { Self { @@ -50,7 +48,6 @@ impl SecureChannel { their_identifier, encryptor_remote_route, addresses, - is_key_exchange_only, flow_control_id, } } @@ -107,11 +104,7 @@ impl SecureChannel { Ok(()) } - /// This secure channel is used only for handshake, further encryption happens using - /// api address. Encryption part may be absent. - pub fn is_key_exchange_only(&self) -> bool { - self.is_key_exchange_only - } + /// The Identifier of the other side pub fn their_identifier(&self) -> &Identifier { &self.their_identifier @@ -125,7 +118,6 @@ impl SecureChannel { pub struct SecureChannelListener { #[n(1)] address: Address, #[n(2)] flow_control_id: FlowControlId, - #[n(3)] is_key_exchange_only: bool, } impl fmt::Display for SecureChannelListener { @@ -140,14 +132,9 @@ impl fmt::Display for SecureChannelListener { impl SecureChannelListener { /// Constructor. - pub fn new( - address: Address, - is_key_exchange_only: bool, - flow_control_id: FlowControlId, - ) -> Self { + pub fn new(address: Address, flow_control_id: FlowControlId) -> Self { Self { address, - is_key_exchange_only, flow_control_id, } } @@ -161,9 +148,4 @@ impl SecureChannelListener { pub fn flow_control_id(&self) -> &FlowControlId { &self.flow_control_id } - /// This secure channel listener is used only for handshake, further encryption happens using - /// api address. Encryption part may be absent. - pub fn is_key_exchange_only(&self) -> bool { - self.is_key_exchange_only - } } diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channels/secure_channels.rs b/implementations/rust/ockam/ockam_identity/src/secure_channels/secure_channels.rs index 9546970d2b2..8297a343768 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channels/secure_channels.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channels/secure_channels.rs @@ -1,32 +1,24 @@ -use core::sync::atomic::AtomicBool; use ockam_core::compat::sync::Arc; -use ockam_core::flow_control::FlowControls; use ockam_core::Result; use ockam_core::{Address, Route}; -use ockam_node::{Context, WorkerBuilder}; -use tracing::info; +use ockam_node::Context; use crate::identities::Identities; use crate::models::Identifier; use crate::secure_channel::handshake_worker::HandshakeWorker; use crate::secure_channel::{ - Addresses, DecryptorHandler, RemoteRoute, Role, SecureChannelListenerOptions, - SecureChannelListenerWorker, SecureChannelOptions, SecureChannelRegistry, - SecureChannelSharedState, + Addresses, RemoteRoute, Role, SecureChannelListenerOptions, SecureChannelListenerWorker, + SecureChannelOptions, SecureChannelRegistry, }; #[cfg(feature = "storage")] use crate::SecureChannelsBuilder; -use crate::{ - IdentityError, SecureChannel, SecureChannelListener, SecureChannelRegistryEntry, - SecureChannelRepository, Vault, -}; +use crate::{IdentityError, SecureChannel, SecureChannelListener, Vault}; /// Identity implementation #[derive(Clone)] pub struct SecureChannels { pub(crate) identities: Arc, pub(crate) secure_channel_registry: SecureChannelRegistry, - pub(crate) secure_channel_repository: Arc, } impl SecureChannels { @@ -34,25 +26,16 @@ impl SecureChannels { pub fn new( identities: Arc, secure_channel_registry: SecureChannelRegistry, - secure_channel_repository: Arc, ) -> Self { Self { identities, secure_channel_registry, - secure_channel_repository, } } /// Constructor - pub fn from_identities( - identities: Arc, - secure_channel_repository: Arc, - ) -> Arc { - Arc::new(Self::new( - identities, - SecureChannelRegistry::default(), - secure_channel_repository, - )) + pub fn from_identities(identities: Arc) -> Arc { + Arc::new(Self::new(identities, SecureChannelRegistry::default())) } /// Return the identities services associated to this service @@ -70,11 +53,6 @@ impl SecureChannels { self.secure_channel_registry.clone() } - /// Return the secure channel repository - pub fn secure_channel_repository(&self) -> Arc { - self.secure_channel_repository.clone() - } - /// Create a builder for secure channels #[cfg(feature = "storage")] pub async fn builder() -> Result { @@ -97,7 +75,6 @@ impl SecureChannels { ) -> Result { let address = address.into(); let options = options.into(); - let key_exchange_only = options.key_exchange_only; let flow_control_id = options.flow_control_id.clone(); SecureChannelListenerWorker::create( @@ -109,11 +86,7 @@ impl SecureChannels { ) .await?; - Ok(SecureChannelListener::new( - address, - key_exchange_only, - flow_control_id, - )) + Ok(SecureChannelListener::new(address, flow_control_id)) } /// Initiate a SecureChannel using `Route` to the SecureChannel listener and [`SecureChannelOptions`] @@ -151,12 +124,6 @@ impl SecureChannels { None => None, }; - let secure_channel_repository = if options.is_persistent { - Some(self.secure_channel_repository()) - } else { - None - }; - let encryptor_remote_route = RemoteRoute::create(); let Some(their_identifier) = HandshakeWorker::create( ctx, @@ -171,8 +138,6 @@ impl SecureChannels { Some(route), Some(options.timeout), Role::Initiator, - options.key_exchange_only, - secure_channel_repository, encryptor_remote_route.clone(), ) .await? @@ -185,112 +150,10 @@ impl SecureChannels { their_identifier, encryptor_remote_route, addresses, - options.key_exchange_only, flow_control_id, )) } - /// Start a decryptor side for a previously existed and persisted secure channel - /// Only decryptor api part is started - pub async fn start_persisted_secure_channel_decryptor( - &self, - ctx: &Context, - decryptor_remote_address: &Address, - ) -> Result { - info!( - "Starting persisted secure channel: {}", - decryptor_remote_address - ); - - let Some(persisted_secure_channel) = self - .secure_channel_repository - .get(decryptor_remote_address) - .await? - else { - return Err(IdentityError::PersistentSecureChannelNotFound)?; - }; - - let decryption_key = persisted_secure_channel.decryption_key_handle().clone(); - - self.vault() - .secure_channel_vault - .load_aead_key(&decryption_key) - .await?; - - let my_identifier = persisted_secure_channel.my_identifier(); - let their_identifier = persisted_secure_channel.their_identifier(); - let role = persisted_secure_channel.role(); - let shared_state = SecureChannelSharedState { - remote_route: RemoteRoute::create(), // Unused - should_send_close: Arc::new(AtomicBool::new(false)), // Don't need to send anything - }; - - let mut addresses = Addresses::generate(role); - // FIXME: All other addresses except these two are random and incorrect, we don't use them - // for now though - addresses.decryptor_remote = persisted_secure_channel.decryptor_remote().clone(); - addresses.decryptor_api = persisted_secure_channel.decryptor_api().clone(); - - let decryptor_handler = DecryptorHandler::new( - self.identities(), - None, // We don't need authority, we won't verify any credentials - role, - true, - addresses.clone(), - decryption_key, - self.vault().secure_channel_vault.clone(), - their_identifier.clone(), - shared_state.clone(), - ); - - let decryptor_worker = HandshakeWorker::new( - Arc::new(self.clone()), - None, // No callback will happen - None, - my_identifier.clone(), - addresses.clone(), - role, - true, - None, // No remote interaction - Some(decryptor_handler), - None, // We don't need authority, we won't verify any credentials - self.identities.change_history_repository(), - None, // We don't need credential retriever, we won't present any credentials - // Key exchange only secure channel's state is unchanged after the initial creation, so no need to update it - None, - shared_state.clone(), - ); - - WorkerBuilder::new(decryptor_worker) - .with_address(addresses.decryptor_api.clone()) // We only need API address here - .start(ctx) - .await?; - - let sc = SecureChannel::new( - ctx.flow_controls().clone(), - their_identifier.clone(), - shared_state.remote_route, - addresses.clone(), - true, - FlowControls::generate_flow_control_id(), // This is random and doesn't matter - ); - - let info = SecureChannelRegistryEntry::new( - addresses.encryptor.clone(), - addresses.encryptor_api.clone(), - addresses.decryptor_remote.clone(), - addresses.decryptor_api.clone(), - role.is_initiator(), - my_identifier.clone(), - their_identifier.clone(), - Address::random_local(), // Random, unused for now - ); - - self.secure_channel_registry.register_channel(info)?; - - Ok(sc) - } - /// Stop a SecureChannel given an encryptor address pub async fn stop_secure_channel(&self, ctx: &Context, channel: &Address) -> Result<()> { ctx.stop_worker(channel.clone()).await diff --git a/implementations/rust/ockam/ockam_identity/src/secure_channels/secure_channels_builder.rs b/implementations/rust/ockam/ockam_identity/src/secure_channels/secure_channels_builder.rs index 53523d2ab34..0d3f99bb6bf 100644 --- a/implementations/rust/ockam/ockam_identity/src/secure_channels/secure_channels_builder.rs +++ b/implementations/rust/ockam/ockam_identity/src/secure_channels/secure_channels_builder.rs @@ -103,10 +103,6 @@ impl SecureChannelsBuilder { /// Build secure channels pub fn build(self) -> Arc { let identities = self.identities_builder.build(); - Arc::new(SecureChannels::new( - identities, - self.registry, - self.secure_channel_repository, - )) + Arc::new(SecureChannels::new(identities, self.registry)) } } diff --git a/implementations/rust/ockam/ockam_identity/tests/channel.rs b/implementations/rust/ockam/ockam_identity/tests/channel.rs index f9b4e5a555d..a625737731d 100644 --- a/implementations/rust/ockam/ockam_identity/tests/channel.rs +++ b/implementations/rust/ockam/ockam_identity/tests/channel.rs @@ -10,7 +10,6 @@ use ockam_identity::models::{CredentialSchemaIdentifier, Identifier}; use ockam_identity::secure_channels::secure_channels; use ockam_identity::utils::AttributesBuilder; use ockam_identity::{ - DecryptionRequest, DecryptionResponse, EncryptionRequest, EncryptionResponse, IdentityAccessControlBuilder, SecureChannelListenerOptions, SecureChannelOptions, SecureChannels, TrustEveryonePolicy, TrustIdentifierPolicy, Vault, }; @@ -402,121 +401,82 @@ async fn test_channel_registry(ctx: &mut Context) -> Result<()> { Ok(()) } -#[ockam_macros::test] -async fn test_channel_api(ctx: &mut Context) -> Result<()> { - let secure_channels = secure_channels().await?; - let identities_creation = secure_channels.identities().identities_creation(); - - let alice = identities_creation.create_identity().await?; - let bob = identities_creation.create_identity().await?; - - let bob_listener = secure_channels - .create_secure_channel_listener( - ctx, - &bob, - "bob_listener", - SecureChannelListenerOptions::new(), - ) - .await?; - - let alice_channel = secure_channels - .create_secure_channel( - ctx, - &alice, - route!["bob_listener"], - SecureChannelOptions::new(), - ) - .await?; - - let mut bob_ctx = ctx - .new_detached_with_mailboxes(Mailboxes::main( - "bob", - Arc::new(AllowAll), - Arc::new(AllowAll), - )) - .await?; - - ctx.flow_controls() - .add_consumer("bob", bob_listener.flow_control_id()); - - ctx.send( - route![alice_channel.clone(), "bob"], - "Hello, Alice!".to_string(), - ) - .await?; - - let msg = bob_ctx.receive::().await?; - let return_route = msg.return_route().clone(); - - assert_eq!("Hello, Alice!", msg.into_body()?); - - let bob_channel = return_route.next().unwrap().clone(); - - let alice_channel_data = secure_channels - .secure_channel_registry() - .get_channel_by_encryptor_address(alice_channel.encryptor_address()) - .unwrap(); - - let bob_channel_data = secure_channels - .secure_channel_registry() - .get_channel_by_encryptor_address(&bob_channel) - .unwrap(); - - let encrypted_alice: EncryptionResponse = ctx - .send_and_receive( - route![alice_channel_data.encryptor_api_address().clone()], - EncryptionRequest::Encrypt(b"Ping".to_vec()), - ) - .await?; - let encrypted_alice = match encrypted_alice { - EncryptionResponse::Ok(p) => p, - EncryptionResponse::Err(err) => return Err(err), - }; - - let encrypted_bob: EncryptionResponse = ctx - .send_and_receive( - route![bob_channel_data.encryptor_api_address().clone()], - EncryptionRequest::Encrypt(b"Pong".to_vec()), - ) - .await?; - let encrypted_bob = match encrypted_bob { - EncryptionResponse::Ok(p) => p, - EncryptionResponse::Err(err) => return Err(err), - }; - - let decrypted_alice: DecryptionResponse = ctx - .send_and_receive( - route![alice_channel_data.decryptor_api_address().clone()], - DecryptionRequest::Decrypt { - ciphertext: encrypted_bob, - rekey_counter: None, - }, - ) - .await?; - let decrypted_alice = match decrypted_alice { - DecryptionResponse::Ok(p) => p, - DecryptionResponse::Err(err) => return Err(err), - }; - - let decrypted_bob: DecryptionResponse = ctx - .send_and_receive( - route![bob_channel_data.decryptor_api_address().clone()], - DecryptionRequest::Decrypt { - ciphertext: encrypted_alice, - rekey_counter: None, - }, - ) - .await?; - let decrypted_bob = match decrypted_bob { - DecryptionResponse::Ok(p) => p, - DecryptionResponse::Err(err) => return Err(err), - }; - - assert_eq!(decrypted_alice, b"Pong"); - assert_eq!(decrypted_bob, b"Ping"); - - Ok(()) -} +// #[ockam_macros::test] +// async fn test_channel_api(ctx: &mut Context) -> Result<()> { +// let secure_channels = secure_channels().await?; +// let identities_creation = secure_channels.identities().identities_creation(); +// +// let alice = identities_creation.create_identity().await?; +// let bob = identities_creation.create_identity().await?; +// +// let bob_listener = secure_channels +// .create_secure_channel_listener( +// ctx, +// &bob, +// "bob_listener", +// SecureChannelListenerOptions::new(), +// ) +// .await?; +// +// let alice_channel = secure_channels +// .create_secure_channel( +// ctx, +// &alice, +// route!["bob_listener"], +// SecureChannelOptions::new(), +// ) +// .await?; +// +// let mut bob_ctx = ctx +// .new_detached_with_mailboxes(Mailboxes::main( +// "bob", +// Arc::new(AllowAll), +// Arc::new(AllowAll), +// )) +// .await?; +// +// ctx.flow_controls() +// .add_consumer("bob", bob_listener.flow_control_id()); +// +// ctx.send( +// route![alice_channel.clone(), "bob"], +// "Hello, Alice!".to_string(), +// ) +// .await?; +// +// let msg = bob_ctx.receive::().await?; +// let return_route = msg.return_route().clone(); +// +// assert_eq!("Hello, Alice!", msg.into_body()?); +// +// let bob_channel = return_route.next().unwrap().clone(); +// +// let alice_channel_data = secure_channels +// .secure_channel_registry() +// .get_channel_by_encryptor_address(alice_channel.encryptor_address()) +// .unwrap(); +// +// let bob_channel_data = secure_channels +// .secure_channel_registry() +// .get_channel_by_encryptor_address(&bob_channel) +// .unwrap(); +// +// let encrypted_alice: SecureChannelApiResponse = ctx +// .send_and_receive( +// route![alice_channel_data.encryptor_api_address().clone()], +// SecureChannelApiRequest::Encrypt(b"Ping".to_vec()), +// ) +// .await?; +// let encrypted_alice = match encrypted_alice { +// SecureChannelApiResponse::Ok(p) => p, +// SecureChannelApiResponse::Err(err) => return Err(err), +// }; +// +// assert_eq!(decrypted_alice, b"Pong"); +// assert_eq!(decrypted_bob, b"Ping"); +// +// Ok(()) +// } #[ockam_macros::test] async fn test_tunneled_secure_channel_works(ctx: &mut Context) -> Result<()> { diff --git a/implementations/rust/ockam/ockam_identity/tests/persistence.rs b/implementations/rust/ockam/ockam_identity/tests/persistence.rs deleted file mode 100644 index 4ea4ea63027..00000000000 --- a/implementations/rust/ockam/ockam_identity/tests/persistence.rs +++ /dev/null @@ -1,408 +0,0 @@ -use ockam_core::{route, Address}; -use ockam_identity::{ - secure_channels, DecryptionRequest, DecryptionResponse, EncryptionRequest, EncryptionResponse, - SecureChannelListenerOptions, SecureChannelOptions, SecureChannelSqlxDatabase, SecureChannels, -}; -use ockam_node::compat::futures::FutureExt; -use ockam_node::database::SqlxDatabase; -use ockam_node::{Context, NodeBuilder}; -use ockam_vault::storage::SecretsSqlxDatabase; -use std::sync::Arc; -use std::time::Duration; -use tempfile::NamedTempFile; - -#[ockam_macros::test] -async fn test_key_exchange_only(ctx: &mut Context) -> ockam_core::Result<()> { - let secure_channels_alice = secure_channels().await?; - let secure_channels_bob = secure_channels().await?; - - let alice = secure_channels_alice - .identities() - .identities_creation() - .create_identity() - .await?; - let bob = secure_channels_bob - .identities() - .identities_creation() - .create_identity() - .await?; - - let bob_options = SecureChannelListenerOptions::new().key_exchange_only(); - secure_channels_bob - .create_secure_channel_listener(ctx, &bob, "bob_listener", bob_options) - .await?; - - let alice_options = SecureChannelOptions::new().key_exchange_only(); - let alice_channel = secure_channels_alice - .create_secure_channel(ctx, &alice, route!["bob_listener"], alice_options) - .await?; - - ctx.sleep(Duration::from_millis(200)).await; - - let bob_channel = secure_channels_bob - .secure_channel_registry() - .get_channel_list()[0] - .clone(); - - let msg1_alice = vec![1u8; 32]; - let msg2_alice = vec![2u8; 32]; - - let msg1_bob = vec![1u8; 32]; - let msg2_bob = vec![2u8; 32]; - - let EncryptionResponse::Ok(encrypted_msg1_alice) = ctx - .send_and_receive( - route![alice_channel.encryptor_api_address().clone()], - EncryptionRequest::Encrypt(msg1_alice.clone()), - ) - .await? - else { - panic!() - }; - let EncryptionResponse::Ok(encrypted_msg2_alice) = ctx - .send_and_receive( - route![alice_channel.encryptor_api_address().clone()], - EncryptionRequest::Encrypt(msg2_alice.clone()), - ) - .await? - else { - panic!() - }; - let EncryptionResponse::Ok(encrypted_msg1_bob) = ctx - .send_and_receive( - route![bob_channel.encryptor_api_address().clone()], - EncryptionRequest::Encrypt(msg1_bob.clone()), - ) - .await? - else { - panic!() - }; - let EncryptionResponse::Ok(encrypted_msg2_bob) = ctx - .send_and_receive( - route![bob_channel.encryptor_api_address().clone()], - EncryptionRequest::Encrypt(msg2_bob.clone()), - ) - .await? - else { - panic!() - }; - - let DecryptionResponse::Ok(decrypted_msg1_alice) = ctx - .send_and_receive( - route![bob_channel.decryptor_api_address().clone()], - DecryptionRequest::Decrypt { - ciphertext: encrypted_msg1_alice, - rekey_counter: None, - }, - ) - .await? - else { - panic!() - }; - - let DecryptionResponse::Ok(decrypted_msg2_alice) = ctx - .send_and_receive( - route![bob_channel.decryptor_api_address().clone()], - DecryptionRequest::Decrypt { - ciphertext: encrypted_msg2_alice, - rekey_counter: None, - }, - ) - .await? - else { - panic!() - }; - - let DecryptionResponse::Ok(decrypted_msg1_bob) = ctx - .send_and_receive( - route![alice_channel.decryptor_api_address().clone()], - DecryptionRequest::Decrypt { - ciphertext: encrypted_msg1_bob, - rekey_counter: None, - }, - ) - .await? - else { - panic!() - }; - - let DecryptionResponse::Ok(decrypted_msg2_bob) = ctx - .send_and_receive( - route![alice_channel.decryptor_api_address().clone()], - DecryptionRequest::Decrypt { - ciphertext: encrypted_msg2_bob, - rekey_counter: None, - }, - ) - .await? - else { - panic!() - }; - - assert_eq!(msg1_alice, decrypted_msg1_alice); - assert_eq!(msg2_alice, decrypted_msg2_alice); - assert_eq!(msg1_bob, decrypted_msg1_bob); - assert_eq!(msg2_bob, decrypted_msg2_bob); - - Ok(()) -} - -#[test] -fn test_persistence() -> ockam_core::Result<()> { - let (_db_file_alice, db_file_alice_path) = NamedTempFile::new().unwrap().keep().unwrap(); - let db_file_alice_path_clone = db_file_alice_path.clone(); - - let (_db_file_bob, db_file_bob_path) = NamedTempFile::new().unwrap().keep().unwrap(); - let db_file_bob_path_clone = db_file_bob_path.clone(); - - struct PassBetweenEnv { - decryptor_api_address_alice: Address, - decryptor_remote_address_alice: Address, - decryptor_api_address_bob: Address, - decryptor_remote_address_bob: Address, - msg1_alice: Vec, - msg2_alice: Vec, - msg1_bob: Vec, - msg2_bob: Vec, - encrypted_msg1_alice: Vec, - encrypted_msg2_alice: Vec, - encrypted_msg1_bob: Vec, - encrypted_msg2_bob: Vec, - } - - let (ctx1, mut executor1) = NodeBuilder::new().build(); - let data = executor1 - .execute(async move { - let data = std::panic::AssertUnwindSafe(async { - let db_alice = - SqlxDatabase::create_sqlite(db_file_alice_path_clone.as_path()).await?; - let secure_channel_repository_alice = - Arc::new(SecureChannelSqlxDatabase::new(db_alice.clone())); - let secrets_repository_alice = Arc::new(SecretsSqlxDatabase::new(db_alice)); - let db_bob = SqlxDatabase::create_sqlite(db_file_bob_path_clone.as_path()).await?; - let secure_channel_repository_bob = - Arc::new(SecureChannelSqlxDatabase::new(db_bob.clone())); - let secrets_repository_bob = Arc::new(SecretsSqlxDatabase::new(db_bob)); - - let secure_channels_alice = SecureChannels::builder() - .await? - .with_secure_channel_repository(secure_channel_repository_alice.clone()) - .with_secrets_repository(secrets_repository_alice) - .build(); - let secure_channels_bob = SecureChannels::builder() - .await? - .with_secure_channel_repository(secure_channel_repository_bob.clone()) - .with_secrets_repository(secrets_repository_bob) - .build(); - - let alice = secure_channels_alice - .identities() - .identities_creation() - .create_identity() - .await?; - let bob = secure_channels_bob - .identities() - .identities_creation() - .create_identity() - .await?; - - let bob_options = SecureChannelListenerOptions::new() - .key_exchange_only() - .persist()?; - secure_channels_bob - .create_secure_channel_listener(&ctx1, &bob, "bob_listener", bob_options) - .await?; - - let alice_options = SecureChannelOptions::new().key_exchange_only().persist()?; - let alice_channel = secure_channels_alice - .create_secure_channel(&ctx1, &alice, route!["bob_listener"], alice_options) - .await?; - - ctx1.sleep(Duration::from_millis(200)).await; - - let bob_channel = secure_channels_bob - .secure_channel_registry() - .get_channel_list()[0] - .clone(); - - let msg1_alice = vec![1u8; 32]; - let msg2_alice = vec![2u8; 32]; - - let msg1_bob = vec![1u8; 32]; - let msg2_bob = vec![2u8; 32]; - - let EncryptionResponse::Ok(encrypted_msg1_alice) = ctx1 - .send_and_receive( - route![alice_channel.encryptor_api_address().clone()], - EncryptionRequest::Encrypt(msg1_alice.clone()), - ) - .await? - else { - panic!() - }; - let EncryptionResponse::Ok(encrypted_msg2_alice) = ctx1 - .send_and_receive( - route![alice_channel.encryptor_api_address().clone()], - EncryptionRequest::Encrypt(msg2_alice.clone()), - ) - .await? - else { - panic!() - }; - let EncryptionResponse::Ok(encrypted_msg1_bob) = ctx1 - .send_and_receive( - route![bob_channel.encryptor_api_address().clone()], - EncryptionRequest::Encrypt(msg1_bob.clone()), - ) - .await? - else { - panic!() - }; - let EncryptionResponse::Ok(encrypted_msg2_bob) = ctx1 - .send_and_receive( - route![bob_channel.encryptor_api_address().clone()], - EncryptionRequest::Encrypt(msg2_bob.clone()), - ) - .await? - else { - panic!() - }; - - let data = PassBetweenEnv { - decryptor_api_address_alice: alice_channel.decryptor_api_address().clone(), - decryptor_remote_address_alice: alice_channel - .decryptor_remote_address() - .clone(), - decryptor_api_address_bob: bob_channel.decryptor_api_address().clone(), - decryptor_remote_address_bob: bob_channel.decryptor_messaging_address().clone(), - msg1_alice, - msg2_alice, - msg1_bob, - msg2_bob, - encrypted_msg1_alice, - encrypted_msg2_alice, - encrypted_msg1_bob, - encrypted_msg2_bob, - }; - - Result::::Ok(data) - }) - .catch_unwind() - .await; - - ctx1.stop().await?; - - data.unwrap() - }) - .unwrap() - .unwrap(); - - let (ctx2, mut executor2) = NodeBuilder::new().build(); - executor2 - .execute(async move { - let res = std::panic::AssertUnwindSafe(async { - let db_alice = SqlxDatabase::create_sqlite(db_file_alice_path.as_path()).await?; - let secure_channel_repository_alice = - Arc::new(SecureChannelSqlxDatabase::new(db_alice.clone())); - let secrets_repository_alice = Arc::new(SecretsSqlxDatabase::new(db_alice)); - let db_bob = SqlxDatabase::create_sqlite(db_file_bob_path.as_path()).await?; - let secure_channel_repository_bob = - Arc::new(SecureChannelSqlxDatabase::new(db_bob.clone())); - let secrets_repository_bob = Arc::new(SecretsSqlxDatabase::new(db_bob)); - - let secure_channels_alice = SecureChannels::builder() - .await? - .with_secure_channel_repository(secure_channel_repository_alice.clone()) - .with_secrets_repository(secrets_repository_alice) - .build(); - let secure_channels_bob = SecureChannels::builder() - .await? - .with_secure_channel_repository(secure_channel_repository_bob.clone()) - .with_secrets_repository(secrets_repository_bob) - .build(); - - secure_channels_alice - .start_persisted_secure_channel_decryptor( - &ctx2, - &data.decryptor_remote_address_alice, - ) - .await?; - - secure_channels_bob - .start_persisted_secure_channel_decryptor( - &ctx2, - &data.decryptor_remote_address_bob, - ) - .await?; - - let DecryptionResponse::Ok(decrypted_msg1_alice) = ctx2 - .send_and_receive( - route![data.decryptor_api_address_bob.clone()], - DecryptionRequest::Decrypt { - ciphertext: data.encrypted_msg1_alice, - rekey_counter: None, - }, - ) - .await? - else { - panic!() - }; - - let DecryptionResponse::Ok(decrypted_msg2_alice) = ctx2 - .send_and_receive( - route![data.decryptor_api_address_bob.clone()], - DecryptionRequest::Decrypt { - ciphertext: data.encrypted_msg2_alice, - rekey_counter: None, - }, - ) - .await? - else { - panic!() - }; - - let DecryptionResponse::Ok(decrypted_msg1_bob) = ctx2 - .send_and_receive( - route![data.decryptor_api_address_alice.clone()], - DecryptionRequest::Decrypt { - ciphertext: data.encrypted_msg1_bob, - rekey_counter: None, - }, - ) - .await? - else { - panic!() - }; - - let DecryptionResponse::Ok(decrypted_msg2_bob) = ctx2 - .send_and_receive( - route![data.decryptor_api_address_alice.clone()], - DecryptionRequest::Decrypt { - ciphertext: data.encrypted_msg2_bob, - rekey_counter: None, - }, - ) - .await? - else { - panic!() - }; - - assert_eq!(data.msg1_alice, decrypted_msg1_alice); - assert_eq!(data.msg2_alice, decrypted_msg2_alice); - assert_eq!(data.msg1_bob, decrypted_msg1_bob); - assert_eq!(data.msg2_bob, decrypted_msg2_bob); - - ockam_core::Result::<()>::Ok(()) - }) - .catch_unwind() - .await; - - ctx2.stop().await?; - - res.unwrap() - }) - .unwrap() - .unwrap(); - - Ok(()) -}