Skip to content

Commit 6321f4e

Browse files
committed
softaes is needed with the pure-rust implementation
1 parent 5c43091 commit 6321f4e

File tree

5 files changed

+226
-201
lines changed

5 files changed

+226
-201
lines changed

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ serde_json = "1.0"
2929

3030
[dependencies]
3131
aead = { optional = true, version = "0.6.0-rc.2", features = ["rand_core"] }
32+
softaes = { version = "0.1", optional = true }
3233

3334
[target."cfg(not(any(target_arch = \"wasm32\", target_arch = \"wasm64\")))".dev-dependencies.boring]
3435
version = "4.19.0"
@@ -39,7 +40,7 @@ harness = false
3940

4041
[features]
4142
default = ["std"]
42-
pure-rust = []
43+
pure-rust = ["softaes"]
4344
rustcrypto-traits-06 = ["aead"]
4445
std = []
4546

src/pure_rust/aegis128x2.rs

Lines changed: 61 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,27 @@ const D: usize = 2; // Degree of parallelism for AEGIS-128X2
1313
#[repr(transparent)]
1414
#[derive(Debug, Clone, Copy)]
1515
struct State {
16-
// We maintain D parallel AEGIS-128L states, each with 8 AES blocks
17-
blocks: [[AesBlock; 8]; D],
16+
// We maintain 8 AES blocks, each with D parallel states
17+
blocks: [[AesBlock; D]; 8],
1818
}
1919

2020
impl State {
2121
fn update(&mut self, d: [[AesBlock; 2]; D]) {
2222
// Update all D states in parallel
23+
let mut tmp = [AesBlock::from_bytes(&[0u8; 16]); D];
2324
for i in 0..D {
24-
let blocks = &mut self.blocks[i];
25-
let tmp = blocks[7];
26-
27-
blocks[7] = blocks[6].round(blocks[7]);
28-
blocks[6] = blocks[5].round(blocks[6]);
29-
blocks[5] = blocks[4].round(blocks[5]);
30-
blocks[4] = blocks[3].round(blocks[4]).xor(d[i][1]);
31-
blocks[3] = blocks[2].round(blocks[3]);
32-
blocks[2] = blocks[1].round(blocks[2]);
33-
blocks[1] = blocks[0].round(blocks[1]);
34-
blocks[0] = tmp.round(blocks[0]).xor(d[i][0]);
25+
tmp[i] = self.blocks[7][i];
26+
}
27+
28+
for i in 0..D {
29+
self.blocks[7][i] = self.blocks[6][i].round(self.blocks[7][i]);
30+
self.blocks[6][i] = self.blocks[5][i].round(self.blocks[6][i]);
31+
self.blocks[5][i] = self.blocks[4][i].round(self.blocks[5][i]);
32+
self.blocks[4][i] = self.blocks[3][i].round(self.blocks[4][i]).xor(d[i][1]);
33+
self.blocks[3][i] = self.blocks[2][i].round(self.blocks[3][i]);
34+
self.blocks[2][i] = self.blocks[1][i].round(self.blocks[2][i]);
35+
self.blocks[1][i] = self.blocks[0][i].round(self.blocks[1][i]);
36+
self.blocks[0][i] = tmp[i].round(self.blocks[0][i]).xor(d[i][0]);
3537
}
3638
}
3739

@@ -49,19 +51,17 @@ impl State {
4951
let nonce_block = AesBlock::from_bytes(nonce);
5052

5153
// Initialize D AEGIS-128L states
52-
let mut blocks = [[AesBlock::from_bytes(&[0u8; 16]); 8]; D];
54+
let mut blocks = [[AesBlock::from_bytes(&[0u8; 16]); D]; 8];
5355

5456
for i in 0..D {
55-
blocks[i] = [
56-
key_block.xor(nonce_block),
57-
c1,
58-
c0,
59-
c1,
60-
key_block.xor(nonce_block),
61-
key_block.xor(c0),
62-
key_block.xor(c1),
63-
key_block.xor(c0),
64-
];
57+
blocks[0][i] = key_block.xor(nonce_block);
58+
blocks[1][i] = c1;
59+
blocks[2][i] = c0;
60+
blocks[3][i] = c1;
61+
blocks[4][i] = key_block.xor(nonce_block);
62+
blocks[5][i] = key_block.xor(c0);
63+
blocks[6][i] = key_block.xor(c1);
64+
blocks[7][i] = key_block.xor(c0);
6565
}
6666

6767
let mut state = State { blocks };
@@ -79,8 +79,8 @@ impl State {
7979
for _ in 0..10 {
8080
// Add context to states
8181
for i in 0..D {
82-
state.blocks[i][3] = state.blocks[i][3].xor(ctx[i]);
83-
state.blocks[i][7] = state.blocks[i][7].xor(ctx[i]);
82+
state.blocks[3][i] = state.blocks[3][i].xor(ctx[i]);
83+
state.blocks[7][i] = state.blocks[7][i].xor(ctx[i]);
8484
}
8585

8686
// Update with nonce and key for each state
@@ -110,9 +110,12 @@ impl State {
110110

111111
fn enc(&mut self, dst: &mut [u8; 32 * D], src: &[u8; 32 * D]) {
112112
for i in 0..D {
113-
let blocks = &self.blocks[i];
114-
let z0 = blocks[6].xor(blocks[1]).xor(blocks[2].and(blocks[3]));
115-
let z1 = blocks[2].xor(blocks[5]).xor(blocks[6].and(blocks[7]));
113+
let z0 = self.blocks[6][i]
114+
.xor(self.blocks[1][i])
115+
.xor(self.blocks[2][i].and(self.blocks[3][i]));
116+
let z1 = self.blocks[2][i]
117+
.xor(self.blocks[5][i])
118+
.xor(self.blocks[6][i].and(self.blocks[7][i]));
116119

117120
// Read from correct positions: M0 split, then M1 split
118121
let msg0 = AesBlock::from_bytes(&src[i * 16..i * 16 + 16]); // M0 split
@@ -133,9 +136,12 @@ impl State {
133136
let mut msg = [[AesBlock::from_bytes(&[0u8; 16]); 2]; D];
134137

135138
for i in 0..D {
136-
let blocks = &self.blocks[i];
137-
let z0 = blocks[6].xor(blocks[1]).xor(blocks[2].and(blocks[3]));
138-
let z1 = blocks[2].xor(blocks[5]).xor(blocks[6].and(blocks[7]));
139+
let z0 = self.blocks[6][i]
140+
.xor(self.blocks[1][i])
141+
.xor(self.blocks[2][i].and(self.blocks[3][i]));
142+
let z1 = self.blocks[2][i]
143+
.xor(self.blocks[5][i])
144+
.xor(self.blocks[6][i].and(self.blocks[7][i]));
139145

140146
// Read from correct positions: M0 split, then M1 split
141147
msg[i][0] = AesBlock::from_bytes(&src[i * 16..i * 16 + 16]).xor(z0); // M0 split
@@ -158,9 +164,12 @@ impl State {
158164
let mut z1_bytes = [0u8; 32]; // 128 * D bits = 32 bytes for D=2
159165

160166
for i in 0..D {
161-
let blocks = &self.blocks[i];
162-
let z0_i = blocks[6].xor(blocks[1]).xor(blocks[2].and(blocks[3]));
163-
let z1_i = blocks[2].xor(blocks[5]).xor(blocks[6].and(blocks[7]));
167+
let z0_i = self.blocks[6][i]
168+
.xor(self.blocks[1][i])
169+
.xor(self.blocks[2][i].and(self.blocks[3][i]));
170+
let z1_i = self.blocks[2][i]
171+
.xor(self.blocks[5][i])
172+
.xor(self.blocks[6][i].and(self.blocks[7][i]));
164173

165174
z0_bytes[i * 16..i * 16 + 16].copy_from_slice(&z0_i.to_bytes());
166175
z1_bytes[i * 16..i * 16 + 16].copy_from_slice(&z1_i.to_bytes());
@@ -218,8 +227,8 @@ impl State {
218227
// Construct t vector: for i in 0..D: t = t || (V[2,i] ^ u)
219228
let mut t_data = [[AesBlock::from_bytes(&[0u8; 16]); 2]; D];
220229
for i in 0..D {
221-
t_data[i][0] = self.blocks[i][2].xor(u); // V[2,i] ^ u
222-
t_data[i][1] = self.blocks[i][2].xor(u); // V[2,i] ^ u for both M0 and M1
230+
t_data[i][0] = self.blocks[2][i].xor(u); // V[2,i] ^ u
231+
t_data[i][1] = self.blocks[2][i].xor(u); // V[2,i] ^ u for both M0 and M1
223232
}
224233

225234
// Repeat(7, Update(t, t)) - Update all D states simultaneously
@@ -233,13 +242,13 @@ impl State {
233242

234243
for i in 0..D {
235244
// ti = V[0,i] ^ V[1,i] ^ V[2,i] ^ V[3,i] ^ V[4,i] ^ V[5,i] ^ V[6,i]
236-
let ti = self.blocks[i][0]
237-
.xor(self.blocks[i][1])
238-
.xor(self.blocks[i][2])
239-
.xor(self.blocks[i][3])
240-
.xor(self.blocks[i][4])
241-
.xor(self.blocks[i][5])
242-
.xor(self.blocks[i][6]);
245+
let ti = self.blocks[0][i]
246+
.xor(self.blocks[1][i])
247+
.xor(self.blocks[2][i])
248+
.xor(self.blocks[3][i])
249+
.xor(self.blocks[4][i])
250+
.xor(self.blocks[5][i])
251+
.xor(self.blocks[6][i]);
243252
tag_block = tag_block.xor(ti);
244253
}
245254

@@ -254,17 +263,17 @@ impl State {
254263
for i in 0..D {
255264
// ti0 = ti0 ^ V[0,i] ^ V[1,i] ^ V[2,i] ^ V[3,i]
256265
ti0 = ti0
257-
.xor(self.blocks[i][0])
258-
.xor(self.blocks[i][1])
259-
.xor(self.blocks[i][2])
260-
.xor(self.blocks[i][3]);
266+
.xor(self.blocks[0][i])
267+
.xor(self.blocks[1][i])
268+
.xor(self.blocks[2][i])
269+
.xor(self.blocks[3][i]);
261270

262271
// ti1 = ti1 ^ V[4,i] ^ V[5,i] ^ V[6,i] ^ V[7,i]
263272
ti1 = ti1
264-
.xor(self.blocks[i][4])
265-
.xor(self.blocks[i][5])
266-
.xor(self.blocks[i][6])
267-
.xor(self.blocks[i][7]);
273+
.xor(self.blocks[4][i])
274+
.xor(self.blocks[5][i])
275+
.xor(self.blocks[6][i])
276+
.xor(self.blocks[7][i]);
268277
}
269278

270279
let mut tag = [0u8; TAG_BYTES];

src/pure_rust/aegis128x4.rs

Lines changed: 61 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -13,25 +13,27 @@ const D: usize = 4; // Degree of parallelism for AEGIS-128X4
1313
#[repr(transparent)]
1414
#[derive(Debug, Clone, Copy)]
1515
struct State {
16-
// We maintain D parallel AEGIS-128L states, each with 8 AES blocks
17-
blocks: [[AesBlock; 8]; D],
16+
// We maintain 8 AES blocks, each with D parallel states
17+
blocks: [[AesBlock; D]; 8],
1818
}
1919

2020
impl State {
2121
fn update(&mut self, d: [[AesBlock; 2]; D]) {
2222
// Update all D states in parallel
23+
let mut tmp = [AesBlock::from_bytes(&[0u8; 16]); D];
2324
for i in 0..D {
24-
let blocks = &mut self.blocks[i];
25-
let tmp = blocks[7];
26-
27-
blocks[7] = blocks[6].round(blocks[7]);
28-
blocks[6] = blocks[5].round(blocks[6]);
29-
blocks[5] = blocks[4].round(blocks[5]);
30-
blocks[4] = blocks[3].round(blocks[4]).xor(d[i][1]);
31-
blocks[3] = blocks[2].round(blocks[3]);
32-
blocks[2] = blocks[1].round(blocks[2]);
33-
blocks[1] = blocks[0].round(blocks[1]);
34-
blocks[0] = tmp.round(blocks[0]).xor(d[i][0]);
25+
tmp[i] = self.blocks[7][i];
26+
}
27+
28+
for i in 0..D {
29+
self.blocks[7][i] = self.blocks[6][i].round(self.blocks[7][i]);
30+
self.blocks[6][i] = self.blocks[5][i].round(self.blocks[6][i]);
31+
self.blocks[5][i] = self.blocks[4][i].round(self.blocks[5][i]);
32+
self.blocks[4][i] = self.blocks[3][i].round(self.blocks[4][i]).xor(d[i][1]);
33+
self.blocks[3][i] = self.blocks[2][i].round(self.blocks[3][i]);
34+
self.blocks[2][i] = self.blocks[1][i].round(self.blocks[2][i]);
35+
self.blocks[1][i] = self.blocks[0][i].round(self.blocks[1][i]);
36+
self.blocks[0][i] = tmp[i].round(self.blocks[0][i]).xor(d[i][0]);
3537
}
3638
}
3739

@@ -49,19 +51,17 @@ impl State {
4951
let nonce_block = AesBlock::from_bytes(nonce);
5052

5153
// Initialize D AEGIS-128L states
52-
let mut blocks = [[AesBlock::from_bytes(&[0u8; 16]); 8]; D];
54+
let mut blocks = [[AesBlock::from_bytes(&[0u8; 16]); D]; 8];
5355

5456
for i in 0..D {
55-
blocks[i] = [
56-
key_block.xor(nonce_block),
57-
c1,
58-
c0,
59-
c1,
60-
key_block.xor(nonce_block),
61-
key_block.xor(c0),
62-
key_block.xor(c1),
63-
key_block.xor(c0),
64-
];
57+
blocks[0][i] = key_block.xor(nonce_block);
58+
blocks[1][i] = c1;
59+
blocks[2][i] = c0;
60+
blocks[3][i] = c1;
61+
blocks[4][i] = key_block.xor(nonce_block);
62+
blocks[5][i] = key_block.xor(c0);
63+
blocks[6][i] = key_block.xor(c1);
64+
blocks[7][i] = key_block.xor(c0);
6565
}
6666

6767
let mut state = State { blocks };
@@ -79,8 +79,8 @@ impl State {
7979
for _ in 0..10 {
8080
// Add context to states
8181
for i in 0..D {
82-
state.blocks[i][3] = state.blocks[i][3].xor(ctx[i]);
83-
state.blocks[i][7] = state.blocks[i][7].xor(ctx[i]);
82+
state.blocks[3][i] = state.blocks[3][i].xor(ctx[i]);
83+
state.blocks[7][i] = state.blocks[7][i].xor(ctx[i]);
8484
}
8585

8686
// Update with nonce and key for each state
@@ -110,9 +110,12 @@ impl State {
110110

111111
fn enc(&mut self, dst: &mut [u8; 32 * D], src: &[u8; 32 * D]) {
112112
for i in 0..D {
113-
let blocks = &self.blocks[i];
114-
let z0 = blocks[6].xor(blocks[1]).xor(blocks[2].and(blocks[3]));
115-
let z1 = blocks[2].xor(blocks[5]).xor(blocks[6].and(blocks[7]));
113+
let z0 = self.blocks[6][i]
114+
.xor(self.blocks[1][i])
115+
.xor(self.blocks[2][i].and(self.blocks[3][i]));
116+
let z1 = self.blocks[2][i]
117+
.xor(self.blocks[5][i])
118+
.xor(self.blocks[6][i].and(self.blocks[7][i]));
116119

117120
// Read from correct positions: M0 split, then M1 split
118121
let msg0 = AesBlock::from_bytes(&src[i * 16..i * 16 + 16]); // M0 split
@@ -133,9 +136,12 @@ impl State {
133136
let mut msg = [[AesBlock::from_bytes(&[0u8; 16]); 2]; D];
134137

135138
for i in 0..D {
136-
let blocks = &self.blocks[i];
137-
let z0 = blocks[6].xor(blocks[1]).xor(blocks[2].and(blocks[3]));
138-
let z1 = blocks[2].xor(blocks[5]).xor(blocks[6].and(blocks[7]));
139+
let z0 = self.blocks[6][i]
140+
.xor(self.blocks[1][i])
141+
.xor(self.blocks[2][i].and(self.blocks[3][i]));
142+
let z1 = self.blocks[2][i]
143+
.xor(self.blocks[5][i])
144+
.xor(self.blocks[6][i].and(self.blocks[7][i]));
139145

140146
// Read from correct positions: M0 split, then M1 split
141147
msg[i][0] = AesBlock::from_bytes(&src[i * 16..i * 16 + 16]).xor(z0); // M0 split
@@ -158,9 +164,12 @@ impl State {
158164
let mut z1_bytes = [0u8; 64]; // 128 * D bits = 64 bytes for D=4
159165

160166
for i in 0..D {
161-
let blocks = &self.blocks[i];
162-
let z0_i = blocks[6].xor(blocks[1]).xor(blocks[2].and(blocks[3]));
163-
let z1_i = blocks[2].xor(blocks[5]).xor(blocks[6].and(blocks[7]));
167+
let z0_i = self.blocks[6][i]
168+
.xor(self.blocks[1][i])
169+
.xor(self.blocks[2][i].and(self.blocks[3][i]));
170+
let z1_i = self.blocks[2][i]
171+
.xor(self.blocks[5][i])
172+
.xor(self.blocks[6][i].and(self.blocks[7][i]));
164173

165174
z0_bytes[i * 16..i * 16 + 16].copy_from_slice(&z0_i.to_bytes());
166175
z1_bytes[i * 16..i * 16 + 16].copy_from_slice(&z1_i.to_bytes());
@@ -218,8 +227,8 @@ impl State {
218227
// Construct t vector: for i in 0..D: t = t || (V[2,i] ^ u)
219228
let mut t_data = [[AesBlock::from_bytes(&[0u8; 16]); 2]; D];
220229
for i in 0..D {
221-
t_data[i][0] = self.blocks[i][2].xor(u); // V[2,i] ^ u
222-
t_data[i][1] = self.blocks[i][2].xor(u); // V[2,i] ^ u for both M0 and M1
230+
t_data[i][0] = self.blocks[2][i].xor(u); // V[2,i] ^ u
231+
t_data[i][1] = self.blocks[2][i].xor(u); // V[2,i] ^ u for both M0 and M1
223232
}
224233

225234
// Repeat(7, Update(t, t)) - Update all D states simultaneously
@@ -233,13 +242,13 @@ impl State {
233242

234243
for i in 0..D {
235244
// ti = V[0,i] ^ V[1,i] ^ V[2,i] ^ V[3,i] ^ V[4,i] ^ V[5,i] ^ V[6,i]
236-
let ti = self.blocks[i][0]
237-
.xor(self.blocks[i][1])
238-
.xor(self.blocks[i][2])
239-
.xor(self.blocks[i][3])
240-
.xor(self.blocks[i][4])
241-
.xor(self.blocks[i][5])
242-
.xor(self.blocks[i][6]);
245+
let ti = self.blocks[0][i]
246+
.xor(self.blocks[1][i])
247+
.xor(self.blocks[2][i])
248+
.xor(self.blocks[3][i])
249+
.xor(self.blocks[4][i])
250+
.xor(self.blocks[5][i])
251+
.xor(self.blocks[6][i]);
243252
tag_block = tag_block.xor(ti);
244253
}
245254

@@ -254,17 +263,17 @@ impl State {
254263
for i in 0..D {
255264
// ti0 = ti0 ^ V[0,i] ^ V[1,i] ^ V[2,i] ^ V[3,i]
256265
ti0 = ti0
257-
.xor(self.blocks[i][0])
258-
.xor(self.blocks[i][1])
259-
.xor(self.blocks[i][2])
260-
.xor(self.blocks[i][3]);
266+
.xor(self.blocks[0][i])
267+
.xor(self.blocks[1][i])
268+
.xor(self.blocks[2][i])
269+
.xor(self.blocks[3][i]);
261270

262271
// ti1 = ti1 ^ V[4,i] ^ V[5,i] ^ V[6,i] ^ V[7,i]
263272
ti1 = ti1
264-
.xor(self.blocks[i][4])
265-
.xor(self.blocks[i][5])
266-
.xor(self.blocks[i][6])
267-
.xor(self.blocks[i][7]);
273+
.xor(self.blocks[4][i])
274+
.xor(self.blocks[5][i])
275+
.xor(self.blocks[6][i])
276+
.xor(self.blocks[7][i]);
268277
}
269278

270279
let mut tag = [0u8; TAG_BYTES];

0 commit comments

Comments
 (0)