KpqC-0.1.0: cbits/third_party/SMAUG-T/src/kem.c
// SPDX-License-Identifier: MIT
#include "api.h"
#include "fips202.h"
#include "hash.h"
#include "indcpa.h"
#include "randombytes.h"
#include "verify.h"
#include <string.h>
/*************************************************
* Name: crypto_kem_keypair_internal
*
* Description: Generates a public key pk and a private key sk deterministically
* from the given randomness (i.e., d and seed)
* for the CCA-secure Module-Lizard key encapsulation mechanism.
*
* Arguments: - uint8_t *pk: pointer to output public key
* - uint8_t *sk: pointer to output private key
* - uint8_t *d: pointer to input d (of length
* SMAUGT_T_BYTES)
* - uint8_t *seed: pointer to input seed (of length
* SMAUGT_CRYPTO_BYTES)
*
* Return: 0 on success, 1 on failure
*
* Specification: Implements @[KS X 123456, Algorithm 33,
* SMAUG-T.KEM.EncapInternal]
**************************************************/
int crypto_kem_keypair_internal(uint8_t *pk, uint8_t *sk,
uint8_t d[SMAUGT_T_BYTES],
uint8_t seed[SMAUGT_CRYPTO_BYTES]) {
int ret = 0;
indcpa_keypair(pk, sk, seed);
memcpy(sk + SMAUGT_PKE_SECRETKEY_BYTES, d, SMAUGT_T_BYTES);
memcpy(sk + SMAUGT_PKE_SECRETKEY_BYTES + SMAUGT_T_BYTES, pk,
SMAUGT_PUBLICKEY_BYTES);
return ret;
}
/*************************************************
* Name: crypto_kem_keypair
*
* Description: Generates a public key pk and a private key sk probabilistically
* by internally sampling the required randomness (i.e., d and
* seed) for the CCA-secure Module-Lizard key encapsulation mechanism.
*
* Arguments: - uint8_t *pk: pointer to output public key
* - uint8_t *sk: pointer to output private key
*
* Return: 0 on success, 1 on failure
*
* Specification: Implements @[KS X 123456, Algorithm 30, SMAUG-T.KEM.KeyGen]
**************************************************/
int crypto_kem_keypair(uint8_t *pk, uint8_t *sk) {
int ret = 0;
uint8_t d[SMAUGT_T_BYTES] = {0};
uint8_t seed[SMAUGT_CRYPTO_BYTES] = {0};
if (randombytes(d, SMAUGT_T_BYTES) != 0) return -1;
if (randombytes(seed, SMAUGT_CRYPTO_BYTES) != 0) return -1;
ret = crypto_kem_keypair_internal(pk, sk, d, seed);
return ret;
}
/*************************************************
* Name: crypto_kem_enc_internal
*
* Description: Generates a shared secret ss and an associated ciphertext ctxt
* deterministically for the given message mu using the provided public key pk.
*
* Arguments: - uint8_t *ctxt: pointer to output ciphertext
* - uint8_t *ss: pointer to output shared secret
* (of length SMAUGT_CRYPTO_BYTES)
* - uint8_t *pk: pointer to input public key
* - uint8_t *mu: pointer to input message (of length
* SMAUGT_DELTA_BYTES)
*
* Return: 0 on success, 1 on failure
*
* Specification: Implements @[KS X 123456, Algorithm 34,
* SMAUG-T.KEM.EncapInternal]
**************************************************/
int crypto_kem_enc_internal(uint8_t *ctxt, uint8_t *ss, const uint8_t *pk,
const uint8_t *mu) {
int ret = 0;
uint8_t seed_r[SMAUGT_DELTA_BYTES + SMAUGT_CRYPTO_BYTES] = {0};
hash_h(seed_r, pk, SMAUGT_PUBLICKEY_BYTES);
hash_g(seed_r, SMAUGT_DELTA_BYTES + SMAUGT_CRYPTO_BYTES, mu,
SMAUGT_MSG_BYTES, seed_r, SHA3_256_HashSize);
memset(ss, 0, SMAUGT_CRYPTO_BYTES);
indcpa_enc(ctxt, pk, mu, seed_r);
cmov(ss, seed_r + SMAUGT_DELTA_BYTES, SMAUGT_CRYPTO_BYTES, 1);
return ret;
}
/*************************************************
* Name: crypto_kem_enc
*
* Description: Generates a shared secret ss and an associated ciphertext ctxt
* probabilistically by internally sampling the required randomness (i.e., mu)
* for the given public key.
*
* Arguments: - uint8_t *ctxt: pointer to output ciphertext
* - uint8_t *ss: pointer to output shared secret
* (of length SMAUGT_CRYPTO_BYTES)
* - uint8_t *pk: pointer to input public key
*
* Return: 0 on success, 1 on failure
*
* Specification: Implements @[KS X 123456, Algorithm 31, SMAUG-T.KEM.Encap]
**************************************************/
int crypto_kem_enc(uint8_t *ctxt, uint8_t *ss, const uint8_t *pk) {
int ret = 0;
uint8_t mu[SMAUGT_MSG_BYTES] = {0}; // shared secret and seed
if (randombytes(mu, SMAUGT_MSG_BYTES) != 0) return -1;
ret = crypto_kem_enc_internal(ctxt, ss, pk, mu);
return ret;
}
/*************************************************
* Name: crypto_kem_dec_internal
*
* Description: Produces a shared secret ss deterministically
* for the given ciphertext ctxt using the provided private key sk.
*
* Arguments: - uint8_t *ss: pointer to output shared secret
* (of length SMAUGT_CRYPTO_BYTES)
* - uint8_t *sk: pointer to input private key
* - uint8_t *ctxt: pointer to input ciphertext
*
* Return: 0 on success, 1 on failure
*
* Specification: Implements @[KS X 123456, Algorithm 35,
* SMAUG-T.KEM.DecapInternal]
**************************************************/
int crypto_kem_dec_internal(uint8_t *ss, const uint8_t *ctxt,
const uint8_t *sk) {
int ret = 0;
uint8_t mu[SMAUGT_MSG_BYTES] = {0};
uint8_t buf[SMAUGT_DELTA_BYTES + SMAUGT_CRYPTO_BYTES] = {
0}; // shared secret and seed
uint8_t buf_tmp[SMAUGT_DELTA_BYTES + SMAUGT_CRYPTO_BYTES] = {0};
uint8_t hash_res[SHA3_256_HashSize] = {0};
const uint8_t *pk = sk + SMAUGT_PKE_SECRETKEY_BYTES + SMAUGT_T_BYTES;
indcpa_dec(mu, sk, ctxt);
hash_h(hash_res, pk, SMAUGT_PUBLICKEY_BYTES);
hash_g(buf, SMAUGT_DELTA_BYTES + SMAUGT_CRYPTO_BYTES, mu, SMAUGT_MSG_BYTES,
hash_res, SHA3_256_HashSize);
uint8_t ctxt_temp[SMAUGT_CIPHERTEXT_BYTES] = {0};
indcpa_enc(ctxt_temp, pk, mu, buf);
int fail = verify(ctxt, ctxt_temp, SMAUGT_CIPHERTEXT_BYTES);
hash_h(hash_res, ctxt, SMAUGT_CIPHERTEXT_BYTES);
hash_g(buf_tmp, SMAUGT_DELTA_BYTES + SMAUGT_CRYPTO_BYTES,
sk + SMAUGT_PKE_SECRETKEY_BYTES, SMAUGT_T_BYTES, hash_res,
SHA3_256_HashSize);
memset(ss, 0, SMAUGT_CRYPTO_BYTES);
cmov(buf + SMAUGT_DELTA_BYTES, buf_tmp + SMAUGT_DELTA_BYTES,
SMAUGT_CRYPTO_BYTES, fail);
cmov(ss, buf + SMAUGT_DELTA_BYTES, SMAUGT_CRYPTO_BYTES, 1);
return ret;
}
/*************************************************
* Name: crypto_kem_dec
*
* Description: Produces a shared secret ss deterministically
* for the given ciphertext ctxt using the provided private key sk.
*
* Arguments: - uint8_t *ss: pointer to output shared secret (of length
* SMAUGT_CRYPTO_BYTES). On failure, ss will contain a
* pseudo-random value.
* - uint8_t *sk: pointer to input private key
* - uint8_t *ctxt: pointer to input ciphertext
*
* Return: 0 on success, 1 on failure
*
* Specification: Implements @[KS X 123456, Algorithm 32, SMAUG-T.KEM.Decap]
**************************************************/
int crypto_kem_dec(uint8_t *ss, const uint8_t *ctxt, const uint8_t *sk) {
int ret = 0;
ret = crypto_kem_dec_internal(ss, ctxt, sk);
return ret;
}