Skip to content

Commit

Permalink
impl zuc256 without mac generator which pass basic test (#3)
Browse files Browse the repository at this point in the history
  • Loading branch information
Xerxes-zhz authored Dec 10, 2024
1 parent c89d09d commit 21fcf84
Show file tree
Hide file tree
Showing 9 changed files with 565 additions and 366 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@
[License]: https://img.shields.io/crates/l/zuc.svg

Documentation: <https://docs.rs/zuc>

## References
- **ZUC 128**:[GB/T 33133.1-2016](https://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=8C41A3AEECCA52B5C0011C8010CF0715)
- **ZUC 256**:[ZUC256-version1.1](http://www.is.cas.cn/ztzl2016/zouchongzhi/201801/W020180416526664982687.pdf)
7 changes: 7 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,5 +11,12 @@
// ---
#![cfg_attr(docsrs, feature(doc_cfg))]

mod zuc;
pub use self::zuc::ZUC;
mod zuc128;
pub use self::zuc128::ZUC128;
mod zuc256;
pub use self::zuc256::{MacLength, ZUC256};

mod utils;
mod zuc_data;
35 changes: 35 additions & 0 deletions src/utils.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/// (a + b) mod (2^32)
#[inline(always)]
pub fn add(a: u32, b: u32) -> u32 {
a.wrapping_add(b)
}

/// rotate left
#[inline(always)]
fn rol(x: u32, n: u32) -> u32 {
x.rotate_left(n)
}

/// L1 linear transform
#[inline(always)]
pub fn l1(x: u32) -> u32 {
x ^ rol(x, 2) ^ rol(x, 10) ^ rol(x, 18) ^ rol(x, 24)
}

/// L2 linear transform
#[inline(always)]
pub fn l2(x: u32) -> u32 {
x ^ rol(x, 8) ^ rol(x, 14) ^ rol(x, 22) ^ rol(x, 30)
}
/// (a * b) mod (2^31 - 1)
#[inline(always)]
pub fn mul_m31(a: u32, b: u32) -> u32 {
((u64::from(a) * u64::from(b)) % ((1 << 31) - 1)) as u32
}

/// (a + b) mod (2^31 - 1)
#[inline(always)]
pub fn add_m31(a: u32, b: u32) -> u32 {
let c = add(a, b);
(c & 0x7FFF_FFFF) + (c >> 31)
}
123 changes: 123 additions & 0 deletions src/zuc.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
// src/zuc.rs
use super::utils::{add, add_m31, l1, l2, mul_m31};
use super::zuc_data::{S0, S1};
use std::mem;

/// S box transform
#[inline(always)]
fn sbox(x: u32) -> u32 {
let x = x.to_be_bytes();
let y = [
S0[x[0] as usize],
S1[x[1] as usize],
S0[x[2] as usize],
S1[x[3] as usize],
];
u32::from_be_bytes(y)
}
/// ZUC keystream generator
#[derive(Clone, Debug)]
pub struct ZUC {
/// LFSR registers (31-bit words x16)
pub(crate) s: [u32; 16],

/// R1 state unit (32 bits)
pub(crate) r1: u32,

/// R2 state unit (32 bits)
pub(crate) r2: u32,

/// X buffer
pub(crate) x: [u32; 4],
}

// 公共实现
impl ZUC {
/// Zero-initialized
#[allow(unsafe_code)]
pub fn zeroed() -> Self {
unsafe { mem::zeroed() }
}

/// Creates a ZUC128 keystream generator
pub fn init(&mut self, s: [u32; 16]) {
self.s = s;
for _ in 0..32 {
self.bit_reconstruction();
let w = self.f();
self.lfsr_with_initialization_mode(w >> 1);
}
self.generate();
}
/// `BitReconstruction` function
fn bit_reconstruction(&mut self) {
let Self { s, x, .. } = self;
x[0] = ((s[15] & 0x7FFF_8000) << 1) | (s[14] & 0xFFFF);
x[1] = ((s[11] & 0xFFFF) << 16) | (s[9] >> 15);
x[2] = ((s[7] & 0xFFFF) << 16) | (s[5] >> 15);
x[3] = ((s[2] & 0xFFFF) << 16) | (s[0] >> 15);
}

/// F non-linear function
fn f(&mut self) -> u32 {
let Self { x, r1, r2, .. } = self;

let w = add(x[0] ^ (*r1), *r2);
let w1 = add(*r1, x[1]);
let w2 = (*r2) ^ x[2];
*r1 = sbox(l1((w1 << 16) | (w2 >> 16)));
*r2 = sbox(l2((w2 << 16) | (w1 >> 16)));

w
}

/// `LFSRWithInitialisationMode` function
fn lfsr_with_initialization_mode(&mut self, u: u32) {
let Self { s, .. } = self;
let v = {
let v1 = mul_m31(1 << 15, s[15]);
let v2 = mul_m31(1 << 17, s[13]);
let v3 = mul_m31(1 << 21, s[10]);
let v4 = mul_m31(1 << 20, s[4]);
let v5 = mul_m31((1 << 8) + 1, s[0]);
add_m31(v1, add_m31(v2, add_m31(v3, add_m31(v4, v5))))
};
let mut s16 = add_m31(v, u);
if s16 == 0 {
s16 = (1 << 31) - 1;
}
for i in 0..15 {
s[i] = s[i + 1];
}
s[15] = s16;
}

/// `LFSRWithWorkMode` function
fn lfsr_with_work_mode(&mut self) {
let Self { s, .. } = self;
let v = {
let v1 = mul_m31(1 << 15, s[15]);
let v2 = mul_m31(1 << 17, s[13]);
let v3 = mul_m31(1 << 21, s[10]);
let v4 = mul_m31(1 << 20, s[4]);
let v5 = mul_m31((1 << 8) + 1, s[0]);
add_m31(v1, add_m31(v2, add_m31(v3, add_m31(v4, v5))))
};
let mut s16 = v;
if s16 == 0 {
s16 = (1 << 31) - 1;
}
for i in 0..15 {
s[i] = s[i + 1];
}
s[15] = s16;
}

/// Generates the next 32-bit word in ZUC128 keystream
pub fn generate(&mut self) -> u32 {
self.bit_reconstruction();
let z = self.f() ^ self.x[3];
self.lfsr_with_work_mode();
z
}
}
Loading

0 comments on commit 21fcf84

Please sign in to comment.