Skip to content

Commit 972b633

Browse files
committed
chacha20: Change buffer_pos to a u16
For a 4-block buffer, we need to be able to represent the past-the-end buffer position of 256, which is too large for a `u8`.
1 parent 3dba685 commit 972b633

File tree

1 file changed

+19
-16
lines changed

1 file changed

+19
-16
lines changed

chacha20/src/chacha.rs

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ pub struct ChaCha<R: Rounds, MC: MaxCounter> {
7070
buffer: Buffer,
7171

7272
/// Position within buffer, or `None` if the buffer is not in use
73-
buffer_pos: u8,
73+
buffer_pos: u16,
7474

7575
/// Current counter value relative to the start of the keystream
7676
counter: u64,
@@ -121,23 +121,23 @@ impl<R: Rounds, MC: MaxCounter> StreamCipher for ChaCha<R, MC> {
121121
if data.len() < BUFFER_SIZE - pos {
122122
let n = pos + data.len();
123123
xor(data, &self.buffer[pos..n]);
124-
self.buffer_pos = n as u8;
124+
self.buffer_pos = n as u16;
125125
return Ok(());
126126
} else {
127127
let (l, r) = data.split_at_mut(BUFFER_SIZE - pos);
128128
data = r;
129129
if let Some(new_ctr) = counter.checked_add(COUNTER_INCR) {
130130
counter = new_ctr;
131131
} else if data.is_empty() {
132-
self.buffer_pos = BUFFER_SIZE as u8;
132+
self.buffer_pos = BUFFER_SIZE as u16;
133133
} else {
134134
return Err(LoopError);
135135
}
136136
xor(l, &self.buffer[pos..]);
137137
}
138138
}
139139

140-
if self.buffer_pos == BUFFER_SIZE as u8 {
140+
if self.buffer_pos == BUFFER_SIZE as u16 {
141141
if data.is_empty() {
142142
return Ok(());
143143
} else {
@@ -154,7 +154,7 @@ impl<R: Rounds, MC: MaxCounter> StreamCipher for ChaCha<R, MC> {
154154
}
155155

156156
let rem = chunks.into_remainder();
157-
self.buffer_pos = rem.len() as u8;
157+
self.buffer_pos = rem.len() as u16;
158158
self.counter = counter;
159159
if !rem.is_empty() {
160160
self.generate_block(counter);
@@ -168,24 +168,27 @@ impl<R: Rounds, MC: MaxCounter> StreamCipher for ChaCha<R, MC> {
168168
impl<R: Rounds, MC: MaxCounter> StreamCipherSeek for ChaCha<R, MC> {
169169
fn try_current_pos<T: SeekNum>(&self) -> Result<T, OverflowError> {
170170
// quick and dirty fix, until ctr-like parallel block processing will be added
171-
let (counter, pos) = if self.buffer_pos < BLOCK_SIZE as u8 {
172-
(self.counter, self.buffer_pos)
173-
} else {
174-
(
175-
self.counter.checked_add(1).ok_or(OverflowError)?,
176-
self.buffer_pos - BLOCK_SIZE as u8,
177-
)
171+
let (counter, pos) = {
172+
let mut counter = self.counter;
173+
let mut pos = self.buffer_pos;
174+
175+
while pos >= BLOCK_SIZE as u16 {
176+
counter = counter.checked_add(1).ok_or(OverflowError)?;
177+
pos -= BLOCK_SIZE as u16;
178+
}
179+
180+
(counter, pos)
178181
};
179-
T::from_block_byte(counter, pos, BLOCK_SIZE as u8)
182+
T::from_block_byte(counter, pos as u8, BLOCK_SIZE as u8)
180183
}
181184

182185
fn try_seek<T: SeekNum>(&mut self, pos: T) -> Result<(), LoopError> {
183-
let res: (u64, u8) = pos.to_block_byte(BUFFER_SIZE as u8)?;
186+
let res: (u64, u8) = pos.to_block_byte(BLOCK_SIZE as u8)?;
184187
let old_counter = self.counter;
185188
let old_buffer_pos = self.buffer_pos;
186189

187-
self.counter = res.0.checked_mul(COUNTER_INCR).ok_or(LoopError)?;
188-
self.buffer_pos = res.1;
190+
self.counter = res.0;
191+
self.buffer_pos = res.1 as u16;
189192

190193
if let Err(e) = self.check_data_len(&[0]) {
191194
self.counter = old_counter;

0 commit comments

Comments
 (0)