text: /**
   *
   * Optimized ISO-C11 Implementation of LEDAcrypt using GCC built-ins.
   *
   * @version 3.0 (May 2020)
   *
   * In alphabetical order:
   *
   * @author Marco Baldi <m.baldi@univpm.it>
   * @author Alessandro Barenghi <alessandro.barenghi@polimi.it>
   * @author Franco Chiaraluce <f.chiaraluce@univpm.it>
   * @author Gerardo Pelosi <gerardo.pelosi@polimi.it>
   * @author Paolo Santini <p.santini@pm.univpm.it>
   *
   * This code is hereby placed in the public domain.
   *
   * THIS SOFTWARE IS PROVIDED BY THE AUTHORS ''AS IS'' AND ANY EXPRESS
   * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE
   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
   * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
   * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
   * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
   * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   **/
  
  #include "niederreiter_keygen.h"
  #include "H_Q_matrices_generation.h"
  #include "gf2x_arith_mod_xPplusOne.h"
  #include "rng.h"
  #include "dfr_test.h"
  #include <string.h>
  /*----------ul------------------------------------------------------------------*/
  /* Implementation that should never be optimized out by the compiler */
  static inline void zeroize( void *v, size_t n )
  {
     volatile unsigned char *p = v;
     while( n-- ) *p++ = 0;
  } // end zeroize
  
  /*----------------------------------------------------------------------------*/
  
  void OQS_KEM_LEDACRYPT_28411_AVX2_key_gen_niederreiter(publicKeyNiederreiter_t   *const pk,
                            privateKeyNiederreiter_t *const sk)
  {
     AES_XOF_struct keys_expander;
     memset(&keys_expander,0x00,sizeof(AES_XOF_struct));
     OQS_KEM_LEDACRYPT_28411_AVX2_randombytes(sk->prng_seed, TRNG_BYTE_LENGTH);
     OQS_KEM_LEDACRYPT_28411_AVX2_seedexpander_from_trng(&keys_expander, sk->prng_seed);
  
     POSITION_T HPosOnes[N0][V];
  
     int isDFRok;
     sk->rejections = (uint8_t) 0;
     do {
        OQS_KEM_LEDACRYPT_28411_AVX2_generateHPosOnes(HPosOnes, &keys_expander);
        sk->rejections = sk->rejections + 1;
        isDFRok = OQS_KEM_LEDACRYPT_28411_AVX2_DFR_test(HPosOnes, &(sk->secondIterThreshold));
     } while(!isDFRok);
  
     sk->rejections = sk->rejections - 1;
  
     OQS_KEM_LEDACRYPT_28411_AVX2_seedexpander(&keys_expander,
                  sk->decryption_failure_secret,
                  (unsigned long)TRNG_BYTE_LENGTH);
  
     DIGIT Ln0dense[NUM_DIGITS_GF2X_ELEMENT] = {0x00};
     OQS_KEM_LEDACRYPT_28411_AVX2_gf2x_mod_densify_CT(Ln0dense,HPosOnes[N0-1],V);
  
     DIGIT Ln0Inv[NUM_DIGITS_GF2X_ELEMENT] = {0x00};
     GF2X_DIGIT_MOD_INVERSE(Ln0Inv, Ln0dense);
  
  #if (defined HIGH_PERFORMANCE_X86_64)
     for (int i = 0; i < N0-1; i++) {
        DIGIT Hdenseblock[NUM_DIGITS_GF2X_ELEMENT] = {0x00};
        OQS_KEM_LEDACRYPT_28411_AVX2_gf2x_mod_densify_CT(Hdenseblock,HPosOnes[i],V);
        OQS_KEM_LEDACRYPT_28411_AVX2_gf2x_mod_mul(pk->Mtr+i*NUM_DIGITS_GF2X_ELEMENT,
                     (const DIGIT * const) Hdenseblock,
                     Ln0Inv);
     }
  #else
     for (int i = 0; i < N0-1; i++) {
        OQS_KEM_LEDACRYPT_28411_AVX2_gf2x_mod_mul_dense_to_sparse(pk->Mtr+i*NUM_DIGITS_GF2X_ELEMENT,
                                     Ln0Inv,
                                     HPosOnes[i],
                                     V);
     }
  #endif
     for (int i = 0; i < N0-1; i++) {
        OQS_KEM_LEDACRYPT_28411_AVX2_gf2x_transpose_in_place(pk->Mtr+i*NUM_DIGITS_GF2X_ELEMENT);
     }
  } // end OQS_KEM_LEDACRYPT_28411_AVX2_key_gen_niederreiter
  
  /*----------------------------------------------------------------------------*/
  
  void OQS_KEM_LEDACRYPT_28411_AVX2_publicKey_deletion_niederreiter(publicKeyNiederreiter_t   *const pk)
  {
     zeroize(pk,sizeof(publicKeyNiederreiter_t));
  } // OQS_KEM_LEDACRYPT_28411_AVX2_publicKey_deletion_niederreiter
  
  /*----------------------------------------------------------------------------*/
  
  void OQS_KEM_LEDACRYPT_28411_AVX2_privateKey_deletion_niederreiter(privateKeyNiederreiter_t *const sk)
  {
     zeroize(sk, sizeof(privateKeyNiederreiter_t));
  } // OQS_KEM_LEDACRYPT_28411_AVX2_privateKey_deletion_niederreiter
  
  /*----------------------------------------------------------------------------*/
  