rand.c 3.6 KB
#include <PR/bbtypes.h>
#include <PR/bbskapi.h>
#include <sha1.h>
#include "rand.h"
#include "util.h"
#include <PR/bcp.h>


/* this whole test is only defined for 20000 bits */

static const short	MINRUN[7] = { 0, 2315, 1114, 527, 240, 103, 103 };
static const short	MAXRUN[7] = { 0, 2685, 1386, 723, 384, 209, 209 };

#define LONGRUN 26
#define MINONES 9725
#define MAXONES 10275
/*
#define MINPOKE 2.16
#define MAXPOKE 46.17
*/

#define MINPOKE 2
#define MAXPOKE 46


const unsigned char Popcount[] = {
 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4,
 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5,
 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6,
 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7,
 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8
};

void
endrun(int last, int run, u32 runs[][7], int *nerrs)
{
    if (run >= LONGRUN) {
	++(*nerrs);
    }
    if (run > 6)
	run = 6;
    ++runs[last][run];
}

int
dofips(u8 *b, int size) {
  int i;
  u8 *p;
  u32 c;
  u32 X;
  u32 last;
  u32 run;
  u32 poker[16];
  u32 runs[2][7];
  int nerrs = 0;
  
#ifdef DEBUG
  message("Before monobit test\n");
#endif
  /* monobit test */
  for (p = b, c = 0; p < &b[size]; ++p){
    c += Popcount[*p];
  }
  
    
  /* monobit test */
  if (c <= MINONES || MAXONES <= c) {   
    message("fails monobit test\n");
    ++nerrs;
  }
#ifdef DEBUG
  else{
      message("Monobit test PASS \n");
    }
#endif

  /* poker test */
  memset(poker, 0, sizeof poker);
#ifdef DEBUG
  message("init poker values\n");
#endif
  for(p = b; p < &b[size]; ++p){
    ++poker[*p & 0xF];
    ++poker[(*p >> 4) & 0xF];
  }
#ifdef DEBUG
  message("after calculating poker values \n");
#endif
  X=0;
  for(i = 0; i < 16; i++){
    X += (u32) poker[i] * poker[i];
#ifdef DEBUG
    message("poker value->\n");
    output_int32_hex(poker[i]);
#endif
  }
#ifdef DEBUG
  message("after summing poker values\n");
  message("before X\n");
  output_int32_hex(X);
#endif
  X = 16* X/ 5000 - 5000;
#ifdef DEBUG
  message("after X\n");
  output_int32_hex(X);
#endif
  if((X <= MINPOKE)  ||  (MAXPOKE <= X)){
#ifdef DEBUG
    message("sample fails poker test\n");
#endif
    ++nerrs;
  }  
#ifdef DEBUG
  else{
    message("poker test PASS\n");
  }
#endif
 


  /* runs test */
   
    memset(runs, 0, sizeof runs);
    last = (b[0] >> 7) & 1;
    run = 0;
    for (p = b; p < &b[size]; ++p) {
	c = *p;
	for (i = 7; i >= 0; --i) {
	    if (((c >> i) & 1) != last) {
		endrun(last, run, runs, &nerrs);
		run = 0;
		last = (c >> i) & 1;
	    }
	    ++run;
	}
    }
    endrun(last, run, runs, &nerrs);

    for (run = 1; run <= 6; ++run) {
	for (last = 0; last <= 1; ++last) {
	  if (runs[last][run] <= MINRUN[run]) {
#ifdef DEBUG
	    message("too few runs\n");
#endif
	    ++nerrs;
	    }
	    else if (runs[last][run] >= MAXRUN[run]) {
#ifdef DEBUG
	      message("too many runs\n");
#endif
	      ++nerrs;
	    }
	}
    }

    if (nerrs ==0){     
#ifdef DEBUG
      message("All runs tests PASS\n");
      message("All tests PASS\n");
#endif
      return SK_API_SUCCESS;
    }
    else{
#ifdef DEBUG
      message("Atleast some tests FAIL\n");
#endif
      return SK_API_FAIL;
    }
}