Skip to main content

cryptography/ciphers/
camellia.rs

1//! Camellia block cipher — CRYPTREC / ISO/IEC 18033-3 / RFC 3713.
2//!
3//! 128-bit block cipher with three standard key sizes:
4//!
5//! - `Camellia128` / `Camellia128Ct`
6//! - `Camellia192` / `Camellia192Ct`
7//! - `Camellia256` / `Camellia256Ct`
8//!
9//! Camellia is a Feistel network with 18 rounds for 128-bit keys and 24 rounds
10//! for 192/256-bit keys. The fast path keeps the direct 8-bit S-box table. The
11//! `Ct` path evaluates the same S-box in packed ANF form so the round function
12//! and key schedule avoid secret-indexed table reads.
13
14#[rustfmt::skip]
15const SBOX1: [u8; 256] = [
16    112, 130,  44, 236, 179,  39, 192, 229, 228, 133,  87,  53, 234,  12, 174,  65,
17     35, 239, 107, 147,  69,  25, 165,  33, 237,  14,  79,  78,  29, 101, 146, 189,
18    134, 184, 175, 143, 124, 235,  31, 206,  62,  48, 220,  95,  94, 197,  11,  26,
19    166, 225,  57, 202, 213,  71,  93,  61, 217,   1,  90, 214,  81,  86, 108,  77,
20    139,  13, 154, 102, 251, 204, 176,  45, 116,  18,  43,  32, 240, 177, 132, 153,
21    223,  76, 203, 194,  52, 126, 118,   5, 109, 183, 169,  49, 209,  23,   4, 215,
22     20,  88,  58,  97, 222,  27,  17,  28,  50,  15, 156,  22,  83,  24, 242,  34,
23    254,  68, 207, 178, 195, 181, 122, 145,  36,   8, 232, 168,  96, 252, 105,  80,
24    170, 208, 160, 125, 161, 137,  98, 151,  84,  91,  30, 149, 224, 255, 100, 210,
25     16, 196,   0,  72, 163, 247, 117, 219, 138,   3, 230, 218,   9,  63, 221, 148,
26    135,  92, 131,   2, 205,  74, 144,  51, 115, 103, 246, 243, 157, 127, 191, 226,
27     82, 155, 216,  38, 200,  55, 198,  59, 129, 150, 111,  75,  19, 190,  99,  46,
28    233, 121, 167, 140, 159, 110, 188, 142,  41, 245, 249, 182,  47, 253, 180,  89,
29    120, 152,   6, 106, 231,  70, 113, 186, 212,  37, 171,  66, 136, 162, 141, 250,
30    114,   7, 185,  85, 248, 238, 172,  10,  54,  73,  42, 104,  60,  56, 241, 164,
31     64,  40, 211, 123, 187, 201,  67, 193,  21, 227, 173, 244, 119, 199, 128, 158,
32];
33
34// RFC 3713 §2.4 base constants.
35const SIGMA: [u64; 6] = [
36    0xA09E_667F_3BCC_908B,
37    0xB67A_E858_4CAA_73B2,
38    0xC6EF_372F_E94F_82BE,
39    0x54FF_53A5_F1D3_6F1C,
40    0x10E5_27FA_DE68_2D1D,
41    0xB056_88C2_B3E6_C1FD,
42];
43
44const SBOX1_ANF: [[u128; 2]; 8] = crate::ct::build_byte_sbox_anf(&SBOX1);
45
46const fn build_sbox2() -> [u8; 256] {
47    let mut out = [0u8; 256];
48    let mut i = 0usize;
49    while i < 256 {
50        let v = SBOX1[i];
51        out[i] = v.rotate_left(1);
52        i += 1;
53    }
54    out
55}
56
57const fn build_sbox3() -> [u8; 256] {
58    let mut out = [0u8; 256];
59    let mut i = 0usize;
60    while i < 256 {
61        let v = SBOX1[i];
62        out[i] = v.rotate_left(7);
63        i += 1;
64    }
65    out
66}
67
68const fn build_sbox4() -> [u8; 256] {
69    let mut out = [0u8; 256];
70    let mut i = 0usize;
71    while i < 256 {
72        // sbox4(x) = sbox1(x.rotate_left(1)) = sbox1((x<<1)|(x>>7))
73        let x = i as u8;
74        let rotated = x.rotate_left(1);
75        out[i] = SBOX1[rotated as usize];
76        i += 1;
77    }
78    out
79}
80
81const SBOX2: [u8; 256] = build_sbox2();
82const SBOX3: [u8; 256] = build_sbox3();
83const SBOX4: [u8; 256] = build_sbox4();
84
85#[derive(Clone, Copy)]
86struct Subkeys18 {
87    kw: [u64; 4],
88    k: [u64; 18],
89    ke: [u64; 4],
90}
91
92#[derive(Clone, Copy)]
93struct Subkeys24 {
94    kw: [u64; 4],
95    k: [u64; 24],
96    ke: [u64; 6],
97}
98
99#[inline]
100fn sbox1(x: u8) -> u8 {
101    SBOX1[x as usize]
102}
103
104#[inline]
105fn sbox1_ct(x: u8) -> u8 {
106    crate::ct::eval_byte_sbox(&SBOX1_ANF, x)
107}
108
109#[inline]
110fn sbox2(x: u8) -> u8 {
111    SBOX2[x as usize]
112}
113
114#[inline]
115fn sbox3(x: u8) -> u8 {
116    SBOX3[x as usize]
117}
118
119#[inline]
120fn sbox4(x: u8) -> u8 {
121    SBOX4[x as usize]
122}
123
124#[inline]
125fn sbox2_ct(x: u8) -> u8 {
126    sbox1_ct(x).rotate_left(1)
127}
128
129#[inline]
130fn sbox3_ct(x: u8) -> u8 {
131    sbox1_ct(x).rotate_left(7)
132}
133
134#[inline]
135fn sbox4_ct(x: u8) -> u8 {
136    sbox1_ct(x.rotate_left(1))
137}
138
139#[inline]
140fn camellia_f(input: u64, subkey: u64) -> u64 {
141    let x = (input ^ subkey).to_be_bytes();
142
143    let t1 = sbox1(x[0]);
144    let t2 = sbox2(x[1]);
145    let t3 = sbox3(x[2]);
146    let t4 = sbox4(x[3]);
147    let t5 = sbox2(x[4]);
148    let t6 = sbox3(x[5]);
149    let t7 = sbox4(x[6]);
150    let t8 = sbox1(x[7]);
151
152    u64::from_be_bytes([
153        t1 ^ t3 ^ t4 ^ t6 ^ t7 ^ t8,
154        t1 ^ t2 ^ t4 ^ t5 ^ t7 ^ t8,
155        t1 ^ t2 ^ t3 ^ t5 ^ t6 ^ t8,
156        t2 ^ t3 ^ t4 ^ t5 ^ t6 ^ t7,
157        t1 ^ t2 ^ t6 ^ t7 ^ t8,
158        t2 ^ t3 ^ t5 ^ t7 ^ t8,
159        t3 ^ t4 ^ t5 ^ t6 ^ t8,
160        t1 ^ t4 ^ t5 ^ t6 ^ t7,
161    ])
162}
163
164#[inline]
165fn camellia_f_ct(input: u64, subkey: u64) -> u64 {
166    let x = (input ^ subkey).to_be_bytes();
167
168    let t1 = sbox1_ct(x[0]);
169    let t2 = sbox2_ct(x[1]);
170    let t3 = sbox3_ct(x[2]);
171    let t4 = sbox4_ct(x[3]);
172    let t5 = sbox2_ct(x[4]);
173    let t6 = sbox3_ct(x[5]);
174    let t7 = sbox4_ct(x[6]);
175    let t8 = sbox1_ct(x[7]);
176
177    u64::from_be_bytes([
178        t1 ^ t3 ^ t4 ^ t6 ^ t7 ^ t8,
179        t1 ^ t2 ^ t4 ^ t5 ^ t7 ^ t8,
180        t1 ^ t2 ^ t3 ^ t5 ^ t6 ^ t8,
181        t2 ^ t3 ^ t4 ^ t5 ^ t6 ^ t7,
182        t1 ^ t2 ^ t6 ^ t7 ^ t8,
183        t2 ^ t3 ^ t5 ^ t7 ^ t8,
184        t3 ^ t4 ^ t5 ^ t6 ^ t8,
185        t1 ^ t4 ^ t5 ^ t6 ^ t7,
186    ])
187}
188
189#[inline]
190fn fl(x: u64, ke: u64) -> u64 {
191    let (mut x1, mut x2) = split_u64_words(x);
192    let (k1, k2) = split_u64_words(ke);
193    x2 ^= (x1 & k1).rotate_left(1);
194    x1 ^= x2 | k2;
195    (u64::from(x1) << 32) | u64::from(x2)
196}
197
198#[inline]
199fn fl_inv(x: u64, ke: u64) -> u64 {
200    let (mut y1, mut y2) = split_u64_words(x);
201    let (k1, k2) = split_u64_words(ke);
202    y1 ^= y2 | k2;
203    y2 ^= (y1 & k1).rotate_left(1);
204    (u64::from(y1) << 32) | u64::from(y2)
205}
206
207#[inline]
208fn halves(x: u128) -> (u64, u64) {
209    let bytes = x.to_be_bytes();
210    (
211        u64::from_be_bytes([
212            bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7],
213        ]),
214        u64::from_be_bytes([
215            bytes[8], bytes[9], bytes[10], bytes[11], bytes[12], bytes[13], bytes[14], bytes[15],
216        ]),
217    )
218}
219
220#[inline]
221fn split_u64_words(x: u64) -> (u32, u32) {
222    let bytes = x.to_be_bytes();
223    (
224        u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]),
225        u32::from_be_bytes([bytes[4], bytes[5], bytes[6], bytes[7]]),
226    )
227}
228
229#[inline]
230fn rot_pair(x: u128, bits: u32) -> (u64, u64) {
231    halves(x.rotate_left(bits))
232}
233
234fn derive_ka(kl: u128, kr: u128, use_ct: bool) -> u128 {
235    // RFC 3713 §2.2 key schedule "KA" derivation.
236    let x = kl ^ kr;
237    let (mut d1, mut d2) = halves(x);
238    let (kl_l, kl_r) = halves(kl);
239
240    let f = if use_ct { camellia_f_ct } else { camellia_f };
241
242    d2 ^= f(d1, SIGMA[0]);
243    d1 ^= f(d2, SIGMA[1]);
244    d1 ^= kl_l;
245    d2 ^= kl_r;
246    d2 ^= f(d1, SIGMA[2]);
247    d1 ^= f(d2, SIGMA[3]);
248
249    (u128::from(d1) << 64) | u128::from(d2)
250}
251
252fn derive_kb(ka: u128, kr: u128, use_ct: bool) -> u128 {
253    // RFC 3713 §2.2 key schedule "KB" derivation (192/256-bit keys only).
254    let (kr_l, kr_r) = halves(kr);
255    let (mut d1, mut d2) = halves(ka);
256
257    let f = if use_ct { camellia_f_ct } else { camellia_f };
258
259    d1 ^= kr_l;
260    d2 ^= kr_r;
261    d2 ^= f(d1, SIGMA[4]);
262    d1 ^= f(d2, SIGMA[5]);
263
264    (u128::from(d1) << 64) | u128::from(d2)
265}
266
267fn expand_128(key: &[u8; 16], use_ct: bool) -> Subkeys18 {
268    let kl = u128::from_be_bytes(*key);
269    let ka = derive_ka(kl, 0, use_ct);
270
271    // RFC 3713 §2.4 rotation schedule for 128-bit keys (KL and KA branches).
272    let left_key_rotations = [
273        rot_pair(kl, 0),
274        rot_pair(kl, 15),
275        rot_pair(kl, 45),
276        rot_pair(kl, 60),
277        rot_pair(kl, 77),
278        rot_pair(kl, 94),
279        rot_pair(kl, 111),
280    ];
281    let aux_key_rotations = [
282        rot_pair(ka, 0),
283        rot_pair(ka, 15),
284        rot_pair(ka, 30),
285        rot_pair(ka, 45),
286        rot_pair(ka, 60),
287        rot_pair(ka, 94),
288        rot_pair(ka, 111),
289    ];
290
291    let mut out = Subkeys18 {
292        kw: [0; 4],
293        k: [0; 18],
294        ke: [0; 4],
295    };
296
297    out.kw[0] = left_key_rotations[0].0;
298    out.kw[1] = left_key_rotations[0].1;
299    out.kw[2] = aux_key_rotations[6].0;
300    out.kw[3] = aux_key_rotations[6].1;
301
302    out.k[0] = aux_key_rotations[0].0;
303    out.k[1] = aux_key_rotations[0].1;
304    out.k[2] = left_key_rotations[1].0;
305    out.k[3] = left_key_rotations[1].1;
306    out.k[4] = aux_key_rotations[1].0;
307    out.k[5] = aux_key_rotations[1].1;
308    out.ke[0] = aux_key_rotations[2].0;
309    out.ke[1] = aux_key_rotations[2].1;
310    out.k[6] = left_key_rotations[2].0;
311    out.k[7] = left_key_rotations[2].1;
312    out.k[8] = aux_key_rotations[3].0;
313    out.k[9] = left_key_rotations[3].1;
314    out.k[10] = aux_key_rotations[4].0;
315    out.k[11] = aux_key_rotations[4].1;
316    out.ke[2] = left_key_rotations[4].0;
317    out.ke[3] = left_key_rotations[4].1;
318    out.k[12] = left_key_rotations[5].0;
319    out.k[13] = left_key_rotations[5].1;
320    out.k[14] = aux_key_rotations[5].0;
321    out.k[15] = aux_key_rotations[5].1;
322    out.k[16] = left_key_rotations[6].0;
323    out.k[17] = left_key_rotations[6].1;
324
325    out
326}
327
328fn expand_192_256(kl: u128, kr: u128, use_ct: bool) -> Subkeys24 {
329    let ka = derive_ka(kl, kr, use_ct);
330    let kb = derive_kb(ka, kr, use_ct);
331
332    // RFC 3713 §2.4 rotation schedule for 192/256-bit keys.
333    // KL, KR, KA, and KB each contribute specific rotated 64-bit halves.
334    let left_key_rotations = [
335        rot_pair(kl, 0),
336        rot_pair(kl, 45),
337        rot_pair(kl, 60),
338        rot_pair(kl, 77),
339        rot_pair(kl, 111),
340    ];
341    let right_key_rotations = [
342        rot_pair(kr, 15),
343        rot_pair(kr, 30),
344        rot_pair(kr, 60),
345        rot_pair(kr, 94),
346    ];
347    let aux_key_rotations = [
348        rot_pair(ka, 15),
349        rot_pair(ka, 45),
350        rot_pair(ka, 77),
351        rot_pair(ka, 94),
352    ];
353    let secondary_key_rotations = [
354        rot_pair(kb, 0),
355        rot_pair(kb, 30),
356        rot_pair(kb, 60),
357        rot_pair(kb, 111),
358    ];
359
360    let mut out = Subkeys24 {
361        kw: [0; 4],
362        k: [0; 24],
363        ke: [0; 6],
364    };
365
366    out.kw[0] = left_key_rotations[0].0;
367    out.kw[1] = left_key_rotations[0].1;
368    out.kw[2] = secondary_key_rotations[3].0;
369    out.kw[3] = secondary_key_rotations[3].1;
370
371    out.k[0] = secondary_key_rotations[0].0;
372    out.k[1] = secondary_key_rotations[0].1;
373    out.k[2] = right_key_rotations[0].0;
374    out.k[3] = right_key_rotations[0].1;
375    out.k[4] = aux_key_rotations[0].0;
376    out.k[5] = aux_key_rotations[0].1;
377    out.ke[0] = right_key_rotations[1].0;
378    out.ke[1] = right_key_rotations[1].1;
379    out.k[6] = secondary_key_rotations[1].0;
380    out.k[7] = secondary_key_rotations[1].1;
381    out.k[8] = left_key_rotations[1].0;
382    out.k[9] = left_key_rotations[1].1;
383    out.k[10] = aux_key_rotations[1].0;
384    out.k[11] = aux_key_rotations[1].1;
385    out.ke[2] = left_key_rotations[2].0;
386    out.ke[3] = left_key_rotations[2].1;
387    out.k[12] = right_key_rotations[2].0;
388    out.k[13] = right_key_rotations[2].1;
389    out.k[14] = secondary_key_rotations[2].0;
390    out.k[15] = secondary_key_rotations[2].1;
391    out.k[16] = left_key_rotations[3].0;
392    out.k[17] = left_key_rotations[3].1;
393    out.ke[4] = aux_key_rotations[2].0;
394    out.ke[5] = aux_key_rotations[2].1;
395    out.k[18] = right_key_rotations[3].0;
396    out.k[19] = right_key_rotations[3].1;
397    out.k[20] = aux_key_rotations[3].0;
398    out.k[21] = aux_key_rotations[3].1;
399    out.k[22] = left_key_rotations[4].0;
400    out.k[23] = left_key_rotations[4].1;
401
402    out
403}
404
405fn camellia_encrypt_18(block: [u8; 16], sk: &Subkeys18, use_ct: bool) -> [u8; 16] {
406    let mut d1 = u64::from_be_bytes(block[..8].try_into().unwrap());
407    let mut d2 = u64::from_be_bytes(block[8..].try_into().unwrap());
408    let f = if use_ct { camellia_f_ct } else { camellia_f };
409
410    d1 ^= sk.kw[0];
411    d2 ^= sk.kw[1];
412
413    let mut idx = 0usize;
414    while idx < 6 {
415        d2 ^= f(d1, sk.k[idx]);
416        d1 ^= f(d2, sk.k[idx + 1]);
417        idx += 2;
418    }
419    d1 = fl(d1, sk.ke[0]);
420    d2 = fl_inv(d2, sk.ke[1]);
421
422    while idx < 12 {
423        d2 ^= f(d1, sk.k[idx]);
424        d1 ^= f(d2, sk.k[idx + 1]);
425        idx += 2;
426    }
427    d1 = fl(d1, sk.ke[2]);
428    d2 = fl_inv(d2, sk.ke[3]);
429
430    while idx < 18 {
431        d2 ^= f(d1, sk.k[idx]);
432        d1 ^= f(d2, sk.k[idx + 1]);
433        idx += 2;
434    }
435
436    let mut out = [0u8; 16];
437    out[..8].copy_from_slice(&(d2 ^ sk.kw[2]).to_be_bytes());
438    out[8..].copy_from_slice(&(d1 ^ sk.kw[3]).to_be_bytes());
439    out
440}
441
442fn camellia_decrypt_18(block: [u8; 16], sk: &Subkeys18, use_ct: bool) -> [u8; 16] {
443    let mut d2 = u64::from_be_bytes(block[..8].try_into().unwrap()) ^ sk.kw[2];
444    let mut d1 = u64::from_be_bytes(block[8..].try_into().unwrap()) ^ sk.kw[3];
445    let f = if use_ct { camellia_f_ct } else { camellia_f };
446
447    let mut idx = 18usize;
448    while idx > 12 {
449        idx -= 2;
450        d1 ^= f(d2, sk.k[idx + 1]);
451        d2 ^= f(d1, sk.k[idx]);
452    }
453    d2 = fl(d2, sk.ke[3]);
454    d1 = fl_inv(d1, sk.ke[2]);
455
456    while idx > 6 {
457        idx -= 2;
458        d1 ^= f(d2, sk.k[idx + 1]);
459        d2 ^= f(d1, sk.k[idx]);
460    }
461    d2 = fl(d2, sk.ke[1]);
462    d1 = fl_inv(d1, sk.ke[0]);
463
464    while idx > 0 {
465        idx -= 2;
466        d1 ^= f(d2, sk.k[idx + 1]);
467        d2 ^= f(d1, sk.k[idx]);
468    }
469
470    let mut out = [0u8; 16];
471    out[..8].copy_from_slice(&(d1 ^ sk.kw[0]).to_be_bytes());
472    out[8..].copy_from_slice(&(d2 ^ sk.kw[1]).to_be_bytes());
473    out
474}
475
476fn camellia_encrypt_24(block: [u8; 16], sk: &Subkeys24, use_ct: bool) -> [u8; 16] {
477    let mut d1 = u64::from_be_bytes(block[..8].try_into().unwrap());
478    let mut d2 = u64::from_be_bytes(block[8..].try_into().unwrap());
479    let f = if use_ct { camellia_f_ct } else { camellia_f };
480
481    d1 ^= sk.kw[0];
482    d2 ^= sk.kw[1];
483
484    let mut idx = 0usize;
485    while idx < 6 {
486        d2 ^= f(d1, sk.k[idx]);
487        d1 ^= f(d2, sk.k[idx + 1]);
488        idx += 2;
489    }
490    d1 = fl(d1, sk.ke[0]);
491    d2 = fl_inv(d2, sk.ke[1]);
492
493    while idx < 12 {
494        d2 ^= f(d1, sk.k[idx]);
495        d1 ^= f(d2, sk.k[idx + 1]);
496        idx += 2;
497    }
498    d1 = fl(d1, sk.ke[2]);
499    d2 = fl_inv(d2, sk.ke[3]);
500
501    while idx < 18 {
502        d2 ^= f(d1, sk.k[idx]);
503        d1 ^= f(d2, sk.k[idx + 1]);
504        idx += 2;
505    }
506    d1 = fl(d1, sk.ke[4]);
507    d2 = fl_inv(d2, sk.ke[5]);
508
509    while idx < 24 {
510        d2 ^= f(d1, sk.k[idx]);
511        d1 ^= f(d2, sk.k[idx + 1]);
512        idx += 2;
513    }
514
515    let mut out = [0u8; 16];
516    out[..8].copy_from_slice(&(d2 ^ sk.kw[2]).to_be_bytes());
517    out[8..].copy_from_slice(&(d1 ^ sk.kw[3]).to_be_bytes());
518    out
519}
520
521fn camellia_decrypt_24(block: [u8; 16], sk: &Subkeys24, use_ct: bool) -> [u8; 16] {
522    let mut d2 = u64::from_be_bytes(block[..8].try_into().unwrap()) ^ sk.kw[2];
523    let mut d1 = u64::from_be_bytes(block[8..].try_into().unwrap()) ^ sk.kw[3];
524    let f = if use_ct { camellia_f_ct } else { camellia_f };
525
526    let mut idx = 24usize;
527    while idx > 18 {
528        idx -= 2;
529        d1 ^= f(d2, sk.k[idx + 1]);
530        d2 ^= f(d1, sk.k[idx]);
531    }
532    d2 = fl(d2, sk.ke[5]);
533    d1 = fl_inv(d1, sk.ke[4]);
534
535    while idx > 12 {
536        idx -= 2;
537        d1 ^= f(d2, sk.k[idx + 1]);
538        d2 ^= f(d1, sk.k[idx]);
539    }
540    d2 = fl(d2, sk.ke[3]);
541    d1 = fl_inv(d1, sk.ke[2]);
542
543    while idx > 6 {
544        idx -= 2;
545        d1 ^= f(d2, sk.k[idx + 1]);
546        d2 ^= f(d1, sk.k[idx]);
547    }
548    d2 = fl(d2, sk.ke[1]);
549    d1 = fl_inv(d1, sk.ke[0]);
550
551    while idx > 0 {
552        idx -= 2;
553        d1 ^= f(d2, sk.k[idx + 1]);
554        d2 ^= f(d1, sk.k[idx]);
555    }
556
557    let mut out = [0u8; 16];
558    out[..8].copy_from_slice(&(d1 ^ sk.kw[0]).to_be_bytes());
559    out[8..].copy_from_slice(&(d2 ^ sk.kw[1]).to_be_bytes());
560    out
561}
562
563/// Camellia-128 fast software path.
564pub struct Camellia128 {
565    subkeys: Subkeys18,
566}
567
568impl Camellia128 {
569    #[must_use]
570    pub fn new(key: &[u8; 16]) -> Self {
571        Self {
572            subkeys: expand_128(key, false),
573        }
574    }
575
576    pub fn new_wiping(key: &mut [u8; 16]) -> Self {
577        let out = Self::new(key);
578        crate::ct::zeroize_slice(key.as_mut_slice());
579        out
580    }
581
582    #[must_use]
583    pub fn encrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
584        camellia_encrypt_18(*block, &self.subkeys, false)
585    }
586
587    #[must_use]
588    pub fn decrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
589        camellia_decrypt_18(*block, &self.subkeys, false)
590    }
591}
592
593/// Camellia-128 constant-time software path.
594pub struct Camellia128Ct {
595    subkeys: Subkeys18,
596}
597
598impl Camellia128Ct {
599    #[must_use]
600    pub fn new(key: &[u8; 16]) -> Self {
601        Self {
602            subkeys: expand_128(key, true),
603        }
604    }
605
606    pub fn new_wiping(key: &mut [u8; 16]) -> Self {
607        let out = Self::new(key);
608        crate::ct::zeroize_slice(key.as_mut_slice());
609        out
610    }
611
612    #[must_use]
613    pub fn encrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
614        camellia_encrypt_18(*block, &self.subkeys, true)
615    }
616
617    #[must_use]
618    pub fn decrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
619        camellia_decrypt_18(*block, &self.subkeys, true)
620    }
621}
622
623/// Camellia-192 fast software path.
624pub struct Camellia192 {
625    subkeys: Subkeys24,
626}
627
628impl Camellia192 {
629    #[must_use]
630    pub fn new(key: &[u8; 24]) -> Self {
631        let mut kl_bytes = [0u8; 16];
632        kl_bytes.copy_from_slice(&key[..16]);
633        let kl = u128::from_be_bytes(kl_bytes);
634        let mut tail_bytes = [0u8; 8];
635        tail_bytes.copy_from_slice(&key[16..]);
636        let tail = u64::from_be_bytes(tail_bytes);
637        let kr = (u128::from(tail) << 64) | u128::from(!tail);
638        Self {
639            subkeys: expand_192_256(kl, kr, false),
640        }
641    }
642
643    pub fn new_wiping(key: &mut [u8; 24]) -> Self {
644        let out = Self::new(key);
645        crate::ct::zeroize_slice(key.as_mut_slice());
646        out
647    }
648
649    #[must_use]
650    pub fn encrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
651        camellia_encrypt_24(*block, &self.subkeys, false)
652    }
653
654    #[must_use]
655    pub fn decrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
656        camellia_decrypt_24(*block, &self.subkeys, false)
657    }
658}
659
660/// Camellia-192 constant-time software path.
661pub struct Camellia192Ct {
662    subkeys: Subkeys24,
663}
664
665impl Camellia192Ct {
666    #[must_use]
667    pub fn new(key: &[u8; 24]) -> Self {
668        let mut kl_bytes = [0u8; 16];
669        kl_bytes.copy_from_slice(&key[..16]);
670        let kl = u128::from_be_bytes(kl_bytes);
671        let mut tail_bytes = [0u8; 8];
672        tail_bytes.copy_from_slice(&key[16..]);
673        let tail = u64::from_be_bytes(tail_bytes);
674        let kr = (u128::from(tail) << 64) | u128::from(!tail);
675        Self {
676            subkeys: expand_192_256(kl, kr, true),
677        }
678    }
679
680    pub fn new_wiping(key: &mut [u8; 24]) -> Self {
681        let out = Self::new(key);
682        crate::ct::zeroize_slice(key.as_mut_slice());
683        out
684    }
685
686    #[must_use]
687    pub fn encrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
688        camellia_encrypt_24(*block, &self.subkeys, true)
689    }
690
691    #[must_use]
692    pub fn decrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
693        camellia_decrypt_24(*block, &self.subkeys, true)
694    }
695}
696
697/// Camellia-256 fast software path.
698pub struct Camellia256 {
699    subkeys: Subkeys24,
700}
701
702impl Camellia256 {
703    #[must_use]
704    pub fn new(key: &[u8; 32]) -> Self {
705        let mut left_key_bytes = [0u8; 16];
706        left_key_bytes.copy_from_slice(&key[..16]);
707        let kl = u128::from_be_bytes(left_key_bytes);
708        let mut right_key_bytes = [0u8; 16];
709        right_key_bytes.copy_from_slice(&key[16..]);
710        let kr = u128::from_be_bytes(right_key_bytes);
711        Self {
712            subkeys: expand_192_256(kl, kr, false),
713        }
714    }
715
716    pub fn new_wiping(key: &mut [u8; 32]) -> Self {
717        let out = Self::new(key);
718        crate::ct::zeroize_slice(key.as_mut_slice());
719        out
720    }
721
722    #[must_use]
723    pub fn encrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
724        camellia_encrypt_24(*block, &self.subkeys, false)
725    }
726
727    #[must_use]
728    pub fn decrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
729        camellia_decrypt_24(*block, &self.subkeys, false)
730    }
731}
732
733/// Camellia-256 constant-time software path.
734pub struct Camellia256Ct {
735    subkeys: Subkeys24,
736}
737
738impl Camellia256Ct {
739    #[must_use]
740    pub fn new(key: &[u8; 32]) -> Self {
741        let mut left_key_bytes = [0u8; 16];
742        left_key_bytes.copy_from_slice(&key[..16]);
743        let kl = u128::from_be_bytes(left_key_bytes);
744        let mut right_key_bytes = [0u8; 16];
745        right_key_bytes.copy_from_slice(&key[16..]);
746        let kr = u128::from_be_bytes(right_key_bytes);
747        Self {
748            subkeys: expand_192_256(kl, kr, true),
749        }
750    }
751
752    pub fn new_wiping(key: &mut [u8; 32]) -> Self {
753        let out = Self::new(key);
754        crate::ct::zeroize_slice(key.as_mut_slice());
755        out
756    }
757
758    #[must_use]
759    pub fn encrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
760        camellia_encrypt_24(*block, &self.subkeys, true)
761    }
762
763    #[must_use]
764    pub fn decrypt_block(&self, block: &[u8; 16]) -> [u8; 16] {
765        camellia_decrypt_24(*block, &self.subkeys, true)
766    }
767}
768
769/// Camellia usually refers to the 128-bit-key variant.
770pub type Camellia = Camellia128;
771/// Constant-time Camellia-128 alias.
772pub type CamelliaCt = Camellia128Ct;
773
774macro_rules! impl_block_cipher {
775    ($name:ty) => {
776        impl crate::BlockCipher for $name {
777            const BLOCK_LEN: usize = 16;
778            fn encrypt(&self, block: &mut [u8]) {
779                let arr: &[u8; 16] = (&*block).try_into().expect("wrong block length");
780                block.copy_from_slice(&self.encrypt_block(arr));
781            }
782            fn decrypt(&self, block: &mut [u8]) {
783                let arr: &[u8; 16] = (&*block).try_into().expect("wrong block length");
784                block.copy_from_slice(&self.decrypt_block(arr));
785            }
786        }
787    };
788}
789
790impl_block_cipher!(Camellia128);
791impl_block_cipher!(Camellia128Ct);
792impl_block_cipher!(Camellia192);
793impl_block_cipher!(Camellia192Ct);
794impl_block_cipher!(Camellia256);
795impl_block_cipher!(Camellia256Ct);
796
797impl Drop for Camellia128 {
798    fn drop(&mut self) {
799        crate::ct::zeroize_slice(self.subkeys.kw.as_mut_slice());
800        crate::ct::zeroize_slice(self.subkeys.k.as_mut_slice());
801        crate::ct::zeroize_slice(self.subkeys.ke.as_mut_slice());
802    }
803}
804
805impl Drop for Camellia128Ct {
806    fn drop(&mut self) {
807        crate::ct::zeroize_slice(self.subkeys.kw.as_mut_slice());
808        crate::ct::zeroize_slice(self.subkeys.k.as_mut_slice());
809        crate::ct::zeroize_slice(self.subkeys.ke.as_mut_slice());
810    }
811}
812
813impl Drop for Camellia192 {
814    fn drop(&mut self) {
815        crate::ct::zeroize_slice(self.subkeys.kw.as_mut_slice());
816        crate::ct::zeroize_slice(self.subkeys.k.as_mut_slice());
817        crate::ct::zeroize_slice(self.subkeys.ke.as_mut_slice());
818    }
819}
820
821impl Drop for Camellia192Ct {
822    fn drop(&mut self) {
823        crate::ct::zeroize_slice(self.subkeys.kw.as_mut_slice());
824        crate::ct::zeroize_slice(self.subkeys.k.as_mut_slice());
825        crate::ct::zeroize_slice(self.subkeys.ke.as_mut_slice());
826    }
827}
828
829impl Drop for Camellia256 {
830    fn drop(&mut self) {
831        crate::ct::zeroize_slice(self.subkeys.kw.as_mut_slice());
832        crate::ct::zeroize_slice(self.subkeys.k.as_mut_slice());
833        crate::ct::zeroize_slice(self.subkeys.ke.as_mut_slice());
834    }
835}
836
837impl Drop for Camellia256Ct {
838    fn drop(&mut self) {
839        crate::ct::zeroize_slice(self.subkeys.kw.as_mut_slice());
840        crate::ct::zeroize_slice(self.subkeys.k.as_mut_slice());
841        crate::ct::zeroize_slice(self.subkeys.ke.as_mut_slice());
842    }
843}
844
845#[cfg(test)]
846mod tests {
847    use super::*;
848
849    fn xorshift64(state: &mut u64) -> u64 {
850        let mut x = *state;
851        x ^= x << 13;
852        x ^= x >> 7;
853        x ^= x << 17;
854        *state = x;
855        x
856    }
857
858    fn fill_bytes(state: &mut u64, out: &mut [u8]) {
859        for chunk in out.chunks_mut(8) {
860            let bytes = xorshift64(state).to_le_bytes();
861            let n = chunk.len();
862            chunk.copy_from_slice(&bytes[..n]);
863        }
864    }
865
866    fn h16(s: &str) -> [u8; 16] {
867        let b: Vec<u8> = (0..s.len())
868            .step_by(2)
869            .map(|i| u8::from_str_radix(&s[i..i + 2], 16).unwrap())
870            .collect();
871        b.try_into().unwrap()
872    }
873
874    fn h24(s: &str) -> [u8; 24] {
875        let b: Vec<u8> = (0..s.len())
876            .step_by(2)
877            .map(|i| u8::from_str_radix(&s[i..i + 2], 16).unwrap())
878            .collect();
879        b.try_into().unwrap()
880    }
881
882    fn h32(s: &str) -> [u8; 32] {
883        let b: Vec<u8> = (0..s.len())
884            .step_by(2)
885            .map(|i| u8::from_str_radix(&s[i..i + 2], 16).unwrap())
886            .collect();
887        b.try_into().unwrap()
888    }
889
890    #[test]
891    fn ct_sbox_matches_table() {
892        for x in 0u8..=255 {
893            assert_eq!(sbox1_ct(x), sbox1(x));
894        }
895    }
896
897    #[test]
898    fn camellia_fast_and_ct_match_random_vectors() {
899        let mut seed = 0x9e37_79b9_7f4a_7c15u64;
900        for _ in 0..128 {
901            let mut block = [0u8; 16];
902            fill_bytes(&mut seed, &mut block);
903
904            let mut k128 = [0u8; 16];
905            fill_bytes(&mut seed, &mut k128);
906            let fast128 = Camellia128::new(&k128);
907            let ct128 = Camellia128Ct::new(&k128);
908            let c128 = fast128.encrypt_block(&block);
909            assert_eq!(c128, ct128.encrypt_block(&block));
910            assert_eq!(block, fast128.decrypt_block(&c128));
911            assert_eq!(block, ct128.decrypt_block(&c128));
912
913            let mut k192 = [0u8; 24];
914            fill_bytes(&mut seed, &mut k192);
915            let fast192 = Camellia192::new(&k192);
916            let ct192 = Camellia192Ct::new(&k192);
917            let c192 = fast192.encrypt_block(&block);
918            assert_eq!(c192, ct192.encrypt_block(&block));
919            assert_eq!(block, fast192.decrypt_block(&c192));
920            assert_eq!(block, ct192.decrypt_block(&c192));
921
922            let mut k256 = [0u8; 32];
923            fill_bytes(&mut seed, &mut k256);
924            let fast256 = Camellia256::new(&k256);
925            let ct256 = Camellia256Ct::new(&k256);
926            let c256 = fast256.encrypt_block(&block);
927            assert_eq!(c256, ct256.encrypt_block(&block));
928            assert_eq!(block, fast256.decrypt_block(&c256));
929            assert_eq!(block, ct256.decrypt_block(&c256));
930        }
931    }
932
933    #[test]
934    fn camellia128_kat() {
935        let key = h16("0123456789abcdeffedcba9876543210");
936        let pt = h16("0123456789abcdeffedcba9876543210");
937        let ct = h16("67673138549669730857065648eabe43");
938        let cipher = Camellia128::new(&key);
939        assert_eq!(cipher.encrypt_block(&pt), ct);
940        assert_eq!(cipher.decrypt_block(&ct), pt);
941    }
942
943    #[test]
944    fn camellia128_ct_kat() {
945        let key = h16("0123456789abcdeffedcba9876543210");
946        let pt = h16("0123456789abcdeffedcba9876543210");
947        let ct = h16("67673138549669730857065648eabe43");
948        let cipher = Camellia128Ct::new(&key);
949        assert_eq!(cipher.encrypt_block(&pt), ct);
950        assert_eq!(cipher.decrypt_block(&ct), pt);
951    }
952
953    #[test]
954    fn camellia192_kat() {
955        let key = h24("0123456789abcdeffedcba98765432100011223344556677");
956        let pt = h16("0123456789abcdeffedcba9876543210");
957        let ct = h16("b4993401b3e996f84ee5cee7d79b09b9");
958        let cipher = Camellia192::new(&key);
959        assert_eq!(cipher.encrypt_block(&pt), ct);
960        assert_eq!(cipher.decrypt_block(&ct), pt);
961    }
962
963    #[test]
964    fn camellia192_ct_kat() {
965        let key = h24("0123456789abcdeffedcba98765432100011223344556677");
966        let pt = h16("0123456789abcdeffedcba9876543210");
967        let ct = h16("b4993401b3e996f84ee5cee7d79b09b9");
968        let cipher = Camellia192Ct::new(&key);
969        assert_eq!(cipher.encrypt_block(&pt), ct);
970        assert_eq!(cipher.decrypt_block(&ct), pt);
971    }
972
973    #[test]
974    fn camellia256_kat() {
975        let key = h32("0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff");
976        let pt = h16("0123456789abcdeffedcba9876543210");
977        let ct = h16("9acc237dff16d76c20ef7c919e3a7509");
978        let cipher = Camellia256::new(&key);
979        assert_eq!(cipher.encrypt_block(&pt), ct);
980        assert_eq!(cipher.decrypt_block(&ct), pt);
981    }
982
983    #[test]
984    fn camellia256_ct_kat() {
985        let key = h32("0123456789abcdeffedcba987654321000112233445566778899aabbccddeeff");
986        let pt = h16("0123456789abcdeffedcba9876543210");
987        let ct = h16("9acc237dff16d76c20ef7c919e3a7509");
988        let cipher = Camellia256Ct::new(&key);
989        assert_eq!(cipher.encrypt_block(&pt), ct);
990        assert_eq!(cipher.decrypt_block(&ct), pt);
991    }
992
993    #[test]
994    fn camellia128_matches_openssl_ecb() {
995        let key_hex = "0123456789abcdeffedcba9876543210";
996        let pt_hex = "0123456789abcdeffedcba9876543210";
997        let Some(expected) =
998            crate::test_utils::run_openssl_enc("-camellia-128-ecb", key_hex, None, &h16(pt_hex))
999        else {
1000            return;
1001        };
1002
1003        let cipher = Camellia128::new(&h16(key_hex));
1004        assert_eq!(
1005            cipher.encrypt_block(&h16(pt_hex)).as_slice(),
1006            expected.as_slice()
1007        );
1008    }
1009}