text: #include "rng.h"
  
  #include <string.h> // void *memset(void *s, int c, size_t n);
  
  #include "aes.h"
  #include "qc_ldpc_parameters.h"
  
  /*
   seedexpander_init()
   ctx            - stores the current state of an instance of the seed expander
   seed           - a 32 byte random value
   diversifier    - an 8 byte diversifier
   maxlen         - maximum number of bytes (less than 2**32) generated under this seed and diversifier
   */
  static void seedexpander_init(AES_XOF_struct *ctx,
                                unsigned char *seed,
                                unsigned char *diversifier,
                                size_t maxlen) {
  
      ctx->length_remaining = maxlen;
  
      memset(ctx->key, 0, 32);
      int max_accessible_seed_len = TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH;
      memcpy(ctx->key, seed, max_accessible_seed_len);
  
      memcpy(ctx->ctr, diversifier, 8);
      ctx->ctr[11] = maxlen % 256;
      maxlen >>= 8;
      ctx->ctr[10] = maxlen % 256;
      maxlen >>= 8;
      ctx->ctr[9] = maxlen % 256;
      maxlen >>= 8;
      ctx->ctr[8] = maxlen % 256;
      memset(ctx->ctr + 12, 0x00, 4);
  
      ctx->buffer_pos = 16;
      memset(ctx->buffer, 0x00, 16);
  }
  
  void PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander_from_trng(AES_XOF_struct *ctx,
          const unsigned char *trng_entropy
          /* TRNG_BYTE_LENGTH wide buffer */) {
  
      /*the NIST seedexpander will however access 32B from this buffer */
      unsigned int prng_buffer_size = TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH;
      unsigned char prng_buffer[TRNG_BYTE_LENGTH < 32 ? 32 : TRNG_BYTE_LENGTH] = { 0x00 };
      unsigned char diversifier[8] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
  
      memcpy(prng_buffer,
             trng_entropy,
             TRNG_BYTE_LENGTH < prng_buffer_size ? TRNG_BYTE_LENGTH : prng_buffer_size);
  
      /* the required seed expansion will be quite small, set the max number of
       * bytes conservatively to 10 MiB*/
      seedexpander_init(ctx, prng_buffer, diversifier, RNG_MAXLEN);
  }
  
  /*
   seedexpander()
      ctx  - stores the current state of an instance of the seed expander
      x    - returns the XOF data
      xlen - number of bytes to return
   */
  int PQCLEAN_LEDAKEMLT12_LEAKTIME_seedexpander(AES_XOF_struct *ctx, unsigned char *x, size_t xlen) {
      size_t offset;
      aes256ctx ctx256;
  
      if ( x == NULL ) {
          return RNG_BAD_OUTBUF;
      }
      if ( xlen >= ctx->length_remaining ) {
          return RNG_BAD_REQ_LEN;
      }
  
      aes256_keyexp(&ctx256, ctx->key);
      ctx->length_remaining -= xlen;
  
      offset = 0;
      while ( xlen > 0 ) {
          if ( xlen <= (16 - ctx->buffer_pos) ) { // buffer has what we need
              memcpy(x + offset, ctx->buffer + ctx->buffer_pos, xlen);
              ctx->buffer_pos += xlen;
  
              return RNG_SUCCESS;
          }
  
          // take what's in the buffer
          memcpy(x + offset, ctx->buffer + ctx->buffer_pos, 16 - ctx->buffer_pos);
          xlen -= 16 - ctx->buffer_pos;
          offset += 16 - ctx->buffer_pos;
  
          aes256_ecb(ctx->buffer, ctx->ctr, 16 / AES_BLOCKBYTES, &ctx256);
          ctx->buffer_pos = 0;
  
          //increment the counter
          for (int i = 15; i >= 12; i--) {
              if ( ctx->ctr[i] == 0xff ) {
                  ctx->ctr[i] = 0x00;
              } else {
                  ctx->ctr[i]++;
                  break;
              }
          }
  
      }
      aes256_ctx_release(&ctx256);
  
      return RNG_SUCCESS;
  }
  