]> wagner.pp.ru Git - sites/home_page.git/blob - software/tcl/fips140.tcl
grandpa picture
[sites/home_page.git] / software / tcl / fips140.tcl
1 #!/usr/bin/tclsh
2
3 proc test {name format value min max} {
4         global fail
5         puts -nonewline "[format %20s $name]: [format $format $value]\
6         (<[format $format $min] and >[format $format $max])  "
7         if {$value > $min && $value < $max} {
8                 puts "PASSED"
9         } else {
10                 incr fail
11                 puts "FAILED"
12         }
13 }       
14
15 if {$argc != 1} {
16         puts stderr "Usage $argv0 filename\n\
17         \twhere filename file with at least 20000 random bits (i.e.  /dev/random)"
18         exit 2
19 }       
20 fconfigure stderr -buffering none
21 set f [open [lindex $argv 0]]
22 fconfigure $f -translation binary -blocking y
23 puts -nonewline stderr  "Reading 20000 bits"
24 set bytes [read $f 2500]
25 puts " done"
26 close $f
27 if {[string length $bytes]<2500} {
28         puts stderr "Need at least 2500 bytes, got [string length $bytes]"
29         exit 2
30 }       
31 # monobit test 
32
33 array set hex2ones {0 0 1 1 2 1 3 2 4 1 5 2 6 2 7 3 8 1 9 2 a 2 b 3 c 2
34 d 3 e 3 f 4}
35
36 binary scan $bytes H* hex 
37
38 set ones 0
39 array set hist {0 0 1 0 2 0 3 0 4 0 5 0 6 0 7 0 8 0 9 0 a 0 b 0 c 0 d 0 e 0 f 0}
40
41 foreach nibble [split $hex ""] {
42         incr hist($nibble) 
43 }
44 set sumsquare 0
45 foreach {nibble count} [array get hist] {
46         set sumsquare [expr {$sumsquare + $count * $count}]
47         incr ones [expr $hist($nibble)*$hex2ones($nibble)] 
48 }
49 #parray hist
50 set fail 0
51 test "Monobit test" "%5d" $ones 9654 10346
52
53 set chi [expr {$sumsquare*16.0/5000-5000}]
54
55 test "Poker test" %5.2f $chi 1.03 57.4
56 binary scan $bytes b* bits
57 append bits 2
58 set run 0
59 array set runs {0,1 0 0,2 0 0,3 0 0,4 0 0,5 0 0,6 0
60 1,1 0 1,2 0 1,3 0 1,4 0 1,5 0 1,6 0}
61 array set runlimits {
62         1 {2267 2733} 
63         2 {1079 1421} 
64         3 {502 748} 
65         4 {223 402}
66         5 {90 223}
67         6 {90 223}
68 }       
69
70 set prevbit 2
71 set longest 0
72 foreach bit [split $bits ""] {
73         if {$bit == $prevbit} {
74                 incr run
75         } else {
76                 if {$run>0} {
77                         if {$run<=6} {
78                                 incr runs($prevbit,$run)
79                         } else {
80                                 incr runs($prevbit,6)
81                         }       
82                         if {$run>$longest} {
83                                 set longest $run
84                         }
85                 }
86                 set prevbit $bit
87                 set run 1
88         }
89 }
90 puts "[format %20s "Runs test"]:"
91 for {set i 1} {$i<=6} {incr i} {
92         eval test [list "$i zeroes"] %5d $runs(0,$i) $runlimits($i)
93         eval test [list "$i ones  "] %5d $runs(0,$i) $runlimits($i)
94         
95 }
96 test "Long Run test" %5d  $longest 6 34
97
98 if {$fail!=0} {
99         puts "Total result: FAILED!!!"
100         exit 1
101 }       
102