pqc/crypto_kem/hqc-128/clean/kem.c

145 lines
4.7 KiB
C
Raw Normal View History

2020-09-07 19:23:34 +01:00
#include "api.h"
#include "fips202.h"
#include "hqc.h"
#include "nistseedexpander.h"
#include "parameters.h"
#include "parsing.h"
#include "randombytes.h"
#include "sha2.h"
#include "vector.h"
#include <stdint.h>
#include <string.h>
/**
* @file kem.c
* @brief Implementation of api.h
*/
/**
* @brief Keygen of the HQC_KEM IND_CAA2 scheme
*
* The public key is composed of the syndrome <b>s</b> as well as the seed used to generate the vector <b>h</b>.
*
* The secret key is composed of the seed used to generate vectors <b>x</b> and <b>y</b>.
* As a technicality, the public key is appended to the secret key in order to respect NIST API.
*
* @param[out] pk String containing the public key
* @param[out] sk String containing the secret key
* @returns 0 if keygen is successful
*/
int PQCLEAN_HQC128_CLEAN_crypto_kem_keypair(unsigned char *pk, unsigned char *sk) {
PQCLEAN_HQC128_CLEAN_hqc_pke_keygen(pk, sk);
return 0;
}
/**
* @brief Encapsulation of the HQC_KEM IND_CAA2 scheme
*
* @param[out] ct String containing the ciphertext
* @param[out] ss String containing the shared secret
* @param[in] pk String containing the public key
* @returns 0 if encapsulation is successful
*/
int PQCLEAN_HQC128_CLEAN_crypto_kem_enc(unsigned char *ct, unsigned char *ss, const unsigned char *pk) {
uint8_t theta[SHA512_BYTES] = {0};
2020-09-12 14:59:40 +01:00
uint8_t m_bytes[VEC_K_SIZE_BYTES] = {0};
2020-09-07 19:23:34 +01:00
uint64_t m[VEC_K_SIZE_64] = {0};
uint64_t u[VEC_N_SIZE_64] = {0};
uint64_t v[VEC_N1N2_SIZE_64] = {0};
unsigned char d[SHA512_BYTES] = {0};
unsigned char mc[VEC_K_SIZE_BYTES + VEC_N_SIZE_BYTES + VEC_N1N2_SIZE_BYTES] = {0};
// Computing m
2020-09-12 14:59:40 +01:00
randombytes(m_bytes, VEC_K_SIZE_BYTES);
PQCLEAN_HQC128_CLEAN_load8_arr(m, VEC_K_SIZE_64, m_bytes, VEC_K_SIZE_BYTES);
2020-09-07 19:23:34 +01:00
// Computing theta
2020-09-12 14:59:40 +01:00
sha3_512(theta, m_bytes, VEC_K_SIZE_BYTES);
2020-09-07 19:23:34 +01:00
// Encrypting m
PQCLEAN_HQC128_CLEAN_hqc_pke_encrypt(u, v, m, theta, pk);
// Computing d
2020-09-12 14:59:40 +01:00
sha512(d, m_bytes, VEC_K_SIZE_BYTES);
2020-09-07 19:23:34 +01:00
// Computing shared secret
2020-09-12 14:59:40 +01:00
memcpy(mc, m_bytes, VEC_K_SIZE_BYTES);
2020-09-11 18:36:03 +01:00
PQCLEAN_HQC128_CLEAN_store8_arr(mc + VEC_K_SIZE_BYTES, VEC_N_SIZE_BYTES, u, VEC_N_SIZE_64);
PQCLEAN_HQC128_CLEAN_store8_arr(mc + VEC_K_SIZE_BYTES + VEC_N_SIZE_BYTES, VEC_N1N2_SIZE_BYTES, v, VEC_N1N2_SIZE_64);
2020-09-07 19:23:34 +01:00
sha512(ss, mc, VEC_K_SIZE_BYTES + VEC_N_SIZE_BYTES + VEC_N1N2_SIZE_BYTES);
// Computing ciphertext
PQCLEAN_HQC128_CLEAN_hqc_ciphertext_to_string(ct, u, v, d);
return 0;
}
/**
* @brief Decapsulation of the HQC_KEM IND_CAA2 scheme
*
* @param[out] ss String containing the shared secret
* @param[in] ct String containing the cipĥertext
* @param[in] sk String containing the secret key
* @returns 0 if decapsulation is successful, -1 otherwise
*/
int PQCLEAN_HQC128_CLEAN_crypto_kem_dec(unsigned char *ss, const unsigned char *ct, const unsigned char *sk) {
2020-09-14 16:27:56 +01:00
uint8_t result;
2020-09-07 19:23:34 +01:00
uint64_t u[VEC_N_SIZE_64] = {0};
uint64_t v[VEC_N1N2_SIZE_64] = {0};
unsigned char d[SHA512_BYTES] = {0};
unsigned char pk[PUBLIC_KEY_BYTES] = {0};
2020-09-12 14:59:40 +01:00
uint8_t m_bytes[VEC_K_SIZE_BYTES] = {0};
2020-09-07 19:23:34 +01:00
uint64_t m[VEC_K_SIZE_64] = {0};
uint8_t theta[SHA512_BYTES] = {0};
uint64_t u2[VEC_N_SIZE_64] = {0};
uint64_t v2[VEC_N1N2_SIZE_64] = {0};
unsigned char d2[SHA512_BYTES] = {0};
unsigned char mc[VEC_K_SIZE_BYTES + VEC_N_SIZE_BYTES + VEC_N1N2_SIZE_BYTES] = {0};
// Retrieving u, v and d from ciphertext
PQCLEAN_HQC128_CLEAN_hqc_ciphertext_from_string(u, v, d, ct);
// Retrieving pk from sk
memcpy(pk, sk + SEED_BYTES, PUBLIC_KEY_BYTES);
// Decryting
PQCLEAN_HQC128_CLEAN_hqc_pke_decrypt(m, u, v, sk);
2020-09-12 14:59:40 +01:00
PQCLEAN_HQC128_CLEAN_store8_arr(m_bytes, VEC_K_SIZE_BYTES, m, VEC_K_SIZE_64);
2020-09-07 19:23:34 +01:00
// Computing theta
2020-09-12 14:59:40 +01:00
sha3_512(theta, m_bytes, VEC_K_SIZE_BYTES);
2020-09-07 19:23:34 +01:00
// Encrypting m'
PQCLEAN_HQC128_CLEAN_hqc_pke_encrypt(u2, v2, m, theta, pk);
// Computing d'
2020-09-12 14:59:40 +01:00
sha512(d2, m_bytes, VEC_K_SIZE_BYTES);
2020-09-07 19:23:34 +01:00
// Computing shared secret
2020-09-12 14:59:40 +01:00
memcpy(mc, m_bytes, VEC_K_SIZE_BYTES);
2020-09-11 18:36:03 +01:00
PQCLEAN_HQC128_CLEAN_store8_arr(mc + VEC_K_SIZE_BYTES, VEC_N_SIZE_BYTES, u, VEC_N_SIZE_64);
PQCLEAN_HQC128_CLEAN_store8_arr(mc + VEC_K_SIZE_BYTES + VEC_N_SIZE_BYTES, VEC_N1N2_SIZE_BYTES, v, VEC_N1N2_SIZE_64);
2020-09-07 19:23:34 +01:00
sha512(ss, mc, VEC_K_SIZE_BYTES + VEC_N_SIZE_BYTES + VEC_N1N2_SIZE_BYTES);
// Abort if c != c' or d != d'
2020-09-14 21:44:09 +01:00
result = PQCLEAN_HQC128_CLEAN_vect_compare((uint8_t *)u, (uint8_t *)u2, VEC_N_SIZE_BYTES);
result |= PQCLEAN_HQC128_CLEAN_vect_compare((uint8_t *)v, (uint8_t *)v2, VEC_N1N2_SIZE_BYTES);
result |= PQCLEAN_HQC128_CLEAN_vect_compare(d, d2, SHA512_BYTES);
2020-09-14 16:27:56 +01:00
result = (uint8_t) (-((int16_t) result) >> 15);
2020-09-10 21:36:42 +01:00
for (size_t i = 0; i < SHARED_SECRET_BYTES; i++) {
2020-09-14 16:27:56 +01:00
ss[i] &= ~result;
2020-09-07 19:23:34 +01:00
}
2020-09-14 18:19:20 +01:00
return -(result & 1);
2020-09-07 19:23:34 +01:00
}