1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
use rand_core::{ RngCore, CryptoRng };
use subtle::{ ConstantTimeEq, ConditionallyAssignable };
use ::params::{
    SYMBYTES,
    CIPHERTEXTBYTES, PUBLICKEYBYTES, SECRETKEYBYTES,
    INDCPA_BYTES,
    INDCPA_SECRETKEYBYTES, INDCPA_PUBLICKEYBYTES,
    POLYVECBYTES
};
use ::indcpa;


pub fn keypair<R: RngCore + CryptoRng>(rng: &mut R, pk: &mut [u8; PUBLICKEYBYTES], sk: &mut [u8; SECRETKEYBYTES]) {
    indcpa::keypair(rng, pk, array_mut_ref!(sk, 0, POLYVECBYTES));
    array_mut_ref!(sk, INDCPA_SECRETKEYBYTES, INDCPA_PUBLICKEYBYTES).clone_from(pk);

    sha3_256!(&mut sk[SECRETKEYBYTES - 2 * SYMBYTES..][..SYMBYTES]; &pk[..PUBLICKEYBYTES]);

    rng.fill_bytes(&mut sk[SECRETKEYBYTES - SYMBYTES..][..SYMBYTES]);
}

pub fn enc<R: RngCore + CryptoRng>(rng: &mut R, c: &mut [u8; CIPHERTEXTBYTES], k: &mut [u8; SYMBYTES], pk: &[u8; PUBLICKEYBYTES]) {
    let mut buf = [0; SYMBYTES];
    let mut buf2 = [0; SYMBYTES];
    let mut kr = [0; SYMBYTES + SYMBYTES];

    rng.fill_bytes(&mut buf);
    sha3_256!(&mut buf; &buf);

    sha3_256!(&mut buf2; &pk[..PUBLICKEYBYTES]);
    sha3_512!(&mut kr; &buf, &buf2);

    indcpa::enc(array_mut_ref!(c, 0, INDCPA_BYTES), &buf, pk, array_ref!(&kr, SYMBYTES, SYMBYTES));

    sha3_256!(&mut kr[SYMBYTES..][..SYMBYTES]; c);
    sha3_256!(k; &kr);
}

pub fn dec(k: &mut [u8; SYMBYTES], c: &[u8; CIPHERTEXTBYTES], sk: &[u8; SECRETKEYBYTES]) -> bool {
    let mut cmp = [0; CIPHERTEXTBYTES];
    let mut buf = [0; SYMBYTES];
    let mut kr = [0; SYMBYTES + SYMBYTES];
    let pk = array_ref!(sk, INDCPA_SECRETKEYBYTES, INDCPA_PUBLICKEYBYTES);

    indcpa::dec(&mut buf, array_ref!(c, 0, INDCPA_BYTES), array_ref!(sk, 0, POLYVECBYTES));
    sha3_512!(&mut kr; &buf, &sk[SECRETKEYBYTES - SYMBYTES - SYMBYTES..][..SYMBYTES]);

    indcpa::enc(&mut cmp, &buf, pk, array_ref!(&kr, SYMBYTES, SYMBYTES));

    let flag = c.ct_eq(&cmp);

    sha3_256!(&mut kr[SYMBYTES..][..SYMBYTES]; &c[..CIPHERTEXTBYTES]);

    {
        let kr = array_mut_ref!(kr, 0, SYMBYTES);
        let sk = array_ref!(sk, SECRETKEYBYTES - SYMBYTES, SYMBYTES);

        for i in 0..SYMBYTES {
            kr[i].conditional_assign(&sk[i], !flag);
        }
    }

    sha3_256!(k; &kr);

    flag.unwrap_u8() == 1
}