Skip to content

Commit 9eef7ec

Browse files
authored
x.crypto.chacha20: mark State as public to make it reusable (#25449)
1 parent 8b820fc commit 9eef7ec

File tree

3 files changed

+74
-40
lines changed

3 files changed

+74
-40
lines changed

vlib/x/crypto/chacha20/chacha_test.v

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,39 @@ import rand
22
import encoding.hex
33
import x.crypto.chacha20
44

5+
// test for chacha20.State exposed api. The test material was taken from
6+
// Test Vector for the ChaCha20 Block Function ch 2.3.2. from RFC 8439 doc.
7+
// See https://datatracker.ietf.org/doc/html/rfc8439#section-2.3.2
8+
fn test_chacha20_state() ! {
9+
// ChaCha state with the key setup.
10+
s := chacha20.State([u32(0x61707865), 0x3320646e, 0x79622d32, 0x6b206574, 0x03020100, 0x07060504,
11+
0x0b0a0908, 0x0f0e0d0c, 0x13121110, 0x17161514, 0x1b1a1918, 0x1f1e1d1c, 0x00000001,
12+
0x09000000, 0x4a000000, 0x00000000]!)
13+
14+
// test for .clone
15+
mut ws := s.clone()
16+
for i := 0; i < 16; i++ {
17+
assert s[i] == ws[i]
18+
}
19+
// After running 20 rounds (10 column rounds interleaved with 10 "diagonal rounds"),
20+
// the ChaCha state looks like this:
21+
expected := chacha20.State([u32(0x837778ab), 0xe238d763, 0xa67ae21e, 0x5950bb2f, 0xc4f2d0c7,
22+
0xfc62bb2f, 0x8fa018fc, 0x3f5ec7b7, 0x335271c2, 0xf29489f3, 0xeabda8fc, 0x82e46ebd,
23+
0xd19c12b4, 0xb04e16de, 0x9e83d0cb, 0x4e3c50a2]!)
24+
25+
// test .qround call
26+
ws.qround(10)
27+
for i := 0; i < 16; i++ {
28+
assert ws[i] == expected[i]
29+
}
30+
31+
// test for .reset call
32+
ws.reset()
33+
for i := 0; i < 16; i++ {
34+
assert ws[i] == 0
35+
}
36+
}
37+
538
// test for extended chacha20 construct with 64-bit counter support
639
fn test_xchacha20_cipher_with_64_counter() ! {
740
key := rand.bytes(32)!

vlib/x/crypto/chacha20/stream.v

Lines changed: 40 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ fn (mut s Stream) keystream_full(mut dst []u8, src []u8) ! {
197197
fn (mut s Stream) keystream() ![]u8 {
198198
// initializes current state and working state
199199
mut awal := s.new_curr_state()
200-
mut ws := clone_state(awal)
200+
mut ws := awal.clone()
201201

202202
// precomputes cache counter-independent values
203203
if s.mode == .standard && !s.precomp {
@@ -222,27 +222,8 @@ fn (mut s Stream) keystream() ![]u8 {
222222
//
223223
// perform chacha20 quarter round n-times
224224
n := if s.mode == .standard { 9 } else { default_qround_nr }
225-
for i := 0; i < n; i++ {
226-
// Column-round
227-
// 0 | 1 | 2 | 3
228-
// 4 | 5 | 6 | 7
229-
// 8 | 9 | 10 | 11
230-
// 12 | 13 | 14 | 15
231-
qround_on_state(mut ws, 0, 4, 8, 12) // 0
232-
qround_on_state(mut ws, 1, 5, 9, 13) // 1
233-
qround_on_state(mut ws, 2, 6, 10, 14) // 2
234-
qround_on_state(mut ws, 3, 7, 11, 15) // 3
225+
ws.qround(n)
235226

236-
// Diagonal round.
237-
// 0 \ 1 \ 2 \ 3
238-
// 5 \ 6 \ 7 \ 4
239-
// 10 \ 11 \ 8 \ 9
240-
// 15 \ 12 \ 13 \ 14
241-
qround_on_state(mut ws, 0, 5, 10, 15)
242-
qround_on_state(mut ws, 1, 6, 11, 12)
243-
qround_on_state(mut ws, 2, 7, 8, 13)
244-
qround_on_state(mut ws, 3, 4, 9, 14)
245-
}
246227
// Adding the working state values with inital state values.
247228
// We dont performs xor-ing here, its done on xor_key_stream and or keystream_full.
248229
for i, _ in ws {
@@ -379,17 +360,53 @@ fn (b Stream) max_ctr() u64 {
379360
}
380361

381362
// State represents the running 64-bytes of chacha20 stream,
382-
type State = [16]u32
363+
pub type State = [16]u32
383364

365+
// clone returns a new copy of this state.
384366
@[direct_array_access; inline]
385-
fn clone_state(s State) State {
367+
pub fn (s State) clone() State {
386368
mut sc := State{}
387369
for i, v in s {
388370
sc[i] = v
389371
}
390372
return sc
391373
}
392374

375+
// reset resets internal values of this state.
376+
@[direct_array_access; inline]
377+
pub fn (mut s State) reset() {
378+
for i, _ in s {
379+
s[i] = u32(0)
380+
}
381+
}
382+
383+
// qround performs quarter round on the working state ws with round number specified in nr.
384+
// Its responsibility the user to provide the correct round number.
385+
@[direct_array_access]
386+
pub fn (mut ws State) qround(nr int) {
387+
for i := 0; i < nr; i++ {
388+
// Column-round
389+
// 0 | 1 | 2 | 3
390+
// 4 | 5 | 6 | 7
391+
// 8 | 9 | 10 | 11
392+
// 12 | 13 | 14 | 15
393+
qround_on_state(mut ws, 0, 4, 8, 12) // 0
394+
qround_on_state(mut ws, 1, 5, 9, 13) // 1
395+
qround_on_state(mut ws, 2, 6, 10, 14) // 2
396+
qround_on_state(mut ws, 3, 7, 11, 15) // 3
397+
398+
// Diagonal round.
399+
// 0 \ 1 \ 2 \ 3
400+
// 5 \ 6 \ 7 \ 4
401+
// 10 \ 11 \ 8 \ 9
402+
// 15 \ 12 \ 13 \ 14
403+
qround_on_state(mut ws, 0, 5, 10, 15)
404+
qround_on_state(mut ws, 1, 6, 11, 12)
405+
qround_on_state(mut ws, 2, 7, 8, 13)
406+
qround_on_state(mut ws, 3, 4, 9, 14)
407+
}
408+
}
409+
393410
// qround_on_state_with_quartet run qround_on_state by previously set up state values in offset
394411
// (a,b,c,d) with values from quartet (q0, q1, q2, q3)
395412
@[direct_array_access]

vlib/x/crypto/chacha20/xchacha.v

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -52,23 +52,7 @@ fn hchacha20(key []u8, nonce []u8) ![]u8 {
5252
x[15] = binary.little_endian_u32(nonce[12..16])
5353

5454
// After initialization, proceed through the ChaCha20 rounds as usual.
55-
for i := 0; i < 10; i++ {
56-
// Column round.
57-
qround_on_state(mut x, 0, 4, 8, 12) // 0
58-
qround_on_state(mut x, 1, 5, 9, 13) // 1
59-
qround_on_state(mut x, 2, 6, 10, 14) // 2
60-
qround_on_state(mut x, 3, 7, 11, 15) // 3
61-
62-
// Diagonal round.
63-
// 0 \ 1 \ 2 \ 3
64-
// 5 \ 6 \ 7 \ 4
65-
// 10 \ 11 \ 8 \ 9
66-
// 15 \ 12 \ 13 \ 14
67-
qround_on_state(mut x, 0, 5, 10, 15)
68-
qround_on_state(mut x, 1, 6, 11, 12)
69-
qround_on_state(mut x, 2, 7, 8, 13)
70-
qround_on_state(mut x, 3, 4, 9, 14)
71-
}
55+
x.qround(10)
7256

7357
// Once the 20 ChaCh20 rounds have been completed, the first 128 bits (16 bytes) and
7458
// last 128 bits (16 bytes) of the ChaCha state (both little-endian) are

0 commit comments

Comments
 (0)