1use 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
21pub 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}