packages feed

KpqC-0.1.0: cbits/third_party/SMAUG-T/src/indcpa.c

// SPDX-License-Identifier: MIT

#include "indcpa.h"
#include "cbd.h"
#include "fips202.h"
#include "pack.h"
#include "randombytes.h"
#include "verify.h"

#include <string.h>

/*************************************************
 * Name:        expand_r
 *
 * Description: Deterministically generate a vector of sparse polynomial r(x)
 *              from a seed.
 *
 * Arguments:   - polyvec *r: pointer to ouptput vector r
 *              - uint8_t *seed: pointer to input seed (of length
 * SMAUGT_DELTA_BYTES)
 *
 * Specification: Implements @[KS X 123456, Algorithm 5, ExpandR]
 **************************************************/
void expand_r(polyvec *r, const uint8_t *seed) {
    unsigned int i;
    uint8_t buf[SMAUGT_CBDSEED_BYTES] = {0};

    for (i = 0; i < SMAUGT_K; ++i) {
        uint8_t extseed[SMAUGT_DELTA_BYTES + 1];
        memcpy(extseed, seed, SMAUGT_DELTA_BYTES);
        extseed[SMAUGT_DELTA_BYTES] = i;

        shake256(buf, SMAUGT_CBDSEED_BYTES, extseed, SMAUGT_DELTA_BYTES + 1);
        sp_cbd(&r->vec[i], buf);
    }
}

/*************************************************
 * Name:        indcpa_keypair
 *
 * Description: Generates a public key and a private key deterministically
 *              from the given randomness seed.
 *              Key generation function of the CPA-secure Module-Lizard
 *              public-key encryption scheme.
 *
 * Arguments:   - uint8_t pk[SMAUGT_PUBLICKEY_BYTES]: pointer to output public
 *              key
 *              - uint8_t sk[SMAUGT_PKE_SECRETKEY_BYTES]: pointer to output
 *              private key
 *              - uint8_t seed[SMAUGT_CRYPTO_BYTES]: pointer to input seed
 *
 * Specification: Implements @[KS X 123456, Algorithm 25, SMAUGT-T.PKE.KeyGen]
 **************************************************/
void indcpa_keypair(uint8_t pk[SMAUGT_PUBLICKEY_BYTES],
                    uint8_t sk[SMAUGT_PKE_SECRETKEY_BYTES],
                    const uint8_t seed[SMAUGT_CRYPTO_BYTES]) {
    public_key pk_tmp;
    secret_key sk_tmp;
    memset(&pk_tmp, 0, sizeof(public_key));
    memset(&sk_tmp, 0, sizeof(secret_key));

    uint8_t extseed[SMAUGT_CRYPTO_BYTES + SMAUGT_PKSEED_BYTES] = {0};
#if SMAUGT_CRYPTO_BYTES + SMAUGT_PKSEED_BYTES != 64
#error                                                                         \
    "This implementation assumes SMAUGT_CRYPTO_BYTES + SMAUGT_PKSEED_BYTES to be 64"
#endif
    sha3_512(extseed, seed, SMAUGT_CRYPTO_BYTES);

    expand_s(&sk_tmp, extseed);

    memcpy(&pk_tmp.seed, extseed + SMAUGT_CRYPTO_BYTES, SMAUGT_PKSEED_BYTES);
    gen_pub_key(&pk_tmp, &sk_tmp, extseed);

    memset(pk, 0, SMAUGT_PUBLICKEY_BYTES);
    memset(sk, 0, SMAUGT_PKE_SECRETKEY_BYTES);
    pack_enck(pk, &pk_tmp);
    pack_deck(sk, &sk_tmp);
}

/*************************************************
 * Name:        indcpa_enc
 *
 * Description: Generates the ciphertext ctxt deterministically
 *              by encrypting the given message mu
 *              with the provided public key pk and the given randomness seed.
 *              Encryption function of the CPA-secure Module-Lizard public-key
 *              encryption scheme.
 *
 * Arguments:   - uint8_t ctxt[SMAUGT_CIPHERTEXT_BYTES]: pointer to output
 *              ciphertext
 *              - const uint8_t pk[SMAUGT_PUBLICKEY_BYTES]: pointer to input
 *              public key
 *              - const uint8_t mu[SMAUGT_MSG_BYTES]: pointer to input plaintext
 *              message
 *              - const uint8_t seed[SMAUGT_DELTA_BYTES]: pointer to input seed
 *
 * Specification: Implements @[KS X 123456, Algorithm 26, SMAUGT-T.PKE.Enc]
 **************************************************/
void indcpa_enc(uint8_t ctxt[SMAUGT_CIPHERTEXT_BYTES],
                const uint8_t pk[SMAUGT_PUBLICKEY_BYTES],
                const uint8_t mu[SMAUGT_MSG_BYTES],
                const uint8_t seed[SMAUGT_DELTA_BYTES]) {

    uint8_t seed_r[SMAUGT_DELTA_BYTES] = {0};
    public_key pk_tmp;
    unpack_enck(&pk_tmp, pk);

    // Compute a vector r = hwt(delta, H'(pk))
    polyvec r;
    memset(&r, 0, sizeof(polyvec));

    if (seed == NULL)
        randombytes(seed_r, SMAUGT_DELTA_BYTES);
    else
        cmov(seed_r, seed, SMAUGT_DELTA_BYTES, 1);
    expand_r(&r, seed_r);

    // Compute c1(x), c2(x)
    ciphertext ctxt_tmp;
    memset(&ctxt_tmp, 0, sizeof(ciphertext));
    computeC1(&(ctxt_tmp.c1), pk_tmp.A, &r);
    computeC2(&(ctxt_tmp.c2), mu, &pk_tmp.b, &r);

    pack_ct(ctxt, &ctxt_tmp);
}

/*************************************************
 * Name:        indcpa_dec
 *
 * Description: Generates the plaintext message mu deterministically
 *              by decrypting the given ciphertext ctxt with the provided
 *              private key sk. Decryption function of the CPA-secure
 * Module-Lizard public-key encryption scheme.
 *
 * Arguments:   - uint8_t mu[SMAUGT_MSG_BYTES]: pointer to output plaintext
 *              message
 *              - const uint8_t sk[SMAUGT_PKE_SECRETKEY_BYTES]: pointer to input
 *              private key
 *              - const uint8_t ctxt[SMAUGT_CIPHERTEXT_BYTES]: pointer to input
 *              ciphertext
 *
 * Specification: Implements @[KS X 123456, Algorithm 28, SMAUGT-T.PKE.Dec]
 **************************************************/
void indcpa_dec(uint8_t mu[SMAUGT_MSG_BYTES],
                const uint8_t sk[SMAUGT_PKE_SECRETKEY_BYTES],
                const uint8_t ctxt[SMAUGT_CIPHERTEXT_BYTES]) {
    poly delta;
    polyvec c1;

    secret_key sk_tmp;
    memset(&sk_tmp, 0, sizeof(secret_key));
    unpack_deck(&sk_tmp, sk);

    ciphertext ctxt_tmp;
    unpack_ct(&ctxt_tmp, ctxt);

    unsigned int i, j;
    c1 = ctxt_tmp.c1;
    delta = ctxt_tmp.c2;
    for (i = 0; i < SMAUGT_N; ++i)
        delta.coeffs[i] =
            (int16_t)((uint16_t)delta.coeffs[i]
                      << SMAUGT_MODULUS_16_LOG_P_PRIME);
    for (i = 0; i < SMAUGT_K; ++i)
        for (j = 0; j < SMAUGT_N; ++j)
            c1.vec[i].coeffs[j] =
                (int16_t)((uint16_t)c1.vec[i].coeffs[j]
                          << SMAUGT_MODULUS_16_LOG_P);

    // Compute delta = (delta + c1^T * s)
    vec_vec_mult_add(&delta, &c1, &sk_tmp, SMAUGT_MODULUS_16_LOG_P);

#if SMAUGT_MODE == SMAUGT_MODET
    d2_dcd(mu, &delta); // EDIT TiMER
#else
    // Compute delta = 2/p * delta
    for (i = 0; i < SMAUGT_N; ++i) {
        delta.coeffs[i] += SMAUGT_DEC_ADD;
        delta.coeffs[i] >>= SMAUGT_MODULUS_16_LOG_T;
        delta.coeffs[i] &= 0x01;
    }

    // Set delta
    memset(mu, 0, SMAUGT_MSG_BYTES);
    for (i = 0; i < SMAUGT_MSG_BYTES; ++i) {
        for (j = 0; j < 8; ++j) {
            mu[i] ^= ((uint8_t)(delta.coeffs[8 * i + j]) << j);
        }
    }
#endif
}