Skip to content

Commit 524278e

Browse files
test(kyberlib): ✅ tests covering the main functions in the symmetric.rs
1 parent 5d3317b commit 524278e

File tree

4 files changed

+166
-23
lines changed

4 files changed

+166
-23
lines changed

src/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ mod avx2;
144144
use avx2::*;
145145

146146
#[cfg(any(not(target_arch = "x86_64"), not(feature = "avx2")))]
147-
mod reference;
147+
pub mod reference;
148148
#[cfg(any(not(target_arch = "x86_64"), not(feature = "avx2")))]
149149
use reference::*;
150150

@@ -169,6 +169,7 @@ pub mod kex;
169169
pub mod macros;
170170
/// Parameters for the KyberLib library.
171171
pub mod params;
172+
172173
/// Random number generators for the KyberLib library.
173174
pub mod rng;
174175
/// Symmetric key encapsulation module for the KyberLib library.

src/reference/fips202.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@
33
use crate::symmetric::KeccakState;
44

55
pub(crate) const SHAKE128_RATE: usize = 168;
6-
const SHAKE256_RATE: usize = 136;
7-
const SHA3_256_RATE: usize = 136;
8-
const SHA3_512_RATE: usize = 72;
9-
const NROUNDS: usize = 24;
6+
pub(crate) const SHAKE256_RATE: usize = 136;
7+
pub(crate) const SHA3_256_RATE: usize = 136;
8+
pub(crate) const SHA3_512_RATE: usize = 72;
9+
pub(crate) const NROUNDS: usize = 24;
1010

1111
fn rol(a: u64, offset: u64) -> u64 {
1212
(a << offset) ^ (a >> (64 - offset))

src/symmetric.rs

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,50 +21,50 @@ pub const AES256CTR_BLOCKBYTES: usize = 64;
2121

2222
/// Block size for AES256CTR in bytes.
2323
#[cfg(not(feature = "90s"))]
24-
pub(crate) const AES256CTR_BLOCKBYTES: usize = 64;
24+
pub const AES256CTR_BLOCKBYTES: usize = 64;
2525

2626
/// Block size for XOF (Extendable Output Function) in bytes.
2727
#[cfg(feature = "90s")]
2828
pub const XOF_BLOCKBYTES: usize = AES256CTR_BLOCKBYTES;
2929

3030
/// Block size for XOF (Extendable Output Function) in bytes.
3131
#[cfg(not(feature = "90s"))]
32-
pub(crate) const XOF_BLOCKBYTES: usize = SHAKE128_RATE;
32+
pub const XOF_BLOCKBYTES: usize = SHAKE128_RATE;
3333

3434
/// Type alias for the XOF (Extendable Output Function) state.
3535
#[cfg(not(feature = "90s"))]
36-
pub(crate) type XofState = KeccakState;
36+
pub type XofState = KeccakState;
3737

3838
/// Type alias for the XOF (Extendable Output Function) state in 90s mode.
3939
#[cfg(feature = "90s")]
4040
pub type XofState = Aes256CtrCtx;
4141

4242
/// Keccak state for absorbing data
43-
#[derive(Copy, Clone)]
44-
pub(crate) struct KeccakState {
45-
pub(crate) s: [u64; 25],
46-
pub(crate) pos: usize,
43+
#[derive(Copy, Clone, Debug, Default)]
44+
pub struct KeccakState {
45+
pub s: [u64; 25],
46+
pub pos: usize,
4747
}
4848

4949
impl KeccakState {
5050
/// Creates a new KeccakState
51-
pub(crate) fn new() -> Self {
51+
pub fn new() -> Self {
5252
KeccakState {
5353
s: [0u64; 25],
5454
pos: 0usize,
5555
}
5656
}
5757

5858
/// Resets the KeccakState
59-
pub(crate) fn reset(&mut self) {
59+
pub fn reset(&mut self) {
6060
self.s = [0u64; 25];
6161
self.pos = 0;
6262
}
6363
}
6464

6565
/// Computes SHA3-256 hash
6666
#[cfg(not(feature = "90s"))]
67-
pub(crate) fn hash_h(out: &mut [u8], input: &[u8], inlen: usize) {
67+
pub fn hash_h(out: &mut [u8], input: &[u8], inlen: usize) {
6868
sha3_256(out, input, inlen);
6969
}
7070

@@ -79,7 +79,7 @@ pub fn hash_h(out: &mut [u8], input: &[u8], inlen: usize) {
7979

8080
/// Computes SHA3-512 hash
8181
#[cfg(not(feature = "90s"))]
82-
pub(crate) fn hash_g(out: &mut [u8], input: &[u8], inlen: usize) {
82+
pub fn hash_g(out: &mut [u8], input: &[u8], inlen: usize) {
8383
sha3_512(out, input, inlen);
8484
}
8585

@@ -94,7 +94,7 @@ pub fn hash_g(out: &mut [u8], input: &[u8], inlen: usize) {
9494

9595
/// Absorbs input data into the XOF state in non-90s mode
9696
#[cfg(not(feature = "90s"))]
97-
pub(crate) fn xof_absorb(state: &mut XofState, input: &[u8], x: u8, y: u8) {
97+
pub fn xof_absorb(state: &mut XofState, input: &[u8], x: u8, y: u8) {
9898
kyber_shake128_absorb(state, input, x, y);
9999
}
100100

@@ -109,7 +109,7 @@ pub fn xof_absorb(state: &mut XofState, input: &[u8], x: u8, y: u8) {
109109

110110
/// Squeezes XOF data into output in non-90s mode
111111
#[cfg(not(feature = "90s"))]
112-
pub(crate) fn xof_squeezeblocks(out: &mut [u8], outblocks: usize, state: &mut XofState) {
112+
pub fn xof_squeezeblocks(out: &mut [u8], outblocks: usize, state: &mut XofState) {
113113
kyber_shake128_squeezeblocks(out, outblocks, state);
114114
}
115115

@@ -121,7 +121,7 @@ pub fn xof_squeezeblocks(out: &mut [u8], outblocks: usize, state: &mut XofState)
121121

122122
/// Pseudo-random function (PRF) in non-90s mode
123123
#[cfg(not(feature = "90s"))]
124-
pub(crate) fn prf(out: &mut [u8], outbytes: usize, key: &[u8], nonce: u8) {
124+
pub fn prf(out: &mut [u8], outbytes: usize, key: &[u8], nonce: u8) {
125125
shake256_prf(out, outbytes, key, nonce);
126126
}
127127

@@ -145,7 +145,7 @@ pub fn prf(out: &mut [u8], _outbytes: usize, key: &[u8], nonce: u8) {
145145

146146
/// Key derivation function (KDF) in non-90s mode
147147
#[cfg(not(feature = "90s"))]
148-
pub(crate) fn kdf(out: &mut [u8], input: &[u8], inlen: usize) {
148+
pub fn kdf(out: &mut [u8], input: &[u8], inlen: usize) {
149149
shake256(out, KYBER_SHARED_SECRET_BYTES, input, inlen);
150150
}
151151

@@ -160,7 +160,7 @@ pub fn kdf(out: &mut [u8], input: &[u8], inlen: usize) {
160160

161161
/// Absorb step of the SHAKE128 specialized for the Kyber context
162162
#[cfg(not(feature = "90s"))]
163-
fn kyber_shake128_absorb(s: &mut KeccakState, input: &[u8], x: u8, y: u8) {
163+
pub fn kyber_shake128_absorb(s: &mut KeccakState, input: &[u8], x: u8, y: u8) {
164164
let mut extseed = [0u8; KYBER_SYM_BYTES + 2];
165165
extseed[..KYBER_SYM_BYTES].copy_from_slice(input);
166166
extseed[KYBER_SYM_BYTES] = x;
@@ -170,13 +170,13 @@ fn kyber_shake128_absorb(s: &mut KeccakState, input: &[u8], x: u8, y: u8) {
170170

171171
/// Squeeze step of SHAKE128 XOF in non-90s mode
172172
#[cfg(not(feature = "90s"))]
173-
fn kyber_shake128_squeezeblocks(output: &mut [u8], nblocks: usize, s: &mut KeccakState) {
173+
pub fn kyber_shake128_squeezeblocks(output: &mut [u8], nblocks: usize, s: &mut KeccakState) {
174174
shake128_squeezeblocks(output, nblocks, s);
175175
}
176176

177177
/// Usage of SHAKE256 as a PRF in non-90s mode
178178
#[cfg(not(feature = "90s"))]
179-
fn shake256_prf(output: &mut [u8], outlen: usize, key: &[u8], nonce: u8) {
179+
pub fn shake256_prf(output: &mut [u8], outlen: usize, key: &[u8], nonce: u8) {
180180
let mut extkey = [0u8; KYBER_SYM_BYTES + 1];
181181
extkey[..KYBER_SYM_BYTES].copy_from_slice(key);
182182
extkey[KYBER_SYM_BYTES] = nonce;

tests/test_symmetric.rs

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
// Copyright © 2023 kyberlib. All rights reserved.
2+
// SPDX-License-Identifier: Apache-2.0 OR MIT
3+
4+
#[cfg(test)]
5+
mod tests {
6+
// Import necessary items
7+
use kyberlib::{
8+
symmetric::{hash_g, hash_h, kdf, prf},
9+
KYBER_SHARED_SECRET_BYTES,
10+
};
11+
12+
// Test the hash_h function
13+
#[test]
14+
fn test_hash_h() {
15+
let input = b"test input";
16+
let inlen = input.len();
17+
let mut out = [0u8; 32];
18+
19+
// Call the hash_h function
20+
hash_h(&mut out, input, inlen);
21+
22+
// Assert that the output is not all zeros
23+
assert_ne!(out, [0u8; 32]);
24+
}
25+
26+
// Test the hash_g function
27+
#[test]
28+
fn test_hash_g() {
29+
let input = b"test input";
30+
let inlen = input.len();
31+
let mut out = [0u8; 64];
32+
33+
// Call the hash_g function
34+
hash_g(&mut out, input, inlen);
35+
36+
// Assert that the output is not all zeros
37+
assert_ne!(out, [0u8; 64]);
38+
}
39+
40+
// Test the xof_absorb and xof_squeezeblocks functions
41+
#[test]
42+
fn test_xof_absorb_squeeze() {
43+
use kyberlib::params::KYBER_SYM_BYTES;
44+
use kyberlib::symmetric::KeccakState;
45+
use kyberlib::symmetric::{kyber_shake128_absorb, kyber_shake128_squeezeblocks};
46+
47+
const SHAKE128_RATE: usize = 168;
48+
49+
let mut state = KeccakState::new();
50+
let input = [1u8; KYBER_SYM_BYTES];
51+
let x = 1;
52+
let y = 2;
53+
let mut out = [0u8; SHAKE128_RATE];
54+
55+
// Absorb input data into the Kyber-specific SHAKE128 state
56+
kyber_shake128_absorb(&mut state, &input, x, y);
57+
let nblocks = out.len() / SHAKE128_RATE;
58+
kyber_shake128_squeezeblocks(&mut out, nblocks, &mut state);
59+
let outlen = out.len();
60+
let mut idx = 0;
61+
for i in 0..outlen {
62+
assert_ne!(out[i], 0);
63+
idx += 1;
64+
}
65+
assert_eq!(idx, outlen);
66+
}
67+
68+
// Test the prf function
69+
#[test]
70+
fn test_prf() {
71+
use kyberlib::params::KYBER_SYM_BYTES;
72+
let mut key = [0u8; KYBER_SYM_BYTES];
73+
key[..8].copy_from_slice(b"test key");
74+
let nonce = 42;
75+
let mut out = [0u8; 64];
76+
let outbytes = out.len();
77+
78+
// Call the prf function
79+
prf(&mut out, outbytes, &key, nonce);
80+
81+
// Assert that the output is not all zeros
82+
assert_ne!(out, [0u8; 64]);
83+
}
84+
85+
// Test the kdf function
86+
#[test]
87+
fn test_kdf() {
88+
let input = b"test input";
89+
let inlen = input.len();
90+
let mut out = [0u8; KYBER_SHARED_SECRET_BYTES];
91+
92+
// Call the kdf function
93+
kdf(&mut out, input, inlen);
94+
95+
// Assert that the output is not all zeros
96+
assert_ne!(out, [0u8; KYBER_SHARED_SECRET_BYTES]);
97+
}
98+
99+
#[cfg(not(feature = "90s"))]
100+
#[test]
101+
fn test_kyber_shake128_absorb_squeeze() {
102+
use kyberlib::params::KYBER_SYM_BYTES;
103+
use kyberlib::symmetric::KeccakState;
104+
use kyberlib::symmetric::{kyber_shake128_absorb, kyber_shake128_squeezeblocks};
105+
106+
const SHAKE128_RATE: usize = 168;
107+
108+
let mut state = KeccakState::new();
109+
let input = [1u8; KYBER_SYM_BYTES];
110+
let x = 1;
111+
let y = 2;
112+
let mut out = [0u8; SHAKE128_RATE];
113+
114+
// Absorb input data into the Kyber-specific SHAKE128 state
115+
kyber_shake128_absorb(&mut state, &input, x, y);
116+
117+
// Squeeze Kyber-specific SHAKE128 data into output
118+
kyber_shake128_squeezeblocks(&mut out, 1, &mut state);
119+
120+
// Assert that the output is not all zeros
121+
assert_ne!(out, [0u8; SHAKE128_RATE]);
122+
}
123+
124+
#[cfg(not(feature = "90s"))]
125+
#[test]
126+
fn test_shake256_prf() {
127+
use kyberlib::params::KYBER_SYM_BYTES;
128+
use kyberlib::symmetric::shake256_prf;
129+
130+
let mut key = [0u8; KYBER_SYM_BYTES];
131+
key.copy_from_slice(&[0u8; KYBER_SYM_BYTES]);
132+
let nonce = 42;
133+
let mut out = [0u8; 32]; // Output length of SHAKE256 is 32 bytes
134+
let outlen = out.len();
135+
136+
// Call the SHAKE256 PRF function
137+
shake256_prf(&mut out, outlen, &key, nonce);
138+
139+
// Assert that the output is not all zeros
140+
assert_ne!(out, [0u8; 32]);
141+
}
142+
}

0 commit comments

Comments
 (0)