Skip to main content

lib_q_aead/
romulus_n.rs

1//! Romulus-N AEAD — registry-facing type.
2
3use alloc::boxed::Box;
4use alloc::vec::Vec;
5
6use lib_q_core::{
7    Aead,
8    AeadDecryptSemantic,
9    AeadKey,
10    Algorithm,
11    DecryptSemanticOutcome,
12    Nonce,
13    Result,
14};
15
16use crate::metadata::{
17    AeadMetadata,
18    AeadWithMetadata,
19};
20
21/// Romulus-N (nonce-based AEAD) for the lib-Q AEAD registry.
22pub struct RomulusNAead {
23    metadata: &'static AeadMetadata,
24    inner: lib_q_romulus::RomulusNAead,
25}
26
27impl RomulusNAead {
28    pub fn new() -> Self {
29        Self {
30            metadata: crate::metadata::get_metadata(Algorithm::RomulusN)
31                .expect("Romulus-N metadata"),
32            inner: lib_q_romulus::RomulusNAead::new(),
33        }
34    }
35}
36
37impl Aead for RomulusNAead {
38    fn encrypt(
39        &self,
40        key: &AeadKey,
41        nonce: &Nonce,
42        plaintext: &[u8],
43        associated_data: Option<&[u8]>,
44    ) -> Result<Vec<u8>> {
45        self.validate_key(key)?;
46        self.validate_nonce(nonce)?;
47        crate::security::validation::validate_plaintext(plaintext)?;
48        let ad = associated_data.unwrap_or(&[]);
49        crate::security::validation::validate_associated_data(ad)?;
50        self.inner.encrypt(key, nonce, plaintext, Some(ad))
51    }
52
53    fn decrypt(
54        &self,
55        key: &AeadKey,
56        nonce: &Nonce,
57        ciphertext: &[u8],
58        associated_data: Option<&[u8]>,
59    ) -> Result<Vec<u8>> {
60        self.validate_key(key)?;
61        self.validate_nonce(nonce)?;
62        self.validate_ciphertext_size(ciphertext.len())?;
63        crate::security::validation::validate_ciphertext(ciphertext)?;
64        let ad = associated_data.unwrap_or(&[]);
65        crate::security::validation::validate_associated_data(ad)?;
66        self.inner.decrypt(key, nonce, ciphertext, Some(ad))
67    }
68}
69
70impl AeadDecryptSemantic for RomulusNAead {
71    fn decrypt_semantic(
72        &self,
73        key: &AeadKey,
74        nonce: &Nonce,
75        ciphertext: &[u8],
76        associated_data: Option<&[u8]>,
77    ) -> Result<DecryptSemanticOutcome> {
78        self.validate_key(key)?;
79        self.validate_nonce(nonce)?;
80        self.validate_ciphertext_size(ciphertext.len())?;
81        crate::security::validation::validate_ciphertext(ciphertext)?;
82        let ad = associated_data.unwrap_or(&[]);
83        crate::security::validation::validate_associated_data(ad)?;
84        self.inner
85            .decrypt_semantic(key, nonce, ciphertext, Some(ad))
86    }
87}
88
89impl AeadWithMetadata for RomulusNAead {
90    fn metadata(&self) -> &'static AeadMetadata {
91        self.metadata
92    }
93}
94
95impl Default for RomulusNAead {
96    fn default() -> Self {
97        Self::new()
98    }
99}
100
101impl crate::plugin::AeadPlugin for RomulusNAead {
102    fn algorithm(&self) -> Algorithm {
103        Algorithm::RomulusN
104    }
105
106    fn create(&self) -> Result<Box<dyn AeadWithMetadata>> {
107        Ok(Box::new(Self::new()))
108    }
109
110    fn metadata(&self) -> &'static AeadMetadata {
111        crate::metadata::get_metadata(Algorithm::RomulusN).expect("Romulus-N metadata")
112    }
113
114    fn name(&self) -> &'static str {
115        "Romulus-N"
116    }
117
118    fn version(&self) -> &'static str {
119        "1.3.0"
120    }
121
122    fn description(&self) -> &'static str {
123        "Romulus-N nonce-based AEAD (SKINNY-128-384+), 128-bit key/nonce/tag"
124    }
125}
126
127#[cfg(test)]
128mod tests {
129    use super::*;
130
131    #[test]
132    fn romulus_n_metadata_matches() {
133        let a = RomulusNAead::new();
134        assert_eq!(a.algorithm(), Algorithm::RomulusN);
135        assert_eq!(a.key_size(), 16);
136        assert_eq!(a.nonce_size(), 16);
137        assert_eq!(a.tag_size(), 16);
138    }
139}