rustdds 0.11.8

Native Rust DDS implementation with RTPS
Documentation
#[allow(unused_imports)]
use log::{debug, error, info, trace, warn};

use crate::security::cryptographic::CryptoTransformKeyId;
use super::{
  aes_gcm_gmac::validate_mac,
  key_material::ReceiverSpecificKeyMaterial,
  types::{BuiltinInitializationVector, BuiltinMAC, ReceiverSpecificMAC},
  DecodeSessionMaterials,
};

fn find_receiver_specific_mac<'a>(
  receiver_specific_key_id: &CryptoTransformKeyId,
  receiver_specific_macs: &'a [ReceiverSpecificMAC],
) -> Option<&'a BuiltinMAC> {
  receiver_specific_macs
    .iter()
    .find(
      |ReceiverSpecificMAC {
         receiver_mac_key_id,
         ..
       }| receiver_mac_key_id.eq(receiver_specific_key_id),
    )
    .map(|ReceiverSpecificMAC { receiver_mac, .. }| receiver_mac)
}

pub(super) fn validate_receiver_specific_mac(
  decode_materials: &DecodeSessionMaterials,
  initialization_vector: &BuiltinInitializationVector,
  common_mac: &BuiltinMAC,
  receiver_specific_macs: &[ReceiverSpecificMAC],
) -> bool {
  if let DecodeSessionMaterials {
    receiver_specific_key: Some(ReceiverSpecificKeyMaterial { key_id, key }),
    ..
  } = decode_materials
  {
    if let Some(receiver_specific_mac) = find_receiver_specific_mac(key_id, receiver_specific_macs)
    {
      // The receiver-specific MAC is computed for common_mac, not the  ciphertext.
      // See 9.5.3.3.4
      validate_mac(
        key,
        *initialization_vector,
        common_mac,
        *receiver_specific_mac,
      )
      .map_or_else(
        |e| {
          error!("Decoding receiver-specific MAC failed: {e}");
          false
        },
        |_| true, // Success
      )
    } else {
      trace!(
        "No receiver-specific MAC found for the receiver-specific key id {key_id:?}, rejecting."
      );
      false
    }
  } else {
    // No receiver specific key so no receiver specific MAC expected
    true
  }
}