]> git.cryptolib.org Git - avr-crypto-lib.git/blob - host/bigint_test.rb
adding modulo-reduction to bigint
[avr-crypto-lib.git] / host / bigint_test.rb
1 #!/usr/bin/ruby
2 # bigint_test.rb
3 =begin
4     This file is part of the AVR-Crypto-Lib.
5     Copyright (C) 2008, 2009  Daniel Otte (daniel.otte@rub.de)
6
7     This program is free software: you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation, either version 3 of the License, or
10     (at your option) any later version.
11
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16
17     You should have received a copy of the GNU General Public License
18     along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 =end
20
21 $debug = true
22 $debug = false
23 require 'rubygems'
24 require 'serialport'
25 require 'getopt/std'
26 require 'ftools'
27 require 'date'
28 $buffer_size = 0
29 $conffile_check = Hash.new
30 $conffile_check.default = 0
31
32 ################################################################################
33 # readconfigfile                                                               #
34 ################################################################################
35
36 def readconfigfile(fname, conf)
37   return conf if $conffile_check[fname]==1
38   $conffile_check[fname]=1
39   section = "default"
40   if not File.exists?(fname)
41     return conf
42   end
43   file = File.open(fname, "r")
44   until file.eof
45     line = file.gets()
46         next if /[\s]*#/.match(line)
47         if m=/\[[\s]*([^\s]*)[\s]*\]/.match(line)
48           section=m[1]
49           conf[m[1]] = Hash.new
50           next
51         end
52         next if not /=/.match(line)
53         m=/[\s]*([^\s]*)[\s]*=[\s]*([^\s]*)/.match(line)
54         if m[1]=="include"
55           Dir.glob(m[2]){ |fn| conf = readconfigfile(fn, conf) }
56         else
57           conf[section][m[1]] = m[2]
58         end
59   end
60   file.close()
61   return conf
62 end
63
64 ################################################################################
65 # reset_system                                                                 #
66 ################################################################################
67
68 def reset_system
69   $sp.print("exit\r")
70   sleep 0.1
71   $sp.print("exit\r")
72   sleep 0.1
73 end
74
75 ################################################################################
76 # init_system                                                                  #
77 ################################################################################
78
79 def init_system(test_prog)
80   $sp.print("echo off \r")
81   print("DBG i: " + "echo off \r"+"\n") if $debug
82   sleep 0.1
83   $sp.print("#{test_prog}\r")
84   print("DBG i: " + "#{test_prog} \r"+"\n") if $debug
85   sleep 1
86 end
87
88
89 ################################################################################
90 # screen_progress                                                              #
91 ################################################################################
92 def screen_progress(v)
93   if $linepos==0
94     printf("\n%5d [%04d]: ", $testno, $size)
95   end
96   putc((v)?('*'):('!'))
97   $testno += 1
98   $linepos = ($linepos+1)%$linewidth
99 end
100
101 ################################################################################
102 # add_test                                                                     #
103 ################################################################################
104
105 def add_test(a,b)
106   begin
107     line = $sp.gets()
108     line = "" if line==nil
109     puts("DBG got: "+line) if $debug
110     if /^Error:.*/.match(line)
111       puts line
112       return false
113     end
114   end while not /[\s]*enter a:[\s]*/.match(line)
115   $sp.print(a.to_s(16)+" ")
116   begin
117     line = $sp.gets()
118     line = "" if line==nil
119     puts("DBG got: "+line) if $debug
120     if /^Error:.*/.match(line)
121       puts line
122       return false
123     end
124   end while not /[\s]*enter b:[\s]*/.match(line)
125   $sp.print(b.to_s(16)+" ")
126   begin
127     line = $sp.gets()
128     line = "" if line==nil
129     puts("DBG got: "+line) if $debug
130     if /^Error:.*/.match(line)
131       puts line
132       return false
133     end
134   end while not m=/[\s]*([-]?[0-9a-fA-F]*)[\s]+\+[\s]+([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line)
135   a_ = m[1].to_i(16)
136   b_ = m[2].to_i(16)
137   c_ = m[3].to_i(16)
138   line.chomp!
139   if(a_== a && b_ == b && c_ == (a+b))
140     $logfile.printf("[pass]: %s\n", line)
141     return true
142   else
143     $logfile.printf("[fail (%s%s%s)]: %s", (a==a_)?"":"a", (b==b_)?"":"b", (c_==a+b)?"":"c",line)
144     $logfile.printf(" ; should %s + %s = %s\n", a.to_s(16), b.to_s(16), (a+b).to_s(16))
145     return false
146   end
147   return false
148 end
149
150 ################################################################################
151 # mul_test                                                                     #
152 ################################################################################
153
154 def mul_test(a,b)
155   begin
156     line = $sp.gets()
157     line = "" if line==nil
158     puts("DBG got: "+line) if $debug
159     if /^Error:.*/.match(line)
160       puts line
161       return false
162     end
163   end while not /[\s]*enter a:[\s]*/.match(line)
164   $sp.print(a.to_s(16)+" ")
165   begin
166     line = $sp.gets()
167     line = "" if line==nil
168     puts("DBG got: "+line) if $debug
169     if /^Error:.*/.match(line)
170       puts line
171       return false
172     end
173   end while not /[\s]*enter b:[\s]*/.match(line)
174   $sp.print(b.to_s(16)+" ")
175   begin
176     line = $sp.gets()
177     line = "" if line==nil
178     puts("DBG got: "+line) if $debug
179     if /^Error:.*/.match(line)
180       puts line
181       return false
182     end
183   end while not m=/[\s]*([+-]?[0-9a-fA-F]*)[\s]+\*[\s]+([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line)
184   a_ = m[1].to_i(16)
185   b_ = m[2].to_i(16)
186   c_ = m[3].to_i(16)
187   line.chomp!
188   if(a_== a && b_ == b && c_ == (a*b))
189     $logfile.printf("[pass]: %s\n", line)
190     return true
191   else
192     $logfile.printf("[fail (%s%s%s)]: %s", (a==a_)?"":"a", (b==b_)?"":"b", (c_==a+b)?"":"c",line)
193     $logfile.printf(" ; should %s * %s = %s\n", a.to_s(16), b.to_s(16), (a*b).to_s(16))
194     return false
195   end
196   return false
197 end
198
199 ################################################################################
200 # square_test                                                                  #
201 ################################################################################
202
203 def square_test(a)
204   begin
205     line = $sp.gets()
206     line = "" if line==nil
207     puts("DBG got: "+line) if $debug
208     if /^Error:.*/.match(line)
209       puts line
210       return false
211     end
212   end while not /[\s]*enter a:[\s]*/.match(line)
213   $sp.print(a.to_s(16)+" ")
214   begin
215     line = $sp.gets()
216     line = "" if line==nil
217     puts("DBG got: "+line) if $debug
218     if /^Error:.*/.match(line)
219       puts line
220       return false
221     end
222   end while not m=/[\s]*([+-]?[0-9a-fA-F]*)[\s]*\*\*2[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line)
223   a_ = m[1].to_i(16)
224   c_ = m[2].to_i(16)
225   line.chomp!
226   if(a_== a && c_ == (a**2))
227     $logfile.printf("[pass]: %s\n", line)
228     return true
229   else
230     $logfile.printf("[fail (%s%s)]: %s", (a==a_)?"":"a", (c_==a**2)?"":"c",line)
231     $logfile.printf(" ; should %s **2 = %s\n", a.to_s(16), (a**2).to_s(16))
232     return false
233   end
234   return false
235 end
236
237 ################################################################################
238 # reduce_test                                                                  #
239 ################################################################################
240
241 def reduce_test(a,b)
242   begin
243     line = $sp.gets()
244     line = "" if line==nil
245     puts("DBG got: "+line) if $debug
246     if /^Error:.*/.match(line)
247       puts line
248       return false
249     end
250   end while not /[\s]*enter a:[\s]*/.match(line)
251   $sp.print(a.to_s(16)+" ")
252   begin
253     line = $sp.gets()
254     line = "" if line==nil
255     puts("DBG got: "+line) if $debug
256     if /^Error:.*/.match(line)
257       puts line
258       return false
259     end
260   end while not /[\s]*enter b:[\s]*/.match(line)
261   $sp.print(b.to_s(16)+" ")
262   begin
263     line = $sp.gets()
264     line = "" if line==nil
265     puts("DBG got: "+line) if $debug
266     if /^Error:.*/.match(line)
267       puts line
268       return false
269     end
270   end while not m=/[\s]*([+-]?[0-9a-fA-F]*)[\s]+%[\s]+([+-]?[0-9a-fA-F]*)[\s]*=[\s]*([+-]?[0-9a-fA-F]*)/.match(line)
271   a_ = m[1].to_i(16)
272   b_ = m[2].to_i(16)
273   c_ = m[3].to_i(16)
274   line.chomp!
275   if(a_== a && b_ == b && c_ == (a%b))
276     $logfile.printf("[pass]: %s\n", line)
277     return true
278   else
279     $logfile.printf("[fail (%s%s%s)]: %s", (a==a_)?"":"a", (b==b_)?"":"b", (c_==a+b)?"":"c",line)
280     $logfile.printf(" ; should %s %% %s = %s\n", a.to_s(16), b.to_s(16), (a%b).to_s(16))
281     return false
282   end
283   return false
284 end
285
286 ################################################################################
287 # run_test_add                                                                 #
288 ################################################################################
289
290 def run_test_add(skip=0)
291   length_a_B = skip+1
292   length_b_B = skip+1
293   begin
294     $size = length_a_B
295     (0..16).each do |i|
296       s_a = rand(2)*2-1
297       s_b = rand(2)*2-1
298       a = rand(256**length_a_B) * s_a
299       b = rand(256**length_a_B) * s_b
300       v = add_test(a, b)
301       screen_progress(v)
302       v = add_test(b, a)
303       screen_progress(v)
304     end
305     (0..16).each do |i|
306       s_a = rand(2)-1
307       s_b = rand(2)-1
308       b_size = rand(length_b_B+1)
309       a = rand(256**length_a_B) * s_a
310       b = rand(256**b_size) * s_b
311       v = add_test(a, b)
312       screen_progress(v)      
313       v = add_test(b, a)
314       screen_progress(v)
315
316     end
317     length_a_B += 1
318     length_b_B += 1
319   end while length_a_B<4096/8
320 end
321
322 ################################################################################
323 # run_test_mul                                                                 #
324 ################################################################################
325
326 def run_test_mul(skip=0)
327   length_a_B = skip+1
328   length_b_B = skip+1
329   begin
330     $size = length_a_B
331     (0..16).each do |i|
332       s_a = rand(2)*2-1
333       s_b = rand(2)*2-1
334       a = rand(256**length_a_B) * s_a
335       b = rand(256**length_a_B) * s_b
336       v = mul_test(a, b)
337       screen_progress(v)
338       v = mul_test(b, a)
339       screen_progress(v)
340     end
341     (0..16).each do |i|
342       s_a = rand(2)-1
343       s_b = rand(2)-1
344       b_size = rand(length_b_B+1)
345       a = rand(256**length_a_B) * s_a
346       b = rand(256**b_size) * s_b
347       v = mul_test(a, b)
348       screen_progress(v)      
349       v = mul_test(b, a)
350       screen_progress(v)
351     end
352     length_a_B += 1
353     length_b_B += 1
354   end while length_a_B<4096/8
355 end
356
357 ################################################################################
358 # run_test_square                                                              #
359 ################################################################################
360
361 def run_test_square(skip=0)
362   length_a_B = skip+1
363   begin
364     $size = length_a_B
365     (0..16).each do |i|
366       a = rand(256**length_a_B)
367       v = square_test(a)
368       screen_progress(v)
369     end
370     length_a_B += 1
371   end while length_a_B<4096/8
372 end
373
374 ################################################################################
375 # run_test_reduce                                                              #
376 ################################################################################
377
378 def run_test_reduce(skip=0)
379   length_a_B = skip+1
380   length_b_B = skip+1
381   begin
382     $size = length_a_B
383     (0..16).each do |i|
384       a = rand(256**length_a_B)
385       b = rand(256**length_a_B)+1
386       v = reduce_test(a, b)
387       screen_progress(v)
388       end
389     (0..16).each do |i|
390       b_size = rand(length_b_B+1)
391       a = rand(256**length_a_B)
392       b = rand(256**b_size)+1 
393       v = reduce_test(a, b)
394       screen_progress(v)      
395       end
396     length_a_B += 1
397     length_b_B += 1
398   end while length_a_B<4096/8
399 end
400
401 ################################################################################
402 # MAIN                                                                         #
403 ################################################################################
404
405 opts = Getopt::Std.getopts("s:f:i:a:hd")
406
407 conf = Hash.new
408 conf = readconfigfile("/etc/testport.conf", conf)
409 conf = readconfigfile("~/.testport.conf", conf)
410 conf = readconfigfile("testport.conf", conf)
411 conf = readconfigfile(opts["f"], conf) if opts["f"]
412
413 #puts conf.inspect
414
415 puts("serial port interface version: " + SerialPort::VERSION);
416 $linewidth = 64
417 $linepos = 0
418 $testno = 0
419 params = { "baud"       => conf["PORT"]["baud"].to_i,
420             "data_bits" => conf["PORT"]["databits"].to_i,
421             "stop_bits" => conf["PORT"]["stopbits"].to_i,
422             "parity"    => SerialPort::NONE }
423 params["paraty"] = SerialPort::ODD   if conf["PORT"]["paraty"].downcase == "odd"
424 params["paraty"] = SerialPort::EVEN  if conf["PORT"]["paraty"].downcase == "even"
425 params["paraty"] = SerialPort::MARK  if conf["PORT"]["paraty"].downcase == "mark"
426 params["paraty"] = SerialPort::SPACE if conf["PORT"]["paraty"].downcase == "space"
427
428 puts("\nPort: "+conf["PORT"]["port"]+"@"    +
429                 params["baud"].to_s      +
430                 " "                      +
431                 params["data_bits"].to_s +
432                 conf["PORT"]["paraty"][0,1].upcase +
433                 params["stop_bits"].to_s +
434                 "\n")
435
436 $sp = SerialPort.new(conf["PORT"]["port"], params)
437
438 $sp.read_timeout=1000; # 5 minutes
439 $sp.flow_control = SerialPort::SOFT
440
441 reset_system()
442
443 if opts['d']
444   $debug = true
445 end
446
447 logfilename = conf['PORT']['testlogbase']+'bigint.txt'
448 if File.exists?(logfilename)
449   i=1
450   begin
451     logfilename = sprintf('%s%04d%s', conf['PORT']['testlogbase']+'bigint_',i,'.txt')
452     i+=1
453   end while(File.exists?(logfilename))
454   while(i>2) do
455     File.move(sprintf('%s%04d%s', conf['PORT']['testlogbase']+'bigint_',i-2,'.txt'), 
456               sprintf('%s%04d%s', conf['PORT']['testlogbase']+'bigint_',i-1,'.txt'), true)
457     i-=1
458   end
459     File.move(sprintf('%s%s', conf['PORT']['testlogbase'],'bigint.txt'), 
460               sprintf('%s%04d%s', conf['PORT']['testlogbase']+'bigint_',1,'.txt'), true)
461   logfilename = conf['PORT']['testlogbase']+'bigint.txt' 
462 end
463 $logfile = File.open(logfilename, 'w')
464 printf("logfile: %s\n", logfilename)
465
466 $logfile.printf("bigint test from: %s\n", Time.now.to_s)
467 $logfile.printf("skip = %s\n", opts['s']) if opts['s']
468 $logfile.printf("seed = 0x%X\n", 0xdeadbeef)
469
470 tests = Hash.new
471 tests['a'] = proc {|x| run_test_add(x) }
472 tests['m'] = proc {|x| run_test_mul(x) }
473 tests['s'] = proc {|x| run_test_square(x) }
474 tests['r'] = proc {|x| run_test_reduce(x) }
475 init_str = Hash.new
476 init_str['a'] = 'add-test'
477 init_str['m'] = 'mul-test'
478 init_str['s'] = 'square-test'
479 init_str['r'] = 'reduce-test'
480
481 srand(0xdeadbeef)
482
483 if opts['a']
484   opts['a'].each_char do |x|
485     if tests[x]
486       puts init_str[x]
487       init_system(init_str[x])
488       tests[x].call(opts['s']?opts['s'].to_i():0) 
489     else
490       puts "no test defiened for '#{x}'"
491     end  
492   end
493 else
494   'amsr'.each_char do |x|
495     if tests[x]
496       puts init_str[x]
497       init_system(init_str[x])
498       tests[x].call(opts['s']?opts['s'].to_i():0) 
499     else
500       puts "no test defiened for '#{x}'"
501     end  
502   end
503 end
504
505
506 $logile.close()