-
+ 5C5C7220C10FBB579426F43BA712034A4F2FD07F36E4A599E47A74E6305AA2F97FD1F0BB96E6D23FD8FE575ED539EB625917EE54C063B8200DFFE7985790DC2A
eucrypt/smg_bit_keccak/tests/smg_bit_keccak-test.adb
(0 . 0)(1 . 393)
553 with SMG_Bit_Keccak; use SMG_Bit_Keccak;
554 with Ada.Exceptions; use Ada.Exceptions;
555 with Ada.Text_IO; use Ada.Text_IO;
556 with Ada.Strings.Fixed; use Ada.Strings.Fixed;
557 with Interfaces; use Interfaces;
558
559 procedure SMG_Bit_Keccak.Test is
560 --types
561 type Keccak_Perms is ( None, Theta, Rho, Pi, Chi, Iota );
562 type Test_Vector is array( Keccak_Perms ) of State;
563 type Test_Round is array( Round_Index ) of Test_Vector;
564 subtype Hexstring is String( 1 .. Z_Length / 4 ); --word as hex string
565 subtype Bitstring is String( 1 .. Z_Length ); -- word as binary string
566 type Bithex is array( 0 .. 3 ) of Bit;
567
568 -- helper methods
569 procedure HexCharToBit( H : in Character; B: out Bithex) is
570 begin
571 case H is
572 when '0' => B := (0, 0, 0, 0);
573 when '1' => B := (0, 0, 0, 1);
574 when '2' => B := (0, 0, 1, 0);
575 when '3' => B := (0, 0, 1, 1);
576 when '4' => B := (0, 1, 0, 0);
577 when '5' => B := (0, 1, 0, 1);
578 when '6' => B := (0, 1, 1, 0);
579 when '7' => B := (0, 1, 1, 1);
580 when '8' => B := (1, 0, 0, 0);
581 when '9' => B := (1, 0, 0, 1);
582 when 'A' => B := (1, 0, 1, 0);
583 when 'B' => B := (1, 0, 1, 1);
584 when 'C' => B := (1, 1, 0, 0);
585 when 'D' => B := (1, 1, 0, 1);
586 when 'E' => B := (1, 1, 1, 0);
587 when 'F' => B := (1, 1, 1, 1);
588 when others => null;
589 end case;
590 end HexCharToBit;
591
592 function HexToBitword( H: in Hexstring ) return Bitword is
593 BW : Bitword;
594 B1, B2 : Bithex;
595 PosH, PosB : Natural;
596 begin
597 -- read the hexstring octet by octet
598 for I in 1 .. Z_Length / 8 loop
599 PosH := Integer(H'First) + (I - 1) * 2;
600 HexCharToBit( H(PosH), B1 );
601 HexCharToBit( H(PosH + 1), B2 );
602
603 PosB := Integer(BW'First) + (I - 1) * 8;
604 for J in 0 .. 3 loop
605 BW ( ZCoord(PosB + J) ) := B1(J);
606 BW ( ZCoord(PosB + 4 + J) ) := B2(J);
607 end loop;
608 end loop;
609 return BW;
610 end HexToBitword;
611
612 -- prints one bitword as an array of bits
613 procedure print_bitword( B: in Bitword ) is
614 bstr: Bitstring;
615 begin
616 for I in ZCoord loop
617 if B( I ) > 0 then
618 bstr( Bitstring'First + Integer(I) ) := '1';
619 else
620 bstr( Bitstring'First + Integer(I) ) := '0';
621 end if;
622 end loop;
623 Put(bstr);
624 end print_bitword;
625
626 -- prints a keccak state, bitword by bitword
627 procedure print_state( S: in State; Title: in String) is
628 begin
629 Put_Line("---------" & Title & "---------");
630 for Y in XYCoord loop
631 for X in XYCoord loop
632 Put( "S(" & XYCoord'Image(X) & ", " & XYCoord'Image(Y) & ")= ");
633 print_bitword( S( X, Y ) );
634 new_line(1);
635 end loop;
636 end loop;
637 end print_state;
638
639 function read_state(File: in FILE_TYPE; Oct: Positive :=8) return State is
640 S: State;
641 Line1: String := "0000000000000000 " &
642 "0000000000000000 " &
643 "0000000000000000 " &
644 "0000000000000000 " &
645 "0000000000000000";
646 StartPos, EndPos: Positive;
647 Len: Positive := Oct*2;
648 HStr: Hexstring;
649 begin
650 for Y in XYCoord loop
651 Line1 := Get_Line(File);
652 StartPos := Line1'First;
653 EndPos := StartPos + Len-1;
654
655 for X in XYCoord loop
656 HStr := Line1( StartPos .. EndPos );
657 S( X, Y ) := HexToBitword(HStr);
658 StartPos := EndPos + 2; --one space to skip
659 EndPos := StartPos + Len - 1;
660 end loop;
661 end loop;
662 return S;
663 end read_state;
664
665 --reads a full test round from specified file (pre-defined format)
666 function read_from_file (filename : in String;
667 T : out Test_Round)
668 return Boolean is
669 file: FILE_TYPE;
670 InputMarker: String := "lanes as 64-bit words:";
671 octets: Positive := 8;
672 RoundNo: Round_Index;
673 begin
674 -- try to open the input file
675 begin
676 open(file, In_File, filename);
677 exception
678 when others =>
679 Put_Line(Standard_Error,
680 "Can not open the file '" & filename & "'. Does it exist?");
681 return False;
682 end;
683
684 -- find & read input state first
685 RoundNo := -1;
686 loop
687 declare
688 Line: String := Get_Line(file);
689 begin
690 --check if this is test data of any known kind
691 if index(Line, InputMarker, 1) > 0 then
692 T(0)(None) := read_state(file, octets);
693 print_state(T(0)(None), "Read Input State");
694 elsif index(Line, "Round ", 1) > 0 then
695 RoundNo := RoundNo +1;
696 elsif index(Line, "theta", 1) > 0 then
697 T(RoundNo)(Theta) := read_state(file, octets);
698 if (RoundNo > 0) then
699 T(RoundNo)(None) := T(RoundNo-1)(Iota); -- previous state as input
700 end if;
701 elsif index(Line, "rho", 1) > 0 then
702 T(RoundNo)(Rho) := read_state(file, octets);
703 elsif index(Line, "pi", 1) > 0 then
704 T(RoundNo)(Pi) := read_state(file, octets);
705 elsif index(Line, "chi", 1) > 0 then
706 T(RoundNo)(Chi) := read_state(file, octets);
707 elsif index(Line, "iota", 1) > 0 then
708 T(RoundNo)(Iota) := read_state(file, octets);
709 end if;
710 exit when End_Of_File(file);
711 end;
712 end loop;
713 Close(file);
714 return True;
715 end read_from_file;
716
717
718 -- performs one single round of Keccak, step by step
719 -- each permutation is tested separately
720 -- test fails with exception raised at first output not matching expected
721 procedure test_one_round(T: Test_Vector; Round: Round_Index) is
722 Input: State;
723 Expected: State;
724 Output: State;
725 Test_One_Round_Fail: Exception;
726 begin
727 Input := T(None);
728 for I in Keccak_Perms range Theta..Iota loop
729 Expected := T(I);
730 case I is
731 when Theta => Output := SMG_Bit_Keccak.Theta(Input);
732 when Rho => Output := SMG_Bit_Keccak.Rho(Input);
733 when Pi => Output := SMG_Bit_Keccak.Pi(Input);
734 when Chi => Output := SMG_Bit_Keccak.Chi(Input);
735 when Iota => Output := SMG_Bit_Keccak.Iota(RC(Round), Input);
736 when others => null;
737 end case;
738
739 if (Output /= Expected) then
740 print_state(Output, "----------real output-------");
741 print_state(Expected, "----------expected output--------");
742 raise Test_One_Round_Fail;
743 else
744 Put_Line("PASSED: " & Keccak_Perms'Image(I));
745 end if;
746 -- get ready for next permutation
747 Input := Expected;
748 end loop;
749 end test_one_round;
750
751 procedure test_bwrotate_left( Input : in Bitword;
752 N : Positive;
753 Expected : in Bitword) is
754 Output: Bitword;
755 begin
756 Output := BWRotate_Left( Input, N );
757 if Output /= Expected then
758 Put_Line("FAIL: test bitword rotate left");
759 Put_Line("Output:");
760 print_bitword( Output );
761 Put_Line("Expected:");
762 print_bitword( Expected );
763 else
764 Put_Line("PASS: test bitword rotate left");
765 end if;
766 end test_bwrotate_left;
767
768 procedure test_keccak_function(T: in Test_Round) is
769 S: State;
770 begin
771 Put_Line("---Full Keccak Function test---");
772 S := Keccak_Function(T(Round_Index'First)(None));
773 if S /= T(Round_Index'Last)(Iota) then
774 Put_Line("FAILED: full keccak function test");
775 else
776 Put_Line("PASSED: full keccak function test");
777 end if;
778 end test_keccak_function;
779
780 procedure test_sponge is
781 Bitrate : constant Keccak_Rate := 1344;
782 Input1 : Bitstream( 1 .. 5 ) := (1, 1, 0, 0, 1);
783 Input2 : Bitstream( 1 .. 30) := (1, 1, 0, 0,
784 1, 0, 1, 0,
785 0, 0, 0, 1,
786 1, 0, 1, 0,
787 1, 1, 0, 1,
788 1, 1, 1, 0,
789 1, 0, 0, 1,
790 1, 0);
791 Hex : array(0..15) of Character := ("0123456789ABCDEF");
792 C : Natural;
793 ExpHex1 : constant String :=
794 "CB7FFB7CE7572A06C537858A0090FC2888C3C6BA9A3ADAB4"&
795 "FE7C9AB4EFE7A1E619B834C843A5A79E23F3F7E314AA597D"&
796 "9DAD376E8413A005984D00CF954F62F59EF30B050C99EA64"&
797 "E958335DAE684195D439B6E6DFD0E402518B5E7A227C48CF"&
798 "239CEA1C391241D7605733A9F4B8F3FFBE74EE45A40730ED"&
799 "1E2FDEFCCA941F518708CBB5B6D5A69C30263267B97D7B29"&
800 "AC87043880AE43033B1017EFB75C33248E2962892CE69DA8"&
801 "BAF1DF4C0902B16C64A1ADD42FF458C94C4D3B0B32711BBA"&
802 "22104989982543D1EF1661AFAF2573687D588C81113ED7FA"&
803 "F7DDF912021FC03D0E98ACC0200A9F7A0E9629DBA33BA0A3"&
804 "C03CCA5A7D3560A6DB589422AC64882EF14A62AD9807B353"&
805 "8DEE1548194DBD456F92B568CE76827F41E0FB3C7F25F3A4"&
806 "C707AD825B289730FEBDFD22A3E742C6FB7125DE0E38B130"&
807 "F3059450CA6185156A7EEE2AB7C8E4709956DC6D5E9F99D5"&
808 "0A19473EA7D737AC934815D68C0710235483DB8551FD8756"&
809 "45692B4E5E16BB9B1142AE300F5F69F43F0091D534F372E1"&
810 "FFC2E522E71003E4D27EF6ACCD36B2756FB5FF02DBF0C96B"&
811 "CAE68E7D6427810582F87051590F6FB65D7B948A9C9D6C93"&
812 "AF4562367A0AD79109D6F3087C775FE6D60D66B74F8D29FB"&
813 "4BA80D0168693A748812EA0CD3CA23854CC84D4E716F4C1A"&
814 "A3B340B1DED2F304DFDBACC1D792C8AC9A1426913E3F67DB"&
815 "790FD5CFB77DAA29";
816 ExpHex2 : constant String :=
817 "35F4FBA9D29E833B1DB17CA2077C11B3348C8AF2A29344AE"&
818 "6AAA1F63FC4536CE795C54F0359953B97CEA27491691E93E"&
819 "E4829EAB388211E6E8BD3EDA74366D0947DFA3D65D127593"&
820 "0AFC42884B7324717DCB003D7B3B5C2E92B84F478CC8DBB5"&
821 "174EB4BAC6207BD22E56FCC6E5FB11BC598FDBE6208913CE"&
822 "34BC03837FDBFCDFF9407D948531B5FC7FFE7029F30E7EDC"&
823 "F9282F0A630FA99839776F5EEA485449F62E421552AF9571";
824 HexStr1 : String( 1 .. ExpHex1'Length );
825 Output1 : Bitstream( 1 .. ExpHex1'Length * 4 );
826 HexStr2 : String( 1 .. ExpHex2'Length );
827 Output2 : Bitstream( 1 .. ExpHex2'Length * 4 );
828 Error : Natural;
829 Pos : Natural;
830 HexPos : Natural;
831 begin
832
833 -- test 1
834 Put_Line("---sponge test 1---");
835 Sponge(Input1, Bitrate, Output1);
836 Put_Line("Input is:");
837 for I of Input1 loop
838 Put(Bit'Image(I));
839 end loop;
840 new_line(1);
841
842 Put_Line("Output is:");
843 for I of Output1 loop
844 Put(Bit'Image(I));
845 end loop;
846 new_line(1);
847
848 Error := 0;
849 for I in 1..Output1'Length/4 loop
850 Pos := Output1'First + (I-1)*4;
851 C := Natural( Output1( Pos ) ) +
852 Natural( Output1( Pos + 1 ) ) * 2 +
853 Natural( Output1( Pos + 2 ) ) * 4 +
854 Natural( Output1( Pos + 3 ) ) * 8;
855 HexPos := I + 2 * ( I mod 2 ) - 1;
856 Hexstr1( HexPos ) := Hex(C);
857 if Hexstr1( HexPos ) /= ExpHex1( HexPos ) then
858 Error := Error + 1;
859 end if;
860 end loop;
861 Put_Line("Expected: ");
862 Put_Line(ExpHex1);
863 Put_Line("Obtained: ");
864 Put_Line(Hexstr1);
865 Put_Line("Errors found: " & Natural'Image(Error));
866
867 -- test 2
868 Put_Line("---sponge test 2---");
869 Sponge(Input2, Bitrate, Output2);
870 Put_Line("Input is:");
871 for I of Input2 loop
872 Put(Bit'Image(I));
873 end loop;
874 new_line(1);
875
876 Put_Line("Output is:");
877 for I of Output2 loop
878 Put(Bit'Image(I));
879 end loop;
880 new_line(1);
881
882 Error := 0;
883 for I in 1..Output2'Length/4 loop
884 Pos := Output2'First + (I-1)*4;
885 C := Natural( Output2( Pos ) ) +
886 Natural( Output2( Pos + 1 ) ) * 2 +
887 Natural( Output2( Pos + 2 ) ) * 4 +
888 Natural( Output2( Pos + 3 ) ) * 8;
889 HexPos := I + 2 * ( I mod 2 ) - 1;
890 Hexstr2( HexPos ) := Hex(C);
891 if Hexstr2( HexPos ) /= ExpHex2( HexPos ) then
892 Error := Error + 1;
893 end if;
894 end loop;
895 Put_Line("Expected: ");
896 Put_Line(ExpHex2);
897 Put_Line("Obtained: ");
898 Put_Line(Hexstr2);
899 Put_Line("Errors found: " & Natural'Image(Error));
900
901 end test_sponge;
902
903 -- end of helper methods
904
905 --variables
906 T : Test_Round;
907 BW, E : Bitword;
908 begin
909 BW:=(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
910 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,1,0);
911 E:=(0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
912 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, 1,0,0,0);
913 test_bwrotate_left(BW, 2, E);
914
915 Put_Line("-----Testing with zero state as input------");
916 if (not read_from_file("testvectorszero.txt", T)) then
917 return;
918 end if;
919
920 for I in Round_Index loop
921 Put_Line("---round " & Round_Index'Image(I) & "---");
922 test_one_round(T(I), I);
923 end loop;
924
925 -- test also Keccak_Function as a whole --
926 test_keccak_function(T);
927
928 Put_Line("-----Testing with non-zero state as input------");
929 if (not read_from_file("testvectorsnonzero.txt", T)) then
930 return;
931 end if;
932
933 for I in Round_Index loop
934 Put_Line("---round " & Round_Index'Image(I) & "---");
935 test_one_round(T(I), I);
936 end loop;
937
938 -- test also Keccak_Function as a whole --
939 test_keccak_function(T);
940
941 -- test Sponge construction
942 test_sponge;
943
944 end SMG_Bit_Keccak.Test;
945