Skip to content

Commit 7bc7672

Browse files
committed
ChaCha20-Poly1305 internals: Clarify memory safety of encrypt_within.
Eliminate the "less safe" variant of `encrypt_within`. Move the check for overlapping buffers into the inner safe wrapper around the assembly function call, so that it is clear what we're giving the assembly function. The extra checks are only done for 32-bit ARM and 32-bit x86, which are less of a performance priority now. And also the checks probably don't affect performance anyway.
1 parent 31a0313 commit 7bc7672

File tree

1 file changed

+19
-31
lines changed

1 file changed

+19
-31
lines changed

src/aead/chacha.rs

Lines changed: 19 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -45,15 +45,15 @@ impl Key {
4545
impl Key {
4646
#[inline]
4747
pub fn encrypt_in_place(&self, counter: Counter, in_out: &mut [u8]) {
48-
self.encrypt_less_safe(counter, in_out, 0..);
48+
self.encrypt_within(counter, in_out, 0..);
4949
}
5050

5151
#[inline]
5252
pub fn encrypt_iv_xor_in_place(&self, iv: Iv, in_out: &mut [u8; 32]) {
5353
// It is safe to use `into_counter_for_single_block_less_safe()`
5454
// because `in_out` is exactly one block long.
5555
debug_assert!(in_out.len() <= BLOCK_LEN);
56-
self.encrypt_less_safe(iv.into_counter_for_single_block_less_safe(), in_out, 0..);
56+
self.encrypt_in_place(iv.into_counter_for_single_block_less_safe(), in_out);
5757
}
5858

5959
#[inline]
@@ -62,32 +62,14 @@ impl Key {
6262
let iv = Iv::assume_unique_for_key(sample);
6363

6464
debug_assert!(out.len() <= BLOCK_LEN);
65-
self.encrypt_less_safe(iv.into_counter_for_single_block_less_safe(), &mut out, 0..);
65+
self.encrypt_in_place(iv.into_counter_for_single_block_less_safe(), &mut out);
6666

6767
out
6868
}
6969

7070
/// Analogous to `slice::copy_within()`.
71+
#[inline(always)]
7172
pub fn encrypt_within(&self, counter: Counter, in_out: &mut [u8], src: RangeFrom<usize>) {
72-
// XXX: The x86 and at least one branch of the ARM assembly language
73-
// code doesn't allow overlapping input and output unless they are
74-
// exactly overlapping. TODO: Figure out which branch of the ARM code
75-
// has this limitation and come up with a better solution.
76-
//
77-
// https://rt.openssl.org/Ticket/Display.html?id=4362
78-
if cfg!(any(target_arch = "arm", target_arch = "x86")) && src.start != 0 {
79-
let len = in_out.len() - src.start;
80-
in_out.copy_within(src, 0);
81-
self.encrypt_in_place(counter, &mut in_out[..len]);
82-
} else {
83-
self.encrypt_less_safe(counter, in_out, src);
84-
}
85-
}
86-
87-
/// This is "less safe" because it skips the important check that `encrypt_within` does.
88-
/// Only call this with `src` equal to `0..` or from `encrypt_within`.
89-
#[inline]
90-
fn encrypt_less_safe(&self, counter: Counter, in_out: &mut [u8], src: RangeFrom<usize>) {
9173
#[cfg(any(
9274
target_arch = "aarch64",
9375
target_arch = "arm",
@@ -103,6 +85,20 @@ impl Key {
10385
) {
10486
let in_out_len = in_out.len().checked_sub(src.start).unwrap();
10587

88+
// XXX: The x86 and at least one branch of the ARM assembly language
89+
// code doesn't allow overlapping input and output unless they are
90+
// exactly overlapping. TODO: Figure out which branch of the ARM code
91+
// has this limitation and come up with a better solution.
92+
//
93+
// https://rt.openssl.org/Ticket/Display.html?id=4362
94+
let (output, input) =
95+
if cfg!(any(target_arch = "aarch64", target_arch = "x86_64")) || src.start == 0 {
96+
(in_out.as_mut_ptr(), in_out[src].as_ptr())
97+
} else {
98+
in_out.copy_within(src, 0);
99+
(in_out.as_mut_ptr(), in_out.as_ptr())
100+
};
101+
106102
// There's no need to worry if `counter` is incremented because it is
107103
// owned here and we drop immediately after the call.
108104
prefixed_extern! {
@@ -114,15 +110,7 @@ impl Key {
114110
counter: &Counter,
115111
);
116112
}
117-
unsafe {
118-
ChaCha20_ctr32(
119-
in_out.as_mut_ptr(),
120-
in_out[src].as_ptr(),
121-
in_out_len,
122-
key.words_less_safe(),
123-
&counter,
124-
)
125-
}
113+
unsafe { ChaCha20_ctr32(output, input, in_out_len, key.words_less_safe(), &counter) }
126114
}
127115

128116
#[cfg(not(any(

0 commit comments

Comments
 (0)