rand.c
3.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#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;
}
}