ring/aead/chacha20_poly1305/
integrated.rs1use super::{
16 super::{NONCE_LEN, TAG_LEN},
17 chacha::Overlapping,
18 check_input_lengths, Aad, InputTooLongError, Key, Nonce, Tag, KEY_LEN,
19};
20use cfg_if::cfg_if;
21
22macro_rules! declare_open {
23 ( $name:ident ) => {
24 prefixed_extern! {
25 fn $name(
26 out_plaintext: *mut u8,
27 ciphertext: *const u8,
28 plaintext_len: usize,
29 ad: *const u8,
30 ad_len: usize,
31 data: &mut InOut<open_data_in>,
32 );
33 }
34 };
35}
36
37macro_rules! declare_seal {
38 ( $name:ident ) => {
39 prefixed_extern! {
40 fn $name(
41 out_ciphertext: *mut u8,
42 plaintext: *const u8,
43 plaintext_len: usize,
44 ad: *const u8,
45 ad_len: usize,
46 data: &mut InOut<seal_data_in>,
47 );
48 }
49 };
50}
51
52cfg_if! {
53 if #[cfg(all(target_arch = "aarch64", target_endian = "little"))] {
54 use crate::cpu::arm::Neon;
55 type RequiredCpuFeatures = Neon;
56 type OptionalCpuFeatures = ();
57 } else {
58 use crate::cpu::intel::{Avx2, Bmi2, Sse41};
59 type RequiredCpuFeatures = Sse41;
60 type OptionalCpuFeatures = (Avx2, Bmi2);
61 }
62}
63
64pub(super) fn seal(
65 Key(key): &Key,
66 nonce: Nonce,
67 aad: Aad<&[u8]>,
68 in_out: &mut [u8],
69 required_cpu_features: RequiredCpuFeatures,
70 optional_cpu_features: Option<OptionalCpuFeatures>,
71) -> Result<Tag, InputTooLongError> {
72 check_input_lengths(aad, in_out)?;
73
74 #[repr(align(16), C)]
81 #[derive(Clone, Copy)]
82 struct seal_data_in {
83 key: [u32; KEY_LEN / 4],
84 counter: u32,
85 nonce: [u8; NONCE_LEN],
86 extra_ciphertext: *const u8,
87 extra_ciphertext_len: usize,
88 }
89
90 let mut data = InOut {
91 input: seal_data_in {
92 key: *key.words_less_safe(),
93 counter: 0,
94 nonce: *nonce.as_ref(),
95 extra_ciphertext: core::ptr::null(),
96 extra_ciphertext_len: 0,
97 },
98 };
99
100 let output = in_out.as_mut_ptr();
103 let input = in_out.as_ptr();
104 let len = in_out.len();
105 let ad = aad.as_ref().as_ptr();
106 let ad_len = aad.as_ref().len();
107
108 #[allow(clippy::needless_late_init)]
109 let tag;
110
111 cfg_if! {
112 if #[cfg(all(target_arch = "aarch64", target_endian = "little"))] {
113 declare_seal! { chacha20_poly1305_seal }
114 let _: Neon = required_cpu_features;
115 let _: Option<()> = optional_cpu_features;
116 tag = unsafe {
117 chacha20_poly1305_seal(output, input, len, ad, ad_len, &mut data);
118 &data.out.tag
119 };
120 } else {
121 let _: Sse41 = required_cpu_features;
122 if matches!(optional_cpu_features, Some((Avx2 { .. }, Bmi2 { .. }))) {
123 declare_seal! { chacha20_poly1305_seal_avx2 }
124 tag = unsafe {
125 chacha20_poly1305_seal_avx2(output, input, len, ad, ad_len, &mut data);
126 &data.out.tag
127 };
128 } else {
129 declare_seal! { chacha20_poly1305_seal_sse41 }
130 tag = unsafe {
131 chacha20_poly1305_seal_sse41(output, input, len, ad, ad_len, &mut data);
132 &data.out.tag
133 };
134 }
135 }
136 }
137
138 Ok(Tag(*tag))
139}
140
141pub(super) fn open(
142 Key(key): &Key,
143 nonce: Nonce,
144 aad: Aad<&[u8]>,
145 in_out: Overlapping<'_>,
146 required_cpu_features: RequiredCpuFeatures,
147 optional_cpu_features: Option<OptionalCpuFeatures>,
148) -> Result<Tag, InputTooLongError> {
149 check_input_lengths(aad, in_out.input())?;
150
151 #[derive(Copy, Clone)]
158 #[repr(align(16), C)]
159 struct open_data_in {
160 key: [u32; KEY_LEN / 4],
161 counter: u32,
162 nonce: [u8; NONCE_LEN],
163 }
164
165 let mut data = InOut {
166 input: open_data_in {
167 key: *key.words_less_safe(),
168 counter: 0,
169 nonce: *nonce.as_ref(),
170 },
171 };
172
173 in_out.with_input_output_len(|input, output, len| {
174 let ad = aad.as_ref().as_ptr();
175 let ad_len = aad.as_ref().len();
176
177 #[allow(clippy::needless_late_init)]
178 let tag;
179
180 cfg_if! {
181 if #[cfg(all(target_arch = "aarch64", target_endian = "little"))] {
182 declare_open! { chacha20_poly1305_open }
183 let _: Neon = required_cpu_features;
184 let _: Option<()> = optional_cpu_features;
185 tag = unsafe {
186 chacha20_poly1305_open(output, input, len, ad, ad_len, &mut data);
187 &data.out.tag
188 };
189 } else {
190 let _: Sse41 = required_cpu_features;
191 if matches!(optional_cpu_features, Some((Avx2 { .. }, Bmi2 { .. }))) {
192 declare_open! { chacha20_poly1305_open_avx2 }
193 tag = unsafe {
194 chacha20_poly1305_open_avx2(output, input, len, ad, ad_len, &mut data);
195 &data.out.tag
196 };
197 } else {
198 declare_open! { chacha20_poly1305_open_sse41 }
199 tag = unsafe {
200 chacha20_poly1305_open_sse41(output, input, len, ad, ad_len, &mut data);
201 &data.out.tag
202 };
203 }
204 }
205 }
206
207 Ok(Tag(*tag))
208 })
209}
210
211#[repr(C)]
214pub(super) union InOut<T>
215where
216 T: Copy,
217{
218 pub(super) input: T,
219 pub(super) out: Out,
220}
221
222#[derive(Clone, Copy)]
227#[repr(align(16), C)]
228pub(super) struct Out {
229 pub(super) tag: [u8; TAG_LEN],
230}