Revision 1990ae634d0602ff022afc946ef66933e4e4a2dc authored by Santiago Zanella-Beguelin on 09 December 2019, 17:48:55 UTC, committed by Santiago Zanella-Beguelin on 09 December 2019, 17:50:10 UTC
1 parent ae8e182
Raw File
Hacl_Frodo_KEM.c
/* MIT License
 *
 * Copyright (c) 2016-2020 INRIA, CMU and Microsoft Corporation
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */


#include "Hacl_Frodo_KEM.h"

inline static void
Hacl_Impl_Matrix_matrix_add(uint32_t n1, uint32_t n2, uint16_t *a, uint16_t *b)
{
  for (uint32_t i0 = (uint32_t)0U; i0 < n1; i0 = i0 + (uint32_t)1U)
  {
    for (uint32_t i = (uint32_t)0U; i < n2; i = i + (uint32_t)1U)
    {
      a[i0 * n2 + i] = a[i0 * n2 + i] + b[i0 * n2 + i];
    }
  }
}

inline static void
Hacl_Impl_Matrix_matrix_sub(uint32_t n1, uint32_t n2, uint16_t *a, uint16_t *b)
{
  for (uint32_t i0 = (uint32_t)0U; i0 < n1; i0 = i0 + (uint32_t)1U)
  {
    for (uint32_t i = (uint32_t)0U; i < n2; i = i + (uint32_t)1U)
    {
      b[i0 * n2 + i] = a[i0 * n2 + i] - b[i0 * n2 + i];
    }
  }
}

inline static void
Hacl_Impl_Matrix_matrix_mul(
  uint32_t n1,
  uint32_t n2,
  uint32_t n3,
  uint16_t *a,
  uint16_t *b,
  uint16_t *c
)
{
  for (uint32_t i0 = (uint32_t)0U; i0 < n1; i0 = i0 + (uint32_t)1U)
  {
    for (uint32_t i1 = (uint32_t)0U; i1 < n3; i1 = i1 + (uint32_t)1U)
    {
      uint16_t res = (uint16_t)0U;
      for (uint32_t i = (uint32_t)0U; i < n2; i = i + (uint32_t)1U)
      {
        uint16_t aij = a[i0 * n2 + i];
        uint16_t bjk = b[i * n3 + i1];
        uint16_t res0 = res;
        res = res0 + aij * bjk;
      }
      c[i0 * n3 + i1] = res;
    }
  }
}

inline static void
Hacl_Impl_Matrix_matrix_mul_s(
  uint32_t n1,
  uint32_t n2,
  uint32_t n3,
  uint16_t *a,
  uint16_t *b,
  uint16_t *c
)
{
  for (uint32_t i0 = (uint32_t)0U; i0 < n1; i0 = i0 + (uint32_t)1U)
  {
    for (uint32_t i1 = (uint32_t)0U; i1 < n3; i1 = i1 + (uint32_t)1U)
    {
      uint16_t res = (uint16_t)0U;
      for (uint32_t i = (uint32_t)0U; i < n2; i = i + (uint32_t)1U)
      {
        uint16_t aij = a[i0 * n2 + i];
        uint16_t bjk = b[i1 * n2 + i];
        uint16_t res0 = res;
        res = res0 + aij * bjk;
      }
      c[i0 * n3 + i1] = res;
    }
  }
}

inline static bool
Hacl_Impl_Matrix_matrix_eq(uint32_t n1, uint32_t n2, uint32_t m, uint16_t *a, uint16_t *b)
{
  bool res = true;
  uint32_t n3 = n1 * n2;
  for (uint32_t i = (uint32_t)0U; i < n3; i = i + (uint32_t)1U)
  {
    uint16_t ai = a[i];
    uint16_t bi = b[i];
    bool a1 = res;
    res =
      a1
      &&
        ((uint32_t)ai & (((uint32_t)1U << m) - (uint32_t)1U))
        == ((uint32_t)bi & (((uint32_t)1U << m) - (uint32_t)1U));
  }
  return res;
}

inline static void
Hacl_Impl_Matrix_matrix_to_lbytes(uint32_t n1, uint32_t n2, uint16_t *m, uint8_t *res)
{
  uint32_t n3 = n1 * n2;
  for (uint32_t i = (uint32_t)0U; i < n3; i = i + (uint32_t)1U)
  {
    uint8_t *tmp = res + (uint32_t)2U * i;
    store16_le(tmp, m[i]);
  }
}

inline static void
Hacl_Impl_Matrix_matrix_from_lbytes(uint32_t n1, uint32_t n2, uint8_t *b, uint16_t *res)
{
  uint32_t n3 = n1 * n2;
  for (uint32_t i = (uint32_t)0U; i < n3; i = i + (uint32_t)1U)
  {
    uint16_t u = load16_le(b + (uint32_t)2U * i);
    res[i] = u;
  }
}

inline static void
Hacl_Impl_Frodo_Gen_frodo_gen_matrix_cshake(
  uint32_t n1,
  uint32_t seed_len,
  uint8_t *seed,
  uint16_t *res
)
{
  KRML_CHECK_SIZE(sizeof (uint8_t), (uint32_t)2U * n1);
  uint8_t r[(uint32_t)2U * n1];
  memset(r, 0U, (uint32_t)2U * n1 * sizeof r[0U]);
  memset(res, 0U, n1 * n1 * sizeof res[0U]);
  for (uint32_t i = (uint32_t)0U; i < n1; i = i + (uint32_t)1U)
  {
    uint32_t ctr = (uint32_t)256U + i;
    uint64_t s[25U] = { 0U };
    s[0U] = (uint64_t)0x10010001a801U | (uint64_t)(uint16_t)ctr << (uint32_t)48U;
    Hacl_Impl_SHA3_state_permute(s);
    Hacl_Impl_SHA3_absorb(s, (uint32_t)168U, seed_len, seed, (uint8_t)0x04U);
    Hacl_Impl_SHA3_squeeze(s, (uint32_t)168U, (uint32_t)2U * n1, r);
    for (uint32_t i0 = (uint32_t)0U; i0 < n1; i0 = i0 + (uint32_t)1U)
    {
      uint8_t *resij = r + (uint32_t)2U * i0;
      uint16_t u = load16_le(resij);
      res[i * n1 + i0] = u;
    }
  }
}

static uint16_t
Hacl_Impl_Frodo_Sample_cdf_table[12U] =
  {
    (uint16_t)4727U, (uint16_t)13584U, (uint16_t)20864U, (uint16_t)26113U, (uint16_t)29434U,
    (uint16_t)31278U, (uint16_t)32176U, (uint16_t)32560U, (uint16_t)32704U, (uint16_t)32751U,
    (uint16_t)32764U, (uint16_t)32767U
  };

inline static uint16_t Hacl_Impl_Frodo_Sample_frodo_sample(uint16_t r)
{
  uint16_t prnd = r >> (uint32_t)1U;
  uint16_t sign = r & (uint16_t)1U;
  uint16_t sample = (uint16_t)0U;
  uint32_t bound = (uint32_t)11U;
  for (uint32_t i = (uint32_t)0U; i < bound; i = i + (uint32_t)1U)
  {
    uint16_t sample0 = sample;
    uint16_t ti = Hacl_Impl_Frodo_Sample_cdf_table[i];
    uint16_t samplei = (uint16_t)(uint32_t)(ti - prnd) >> (uint32_t)15U;
    sample = samplei + sample0;
  }
  uint16_t sample0 = sample;
  return ((~sign + (uint16_t)1U) ^ sample0) + sign;
}

inline static void
Hacl_Impl_Frodo_Sample_frodo_sample_matrix(
  uint32_t n1,
  uint32_t n2,
  uint32_t seed_len,
  uint8_t *seed,
  uint16_t ctr,
  uint16_t *res
)
{
  KRML_CHECK_SIZE(sizeof (uint8_t), (uint32_t)2U * n1 * n2);
  uint8_t r[(uint32_t)2U * n1 * n2];
  memset(r, 0U, (uint32_t)2U * n1 * n2 * sizeof r[0U]);
  uint64_t s[25U] = { 0U };
  s[0U] = (uint64_t)0x10010001a801U | (uint64_t)ctr << (uint32_t)48U;
  Hacl_Impl_SHA3_state_permute(s);
  Hacl_Impl_SHA3_absorb(s, (uint32_t)168U, seed_len, seed, (uint8_t)0x04U);
  Hacl_Impl_SHA3_squeeze(s, (uint32_t)168U, (uint32_t)2U * n1 * n2, r);
  memset(res, 0U, n1 * n2 * sizeof res[0U]);
  for (uint32_t i0 = (uint32_t)0U; i0 < n1; i0 = i0 + (uint32_t)1U)
  {
    for (uint32_t i = (uint32_t)0U; i < n2; i = i + (uint32_t)1U)
    {
      uint8_t *resij = r + (uint32_t)2U * (n2 * i0 + i);
      uint16_t u = load16_le(resij);
      res[i0 * n2 + i] = Hacl_Impl_Frodo_Sample_frodo_sample(u);
    }
  }
}

inline static void
Hacl_Impl_Frodo_Pack_frodo_pack(
  uint32_t n1,
  uint32_t n2,
  uint32_t d,
  uint16_t *a,
  uint8_t *res
)
{
  uint32_t n3 = n1 * n2 / (uint32_t)8U;
  for (uint32_t i = (uint32_t)0U; i < n3; i = i + (uint32_t)1U)
  {
    uint16_t *a1 = a + (uint32_t)8U * i;
    uint8_t *r = res + d * i;
    uint16_t maskd = (uint16_t)((uint32_t)1U << d) - (uint16_t)1U;
    uint8_t v16[16U] = { 0U };
    uint16_t a0 = a1[0U] & maskd;
    uint16_t a11 = a1[1U] & maskd;
    uint16_t a2 = a1[2U] & maskd;
    uint16_t a3 = a1[3U] & maskd;
    uint16_t a4 = a1[4U] & maskd;
    uint16_t a5 = a1[5U] & maskd;
    uint16_t a6 = a1[6U] & maskd;
    uint16_t a7 = a1[7U] & maskd;
    uint128_t
    templong =
      (((((((uint128_t)(uint64_t)a0
      << (uint32_t)7U * d
      | (uint128_t)(uint64_t)a11 << (uint32_t)6U * d)
      | (uint128_t)(uint64_t)a2 << (uint32_t)5U * d)
      | (uint128_t)(uint64_t)a3 << (uint32_t)4U * d)
      | (uint128_t)(uint64_t)a4 << (uint32_t)3U * d)
      | (uint128_t)(uint64_t)a5 << (uint32_t)2U * d)
      | (uint128_t)(uint64_t)a6 << (uint32_t)1U * d)
      | (uint128_t)(uint64_t)a7 << (uint32_t)0U * d;
    store128_be(v16, templong);
    uint8_t *src = v16 + (uint32_t)16U - d;
    memcpy(r, src, d * sizeof src[0U]);
  }
}

inline static void
Hacl_Impl_Frodo_Pack_frodo_unpack(
  uint32_t n1,
  uint32_t n2,
  uint32_t d,
  uint8_t *b,
  uint16_t *res
)
{
  uint32_t n3 = n1 * n2 / (uint32_t)8U;
  for (uint32_t i = (uint32_t)0U; i < n3; i = i + (uint32_t)1U)
  {
    uint8_t *b1 = b + d * i;
    uint16_t *r = res + (uint32_t)8U * i;
    uint16_t maskd = (uint16_t)((uint32_t)1U << d) - (uint16_t)1U;
    uint8_t src[16U] = { 0U };
    memcpy(src + (uint32_t)16U - d, b1, d * sizeof b1[0U]);
    uint128_t u = load128_be(src);
    uint128_t templong = u;
    r[0U] = (uint16_t)(uint64_t)(templong >> (uint32_t)7U * d) & maskd;
    r[1U] = (uint16_t)(uint64_t)(templong >> (uint32_t)6U * d) & maskd;
    r[2U] = (uint16_t)(uint64_t)(templong >> (uint32_t)5U * d) & maskd;
    r[3U] = (uint16_t)(uint64_t)(templong >> (uint32_t)4U * d) & maskd;
    r[4U] = (uint16_t)(uint64_t)(templong >> (uint32_t)3U * d) & maskd;
    r[5U] = (uint16_t)(uint64_t)(templong >> (uint32_t)2U * d) & maskd;
    r[6U] = (uint16_t)(uint64_t)(templong >> (uint32_t)1U * d) & maskd;
    r[7U] = (uint16_t)(uint64_t)(templong >> (uint32_t)0U * d) & maskd;
  }
}

static void randombytes_(uint32_t len, uint8_t *res)
{
  bool b = Lib_RandomBuffer_System_randombytes(res, len);
}

static uint32_t Hacl_Impl_Frodo_KEM_bytes_mu = (uint32_t)16U;

static uint32_t Hacl_Impl_Frodo_KEM_crypto_publickeybytes = (uint32_t)976U;

static uint32_t Hacl_Impl_Frodo_KEM_crypto_ciphertextbytes = (uint32_t)1096U;

inline static void
Hacl_Impl_Frodo_KEM_KeyGen_frodo_mul_add_as_plus_e_pack(
  uint8_t *seed_a,
  uint8_t *seed_e,
  uint8_t *b,
  uint8_t *s
)
{
  uint16_t s_matrix[512U] = { 0U };
  Hacl_Impl_Frodo_Sample_frodo_sample_matrix((uint32_t)64U,
    (uint32_t)8U,
    (uint32_t)16U,
    seed_e,
    (uint16_t)1U,
    s_matrix);
  Hacl_Impl_Matrix_matrix_to_lbytes((uint32_t)64U, (uint32_t)8U, s_matrix, s);
  uint16_t b_matrix[512U] = { 0U };
  uint16_t a_matrix[4096U] = { 0U };
  uint16_t e_matrix[512U] = { 0U };
  Hacl_Impl_Frodo_Gen_frodo_gen_matrix_cshake((uint32_t)64U, (uint32_t)16U, seed_a, a_matrix);
  Hacl_Impl_Frodo_Sample_frodo_sample_matrix((uint32_t)64U,
    (uint32_t)8U,
    (uint32_t)16U,
    seed_e,
    (uint16_t)2U,
    e_matrix);
  Hacl_Impl_Matrix_matrix_mul_s((uint32_t)64U,
    (uint32_t)64U,
    (uint32_t)8U,
    a_matrix,
    s_matrix,
    b_matrix);
  Hacl_Impl_Matrix_matrix_add((uint32_t)64U, (uint32_t)8U, b_matrix, e_matrix);
  Lib_Memzero_clear_words_u16((uint32_t)512U, e_matrix);
  Hacl_Impl_Frodo_Pack_frodo_pack((uint32_t)64U, (uint32_t)8U, (uint32_t)15U, b_matrix, b);
  Lib_Memzero_clear_words_u16((uint32_t)512U, s_matrix);
}

inline static void
Hacl_Impl_Frodo_Encode_frodo_key_encode(uint32_t b, uint8_t *a, uint16_t *res)
{
  for (uint32_t i0 = (uint32_t)0U; i0 < (uint32_t)8U; i0 = i0 + (uint32_t)1U)
  {
    uint8_t v8[8U] = { 0U };
    uint8_t *chunk = a + i0 * b;
    memcpy(v8, chunk, b * sizeof chunk[0U]);
    uint64_t u = load64_le(v8);
    uint64_t x = u;
    uint64_t x0 = x;
    for (uint32_t i = (uint32_t)0U; i < (uint32_t)8U; i = i + (uint32_t)1U)
    {
      uint64_t rk = x0 >> b * i & (((uint64_t)1U << b) - (uint64_t)1U);
      res[i0 * (uint32_t)8U + i] = (uint16_t)rk << ((uint32_t)15U - b);
    }
  }
}

inline static void
Hacl_Impl_Frodo_Encode_frodo_key_decode(uint32_t b, uint16_t *a, uint8_t *res)
{
  for (uint32_t i0 = (uint32_t)0U; i0 < (uint32_t)8U; i0 = i0 + (uint32_t)1U)
  {
    uint64_t templong = (uint64_t)0U;
    for (uint32_t i = (uint32_t)0U; i < (uint32_t)8U; i = i + (uint32_t)1U)
    {
      uint16_t aik = a[i0 * (uint32_t)8U + i];
      uint16_t
      res1 = (aik + ((uint16_t)1U << ((uint32_t)15U - b - (uint32_t)1U))) >> ((uint32_t)15U - b);
      templong = templong | (uint64_t)(res1 & (((uint16_t)1U << b) - (uint16_t)1U)) << b * i;
    }
    uint64_t templong0 = templong;
    uint8_t v8[8U] = { 0U };
    store64_le(v8, templong0);
    uint8_t *tmp = v8;
    memcpy(res + i0 * b, tmp, b * sizeof tmp[0U]);
  }
}

inline static void
Hacl_Impl_Frodo_KEM_Encaps_frodo_mul_add_sb_plus_e_plus_mu(
  uint8_t *b,
  uint8_t *seed_e,
  uint8_t *coins,
  uint16_t *sp_matrix,
  uint16_t *v_matrix
)
{
  uint16_t b_matrix[512U] = { 0U };
  uint16_t epp_matrix[64U] = { 0U };
  Hacl_Impl_Frodo_Pack_frodo_unpack((uint32_t)64U, (uint32_t)8U, (uint32_t)15U, b, b_matrix);
  Hacl_Impl_Frodo_Sample_frodo_sample_matrix((uint32_t)8U,
    (uint32_t)8U,
    (uint32_t)16U,
    seed_e,
    (uint16_t)6U,
    epp_matrix);
  Hacl_Impl_Matrix_matrix_mul((uint32_t)8U,
    (uint32_t)64U,
    (uint32_t)8U,
    sp_matrix,
    b_matrix,
    v_matrix);
  Hacl_Impl_Matrix_matrix_add((uint32_t)8U, (uint32_t)8U, v_matrix, epp_matrix);
  Lib_Memzero_clear_words_u16((uint32_t)64U, epp_matrix);
  uint16_t mu_encode[64U] = { 0U };
  Hacl_Impl_Frodo_Encode_frodo_key_encode((uint32_t)2U, coins, mu_encode);
  Hacl_Impl_Matrix_matrix_add((uint32_t)8U, (uint32_t)8U, v_matrix, mu_encode);
}

inline static void
Hacl_Impl_Frodo_KEM_Encaps_crypto_kem_enc_ct(
  uint8_t *pk,
  uint8_t *g,
  uint8_t *coins,
  uint8_t *ct
)
{
  uint8_t *seed_a = pk;
  uint8_t *b = pk + (uint32_t)16U;
  uint8_t *seed_e = g;
  uint8_t *d = g + (uint32_t)32U;
  uint16_t sp_matrix[512U] = { 0U };
  Hacl_Impl_Frodo_Sample_frodo_sample_matrix((uint32_t)8U,
    (uint32_t)64U,
    (uint32_t)16U,
    seed_e,
    (uint16_t)4U,
    sp_matrix);
  uint32_t c1Len = (uint32_t)960U;
  uint32_t c2Len = (uint32_t)120U;
  uint32_t c12Len = c1Len + c2Len;
  uint8_t *c1 = ct;
  uint16_t bp_matrix[512U] = { 0U };
  uint16_t a_matrix[4096U] = { 0U };
  uint16_t ep_matrix[512U] = { 0U };
  Hacl_Impl_Frodo_Gen_frodo_gen_matrix_cshake((uint32_t)64U, (uint32_t)16U, seed_a, a_matrix);
  Hacl_Impl_Frodo_Sample_frodo_sample_matrix((uint32_t)8U,
    (uint32_t)64U,
    (uint32_t)16U,
    seed_e,
    (uint16_t)5U,
    ep_matrix);
  Hacl_Impl_Matrix_matrix_mul((uint32_t)8U,
    (uint32_t)64U,
    (uint32_t)64U,
    sp_matrix,
    a_matrix,
    bp_matrix);
  Hacl_Impl_Matrix_matrix_add((uint32_t)8U, (uint32_t)64U, bp_matrix, ep_matrix);
  Lib_Memzero_clear_words_u16((uint32_t)512U, ep_matrix);
  Hacl_Impl_Frodo_Pack_frodo_pack((uint32_t)8U, (uint32_t)64U, (uint32_t)15U, bp_matrix, c1);
  uint8_t *c2 = ct + c1Len;
  uint16_t v_matrix[64U] = { 0U };
  Hacl_Impl_Frodo_KEM_Encaps_frodo_mul_add_sb_plus_e_plus_mu(b,
    seed_e,
    coins,
    sp_matrix,
    v_matrix);
  Hacl_Impl_Frodo_Pack_frodo_pack((uint32_t)8U, (uint32_t)8U, (uint32_t)15U, v_matrix, c2);
  Lib_Memzero_clear_words_u16((uint32_t)64U, v_matrix);
  memcpy(ct + c12Len, d, (uint32_t)16U * sizeof d[0U]);
  Lib_Memzero_clear_words_u16((uint32_t)512U, sp_matrix);
}

inline static void
Hacl_Impl_Frodo_KEM_Encaps_crypto_kem_enc_ss(uint8_t *g, uint8_t *ct, uint8_t *ss)
{
  uint32_t ss_init_len = Hacl_Impl_Frodo_KEM_crypto_ciphertextbytes + (uint32_t)16U;
  KRML_CHECK_SIZE(sizeof (uint8_t), ss_init_len);
  uint8_t ss_init[ss_init_len];
  memset(ss_init, 0U, ss_init_len * sizeof ss_init[0U]);
  uint8_t *c12 = ct;
  uint8_t *kd = g + (uint32_t)16U;
  memcpy(ss_init,
    c12,
    (Hacl_Impl_Frodo_KEM_crypto_ciphertextbytes - (uint32_t)16U) * sizeof c12[0U]);
  memcpy(ss_init + Hacl_Impl_Frodo_KEM_crypto_ciphertextbytes - (uint32_t)16U,
    kd,
    (uint32_t)32U * sizeof kd[0U]);
  uint64_t s[25U] = { 0U };
  s[0U] = (uint64_t)0x10010001a801U | (uint64_t)(uint16_t)7U << (uint32_t)48U;
  Hacl_Impl_SHA3_state_permute(s);
  Hacl_Impl_SHA3_absorb(s, (uint32_t)168U, ss_init_len, ss_init, (uint8_t)0x04U);
  Hacl_Impl_SHA3_squeeze(s, (uint32_t)168U, (uint32_t)16U, ss);
}

uint32_t Hacl_Frodo_KEM_crypto_kem_keypair(uint8_t *pk, uint8_t *sk)
{
  uint8_t coins[48U] = { 0U };
  randombytes_((uint32_t)48U, coins);
  uint8_t *s = coins;
  uint8_t *seed_e = coins + (uint32_t)16U;
  uint8_t *z = coins + (uint32_t)32U;
  uint8_t *seed_a = pk;
  uint64_t s1[25U] = { 0U };
  s1[0U] = (uint64_t)0x10010001a801U | (uint64_t)(uint16_t)0U << (uint32_t)48U;
  Hacl_Impl_SHA3_state_permute(s1);
  Hacl_Impl_SHA3_absorb(s1, (uint32_t)168U, (uint32_t)16U, z, (uint8_t)0x04U);
  Hacl_Impl_SHA3_squeeze(s1, (uint32_t)168U, (uint32_t)16U, seed_a);
  uint8_t *b = pk + (uint32_t)16U;
  uint8_t *s_bytes = sk + (uint32_t)16U + Hacl_Impl_Frodo_KEM_crypto_publickeybytes;
  Hacl_Impl_Frodo_KEM_KeyGen_frodo_mul_add_as_plus_e_pack(seed_a, seed_e, b, s_bytes);
  memcpy(sk, s, (uint32_t)16U * sizeof s[0U]);
  memcpy(sk + (uint32_t)16U, pk, Hacl_Impl_Frodo_KEM_crypto_publickeybytes * sizeof pk[0U]);
  return (uint32_t)0U;
}

uint32_t Hacl_Frodo_KEM_crypto_kem_enc(uint8_t *ct, uint8_t *ss, uint8_t *pk)
{
  uint8_t coins[16U] = { 0U };
  randombytes_(Hacl_Impl_Frodo_KEM_bytes_mu, coins);
  uint8_t g[48U] = { 0U };
  uint8_t pk_coins[992U] = { 0U };
  memcpy(pk_coins, pk, Hacl_Impl_Frodo_KEM_crypto_publickeybytes * sizeof pk[0U]);
  memcpy(pk_coins + Hacl_Impl_Frodo_KEM_crypto_publickeybytes,
    coins,
    Hacl_Impl_Frodo_KEM_bytes_mu * sizeof coins[0U]);
  uint64_t s[25U] = { 0U };
  s[0U] = (uint64_t)0x10010001a801U | (uint64_t)(uint16_t)3U << (uint32_t)48U;
  Hacl_Impl_SHA3_state_permute(s);
  Hacl_Impl_SHA3_absorb(s,
    (uint32_t)168U,
    Hacl_Impl_Frodo_KEM_crypto_publickeybytes + Hacl_Impl_Frodo_KEM_bytes_mu,
    pk_coins,
    (uint8_t)0x04U);
  Hacl_Impl_SHA3_squeeze(s, (uint32_t)168U, (uint32_t)48U, g);
  Hacl_Impl_Frodo_KEM_Encaps_crypto_kem_enc_ct(pk, g, coins, ct);
  Hacl_Impl_Frodo_KEM_Encaps_crypto_kem_enc_ss(g, ct, ss);
  Lib_Memzero_clear_words_u8((uint32_t)32U, g);
  return (uint32_t)0U;
}

uint32_t Hacl_Frodo_KEM_crypto_kem_dec(uint8_t *ss, uint8_t *ct, uint8_t *sk)
{
  uint16_t bp_matrix[512U] = { 0U };
  uint16_t c_matrix[64U] = { 0U };
  uint8_t mu_decode[16U] = { 0U };
  uint32_t c1Len = (uint32_t)960U;
  uint8_t *c1 = ct;
  uint8_t *c2 = ct + c1Len;
  Hacl_Impl_Frodo_Pack_frodo_unpack((uint32_t)8U, (uint32_t)64U, (uint32_t)15U, c1, bp_matrix);
  Hacl_Impl_Frodo_Pack_frodo_unpack((uint32_t)8U, (uint32_t)8U, (uint32_t)15U, c2, c_matrix);
  uint8_t *s_bytes = sk + (uint32_t)16U + Hacl_Impl_Frodo_KEM_crypto_publickeybytes;
  uint8_t mu_decode1[16U] = { 0U };
  uint16_t s_matrix[512U] = { 0U };
  uint16_t m_matrix[64U] = { 0U };
  Hacl_Impl_Matrix_matrix_from_lbytes((uint32_t)64U, (uint32_t)8U, s_bytes, s_matrix);
  Hacl_Impl_Matrix_matrix_mul_s((uint32_t)8U,
    (uint32_t)64U,
    (uint32_t)8U,
    bp_matrix,
    s_matrix,
    m_matrix);
  Hacl_Impl_Matrix_matrix_sub((uint32_t)8U, (uint32_t)8U, c_matrix, m_matrix);
  Hacl_Impl_Frodo_Encode_frodo_key_decode((uint32_t)2U, m_matrix, mu_decode1);
  uint8_t g[48U] = { 0U };
  uint32_t
  pk_mu_decode_len = Hacl_Impl_Frodo_KEM_crypto_publickeybytes + Hacl_Impl_Frodo_KEM_bytes_mu;
  KRML_CHECK_SIZE(sizeof (uint8_t), pk_mu_decode_len);
  uint8_t pk_mu_decode[pk_mu_decode_len];
  memset(pk_mu_decode, 0U, pk_mu_decode_len * sizeof pk_mu_decode[0U]);
  uint8_t *pk0 = sk + (uint32_t)16U;
  memcpy(pk_mu_decode, pk0, Hacl_Impl_Frodo_KEM_crypto_publickeybytes * sizeof pk0[0U]);
  memcpy(pk_mu_decode + Hacl_Impl_Frodo_KEM_crypto_publickeybytes,
    mu_decode1,
    Hacl_Impl_Frodo_KEM_bytes_mu * sizeof mu_decode1[0U]);
  uint64_t s0[25U] = { 0U };
  s0[0U] = (uint64_t)0x10010001a801U | (uint64_t)(uint16_t)3U << (uint32_t)48U;
  Hacl_Impl_SHA3_state_permute(s0);
  Hacl_Impl_SHA3_absorb(s0, (uint32_t)168U, pk_mu_decode_len, pk_mu_decode, (uint8_t)0x04U);
  Hacl_Impl_SHA3_squeeze(s0, (uint32_t)168U, (uint32_t)48U, g);
  uint8_t *dp = g + (uint32_t)32U;
  uint8_t *d0 = ct + Hacl_Impl_Frodo_KEM_crypto_ciphertextbytes - (uint32_t)16U;
  uint16_t bpp_matrix[512U] = { 0U };
  uint16_t cp_matrix[64U] = { 0U };
  uint8_t *pk = sk + (uint32_t)16U;
  uint8_t *seed_a = pk;
  uint8_t *b = pk + (uint32_t)16U;
  uint8_t *seed_ep = g;
  uint16_t sp_matrix[512U] = { 0U };
  Hacl_Impl_Frodo_Sample_frodo_sample_matrix((uint32_t)8U,
    (uint32_t)64U,
    (uint32_t)16U,
    seed_ep,
    (uint16_t)4U,
    sp_matrix);
  uint16_t a_matrix[4096U] = { 0U };
  uint16_t ep_matrix[512U] = { 0U };
  Hacl_Impl_Frodo_Gen_frodo_gen_matrix_cshake((uint32_t)64U, (uint32_t)16U, seed_a, a_matrix);
  Hacl_Impl_Frodo_Sample_frodo_sample_matrix((uint32_t)8U,
    (uint32_t)64U,
    (uint32_t)16U,
    seed_ep,
    (uint16_t)5U,
    ep_matrix);
  Hacl_Impl_Matrix_matrix_mul((uint32_t)8U,
    (uint32_t)64U,
    (uint32_t)64U,
    sp_matrix,
    a_matrix,
    bpp_matrix);
  Hacl_Impl_Matrix_matrix_add((uint32_t)8U, (uint32_t)64U, bpp_matrix, ep_matrix);
  Lib_Memzero_clear_words_u16((uint32_t)512U, ep_matrix);
  Hacl_Impl_Frodo_KEM_Encaps_frodo_mul_add_sb_plus_e_plus_mu(b,
    seed_ep,
    mu_decode1,
    sp_matrix,
    cp_matrix);
  Lib_Memzero_clear_words_u16((uint32_t)512U, sp_matrix);
  uint8_t res = (uint8_t)255U;
  for (uint32_t i = (uint32_t)0U; i < (uint32_t)16U; i = i + (uint32_t)1U)
  {
    uint8_t uu____0 = FStar_UInt8_eq_mask(d0[i], dp[i]);
    res = uu____0 & res;
  }
  uint8_t z = res;
  bool b1 = z == (uint8_t)255U;
  bool
  b2 =
    Hacl_Impl_Matrix_matrix_eq((uint32_t)8U,
      (uint32_t)64U,
      (uint32_t)15U,
      bp_matrix,
      bpp_matrix);
  bool
  b3 = Hacl_Impl_Matrix_matrix_eq((uint32_t)8U, (uint32_t)8U, (uint32_t)15U, c_matrix, cp_matrix);
  bool b0 = b1 && b2 && b3;
  bool b4 = b0;
  uint8_t *kp = g + (uint32_t)16U;
  uint8_t *s = sk;
  uint8_t *kp_s;
  if (b4)
  {
    kp_s = kp;
  }
  else
  {
    kp_s = s;
  }
  uint8_t *c12 = ct;
  uint8_t *d = ct + Hacl_Impl_Frodo_KEM_crypto_ciphertextbytes - (uint32_t)16U;
  uint32_t ss_init_len = Hacl_Impl_Frodo_KEM_crypto_ciphertextbytes + (uint32_t)16U;
  KRML_CHECK_SIZE(sizeof (uint8_t), ss_init_len);
  uint8_t ss_init[ss_init_len];
  memset(ss_init, 0U, ss_init_len * sizeof ss_init[0U]);
  memcpy(ss_init,
    c12,
    (Hacl_Impl_Frodo_KEM_crypto_ciphertextbytes - (uint32_t)16U) * sizeof c12[0U]);
  memcpy(ss_init + Hacl_Impl_Frodo_KEM_crypto_ciphertextbytes - (uint32_t)16U,
    kp_s,
    (uint32_t)16U * sizeof kp_s[0U]);
  memcpy(ss_init + Hacl_Impl_Frodo_KEM_crypto_ciphertextbytes - (uint32_t)16U + (uint32_t)16U,
    d,
    (uint32_t)16U * sizeof d[0U]);
  uint64_t s1[25U] = { 0U };
  s1[0U] = (uint64_t)0x10010001a801U | (uint64_t)(uint16_t)7U << (uint32_t)48U;
  Hacl_Impl_SHA3_state_permute(s1);
  Hacl_Impl_SHA3_absorb(s1, (uint32_t)168U, ss_init_len, ss_init, (uint8_t)0x04U);
  Hacl_Impl_SHA3_squeeze(s1, (uint32_t)168U, (uint32_t)16U, ss);
  Lib_Memzero_clear_words_u8((uint32_t)32U, g);
  return (uint32_t)0U;
}

back to top