use crate::{
messages::submessages::{elements::crypto_content::CryptoContent, secure_body::SecureBody},
rtps::Submessage,
security::SecurityResult,
};
use super::{
aes_gcm_gmac::{compute_mac, encrypt},
builtin_key::*,
key_material::*,
types::{BuiltinCryptoFooter, BuiltinInitializationVector, BuiltinMAC, ReceiverSpecificMAC},
};
fn compute_receiver_specific_macs(
initialization_vector: BuiltinInitializationVector,
receiver_specific_key_materials: &[ReceiverSpecificKeyMaterial],
common_mac: BuiltinMAC,
) -> SecurityResult<BuiltinCryptoFooter> {
SecurityResult::from_iter(receiver_specific_key_materials.iter().map(
|ReceiverSpecificKeyMaterial { key_id, key }| {
compute_mac(key, initialization_vector, &common_mac)
.map(|receiver_mac| ReceiverSpecificMAC {
receiver_mac_key_id: *key_id,
receiver_mac,
})
},
))
.map(|receiver_specific_macs| BuiltinCryptoFooter {
common_mac,
receiver_specific_macs,
})
}
pub(super) fn encode_gmac(
key: &BuiltinKey,
initialization_vector: BuiltinInitializationVector,
data: &[u8],
receiver_specific_key_materials: &[ReceiverSpecificKeyMaterial],
) -> SecurityResult<BuiltinCryptoFooter> {
compute_mac(key, initialization_vector, data)
.and_then(|common_mac| {
compute_receiver_specific_macs(
initialization_vector,
receiver_specific_key_materials,
common_mac,
)
})
}
pub(super) fn encode_gcm(
key: &BuiltinKey,
initialization_vector: BuiltinInitializationVector,
data: &[u8],
receiver_specific_key_materials: &[ReceiverSpecificKeyMaterial],
) -> SecurityResult<(Submessage, BuiltinCryptoFooter)> {
encrypt(key, initialization_vector, data).and_then(|(ciphertext, common_mac)| {
compute_receiver_specific_macs(
initialization_vector,
receiver_specific_key_materials,
common_mac,
)
.and_then(|footer| {
SecureBody {
crypto_content: CryptoContent::from(ciphertext),
}
.create_submessage(speedy::Endianness::BigEndian) .map(|submessage| (submessage, footer))
})
})
}