/* Fastrandombytes spinoff from SUPERCOP (bench.cr.yp.to) */

#include <string.h>
#include "kernelrandombytes.h"
#include "aes256ctr.h"
#include "randombytes.h"

unsigned long long randombytes_calls = 0;
unsigned long long randombytes_bytes = 0;

static unsigned int init = 0;
static unsigned char buf[128];
static unsigned long long pos = 128;
static aes256ctr_ctx state;

void randombytes(unsigned char *x,unsigned long long xlen) {
  randombytes_calls += 1;
  randombytes_bytes += xlen;

  if(!init) {
    unsigned char seed[32];
    kernelrandombytes(seed,32);
    aes256ctr_init(&state,seed,0);
    init = 1;
  }

  while(xlen > 0) {
    unsigned long long ready;

    if(pos == 128) {
      if(xlen > 128) {
        aes256ctr_squeezeblocks(x,xlen >> 7,&state);
        x += 128*(xlen >> 7);
        xlen -= 128*(xlen >> 7);
      }
      if(xlen == 0) return;

      aes256ctr_squeezeblocks(buf,1,&state);
      pos = 0;
    }

    ready = 128 - pos;
    if(xlen < ready) ready = xlen;
    memcpy(x,buf + pos,ready);
    memset(buf + pos,0,ready);
    x += ready;
    xlen -= ready;
    pos += ready;
  }
}
