raw
eucrypt_ch11_serpent    1  -- S.MG, 2018
eucrypt_ch11_serpent 2 -- Testing of Serpent implementation using Nessie-format test vectors
eucrypt_ch11_serpent 3
eucrypt_ch11_serpent 4 with SMG_Serpent; use SMG_Serpent;
eucrypt_ch11_serpent 5
eucrypt_ch11_serpent 6 with Ada.Text_IO; use Ada.Text_IO;
eucrypt_ch11_serpent 7 with Ada.Command_Line; use Ada.Command_Line; -- set exit status on fail
eucrypt_ch11_serpent 8 with Interfaces; use Interfaces; -- unsigned_8
eucrypt_ch11_serpent 9
eucrypt_ch11_serpent 10 package body Test_Serpent is
eucrypt_ch11_serpent 11 Test_Fail : exception; -- raised if a test fails
eucrypt_ch11_serpent 12
eucrypt_ch11_serpent 13 procedure test_from_file (filename: String) is
eucrypt_ch11_serpent 14 file : FILE_TYPE;
eucrypt_ch11_serpent 15 keylen : constant := 256;
eucrypt_ch11_serpent 16 blocklen : constant := 128;
eucrypt_ch11_serpent 17 octets : constant := 16;
eucrypt_ch11_serpent 18 K : Key;
eucrypt_ch11_serpent 19 P, P2 : Block; --plain text
eucrypt_ch11_serpent 20 C, C2 : Block; --cipher (encrypted) text
eucrypt_ch11_serpent 21 times100 : Block; --value after 100 iterations
eucrypt_ch11_serpent 22 times1k : Block; --value after 1000 iterations
eucrypt_ch11_serpent 23 W : Key_Schedule;
eucrypt_ch11_serpent 24 Test_No : Positive := 1;
eucrypt_ch11_serpent 25 begin
eucrypt_ch11_serpent 26 begin
eucrypt_ch11_serpent 27 open(file, In_File, filename);
eucrypt_ch11_serpent 28 exception
eucrypt_ch11_serpent 29 when others =>
eucrypt_ch11_serpent 30 Put_Line(Standard_Error, "Can not open the file '" & filename &
eucrypt_ch11_serpent 31 "'. Does it exist?");
eucrypt_ch11_serpent 32 Set_Exit_Status(Failure);
eucrypt_ch11_serpent 33 return;
eucrypt_ch11_serpent 34 end;
eucrypt_ch11_serpent 35
eucrypt_ch11_serpent 36 loop
eucrypt_ch11_serpent 37 declare
eucrypt_ch11_serpent 38 Line1 : String := Get_Line(file);
eucrypt_ch11_serpent 39 Line2 : String := Line1;
eucrypt_ch11_serpent 40 key1, key2 : String( 1..octets*2 );
eucrypt_ch11_serpent 41 len : Natural := 0;
eucrypt_ch11_serpent 42 begin
eucrypt_ch11_serpent 43 --check if this is test data of any known kind
eucrypt_ch11_serpent 44 if index( Line1, "key=", 1 ) > 0 then
eucrypt_ch11_serpent 45 Line2 := Get_Line( file );
eucrypt_ch11_serpent 46 key1 := Tail( Line1, octets*2 );
eucrypt_ch11_serpent 47 key2 := Tail( Line2, octets*2 );
eucrypt_ch11_serpent 48 for jj in 1..octets loop
eucrypt_ch11_serpent 49 K(jj-1) := Unsigned_8'Value("16#" &
eucrypt_ch11_serpent 50 key1( ( jj - 1 ) * 2 + 1 .. jj * 2 ) &
eucrypt_ch11_serpent 51 "#");
eucrypt_ch11_serpent 52 K( jj + octets - 1 ) :=
eucrypt_ch11_serpent 53 Unsigned_8'Value("16#" &
eucrypt_ch11_serpent 54 key2( ( jj - 1 ) * 2 + 1 .. jj * 2 ) &
eucrypt_ch11_serpent 55 "#");
eucrypt_ch11_serpent 56 end loop;
eucrypt_ch11_serpent 57
eucrypt_ch11_serpent 58 elsif index( Line1, "plain=", 1 ) > 0 then
eucrypt_ch11_serpent 59 key1 := Tail( Line1, octets * 2 );
eucrypt_ch11_serpent 60 for jj in 1..octets loop
eucrypt_ch11_serpent 61 P(jj-1) := Unsigned_8'Value("16#" &
eucrypt_ch11_serpent 62 key1( ( jj - 1 ) * 2 + 1 .. jj * 2 ) &
eucrypt_ch11_serpent 63 "#");
eucrypt_ch11_serpent 64 end loop;
eucrypt_ch11_serpent 65 elsif index( Line1, "cipher=", 1 ) > 0 then
eucrypt_ch11_serpent 66 key1 := Tail( Line1, octets * 2 );
eucrypt_ch11_serpent 67 for jj in 1..octets loop
eucrypt_ch11_serpent 68 C(jj-1) := Unsigned_8'Value("16#" &
eucrypt_ch11_serpent 69 key1( ( jj - 1 ) * 2 + 1 .. jj * 2) &
eucrypt_ch11_serpent 70 "#");
eucrypt_ch11_serpent 71 end loop;
eucrypt_ch11_serpent 72 elsif index( Line1, "100 times=", 1 ) > 0 then
eucrypt_ch11_serpent 73 key1 := Tail( Line1, octets * 2 );
eucrypt_ch11_serpent 74 for jj in 1..octets loop
eucrypt_ch11_serpent 75 times100(jj-1) :=
eucrypt_ch11_serpent 76 Unsigned_8'Value("16#" &
eucrypt_ch11_serpent 77 key1( ( jj - 1 ) * 2 + 1 .. jj * 2 ) &
eucrypt_ch11_serpent 78 "#");
eucrypt_ch11_serpent 79 end loop;
eucrypt_ch11_serpent 80 elsif index( Line1, "1000 times=", 1 ) > 0 then
eucrypt_ch11_serpent 81 key1 := Tail( Line1, octets * 2 );
eucrypt_ch11_serpent 82 for jj in 1..octets loop
eucrypt_ch11_serpent 83 times1k(jj-1) :=
eucrypt_ch11_serpent 84 Unsigned_8'value("16#" &
eucrypt_ch11_serpent 85 key1( ( jj - 1 ) * 2 + 1 .. jj * 2 ) &
eucrypt_ch11_serpent 86 "#");
eucrypt_ch11_serpent 87 end loop;
eucrypt_ch11_serpent 88 --at this stage we should have ALL needed, so run test
eucrypt_ch11_serpent 89 Put("-----Test " & Positive'Image(Test_No) & ": encryption...");
eucrypt_ch11_serpent 90 Prepare_Key(K, W);
eucrypt_ch11_serpent 91 Encrypt(W, P, C2);
eucrypt_ch11_serpent 92 if C2 /= C then
eucrypt_ch11_serpent 93 raise Test_Fail;
eucrypt_ch11_serpent 94 else
eucrypt_ch11_serpent 95 Put_Line("Passed-----");
eucrypt_ch11_serpent 96 end if;
eucrypt_ch11_serpent 97 Put("-----Test " & Positive'Image(Test_No) & ": decryption...");
eucrypt_ch11_serpent 98 Decrypt(W, C2, P2);
eucrypt_ch11_serpent 99 if P /= P2 then
eucrypt_ch11_serpent 100 raise Test_Fail;
eucrypt_ch11_serpent 101 else
eucrypt_ch11_serpent 102 Put_Line("Passed-----");
eucrypt_ch11_serpent 103 end if;
eucrypt_ch11_serpent 104
eucrypt_ch11_serpent 105 Put("-----Test " & Positive'Image(Test_No) & ": 100 iterations...");
eucrypt_ch11_serpent 106 for jj in 1 .. 100 loop
eucrypt_ch11_serpent 107 Encrypt(W, P, C2);
eucrypt_ch11_serpent 108 Decrypt(W, C2, P2);
eucrypt_ch11_serpent 109 if (P2 /= P) then
eucrypt_ch11_serpent 110 raise Test_Fail;
eucrypt_ch11_serpent 111 end if;
eucrypt_ch11_serpent 112 P := C2;
eucrypt_ch11_serpent 113 end loop;
eucrypt_ch11_serpent 114 Put_Line("Passed-----");
eucrypt_ch11_serpent 115
eucrypt_ch11_serpent 116 Put("-----Test " & Positive'Image(Test_No) & ": 1000 iterations...");
eucrypt_ch11_serpent 117
eucrypt_ch11_serpent 118 for jj in 1 .. 900 loop
eucrypt_ch11_serpent 119 Encrypt(W, P, C2);
eucrypt_ch11_serpent 120 Decrypt(W, C2, P2);
eucrypt_ch11_serpent 121 if (P2 /= P) then
eucrypt_ch11_serpent 122 raise Test_Fail;
eucrypt_ch11_serpent 123 end if;
eucrypt_ch11_serpent 124 P := C2;
eucrypt_ch11_serpent 125 end loop;
eucrypt_ch11_serpent 126 Put_Line("Passed-----");
eucrypt_ch11_serpent 127 Test_No := Test_No + 1;
eucrypt_ch11_serpent 128 end if;
eucrypt_ch11_serpent 129 exit when End_Of_File(file);
eucrypt_ch11_serpent 130 end;
eucrypt_ch11_serpent 131 end loop;
eucrypt_ch11_serpent 132 Close(file);
eucrypt_ch11_serpent 133 end test_from_file;
eucrypt_ch11_serpent 134
eucrypt_ch11_serpent 135 procedure test_one is
eucrypt_ch11_serpent 136 K: Key;
eucrypt_ch11_serpent 137 P, P2: Block;
eucrypt_ch11_serpent 138 C: Block;
eucrypt_ch11_serpent 139 W: Key_Schedule;
eucrypt_ch11_serpent 140 begin
eucrypt_ch11_serpent 141 K := (16#80#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#,
eucrypt_ch11_serpent 142 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#,
eucrypt_ch11_serpent 143 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#,
eucrypt_ch11_serpent 144 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#);
eucrypt_ch11_serpent 145
eucrypt_ch11_serpent 146 P := (16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#,
eucrypt_ch11_serpent 147 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#, 16#00#);
eucrypt_ch11_serpent 148
eucrypt_ch11_serpent 149 SMG_Serpent.Prepare_Key(K, W);
eucrypt_ch11_serpent 150 Encrypt(W, P, C);
eucrypt_ch11_serpent 151 if C /= (16#A2#, 16#23#, 16#AA#, 16#12#, 16#88#, 16#46#, 16#3C#, 16#0E#,
eucrypt_ch11_serpent 152 16#2B#, 16#E3#, 16#8E#, 16#BD#, 16#82#, 16#56#, 16#16#, 16#C0#)
eucrypt_ch11_serpent 153 then
eucrypt_ch11_serpent 154 raise Test_Fail;
eucrypt_ch11_serpent 155 end if;
eucrypt_ch11_serpent 156
eucrypt_ch11_serpent 157 for I in 1 .. 100 loop
eucrypt_ch11_serpent 158 Encrypt(W, P, C);
eucrypt_ch11_serpent 159 Decrypt(W, C, P2);
eucrypt_ch11_serpent 160 if (P2 /= P) then
eucrypt_ch11_serpent 161 raise Test_Fail;
eucrypt_ch11_serpent 162 end if;
eucrypt_ch11_serpent 163 P := C;
eucrypt_ch11_serpent 164 end loop;
eucrypt_ch11_serpent 165
eucrypt_ch11_serpent 166 if C /= (16#73#, 16#9E#, 16#01#, 16#48#, 16#97#, 16#1F#, 16#D9#, 16#75#,
eucrypt_ch11_serpent 167 16#B5#, 16#85#, 16#EA#, 16#FD#, 16#BD#, 16#65#, 16#9E#, 16#2C#)
eucrypt_ch11_serpent 168 then
eucrypt_ch11_serpent 169 raise Test_Fail;
eucrypt_ch11_serpent 170 end if;
eucrypt_ch11_serpent 171
eucrypt_ch11_serpent 172 for I in 1 .. 900 loop
eucrypt_ch11_serpent 173 Encrypt(W, P, C);
eucrypt_ch11_serpent 174 Decrypt(W, C, P2);
eucrypt_ch11_serpent 175 if (P2 /= P) then
eucrypt_ch11_serpent 176 raise Test_Fail;
eucrypt_ch11_serpent 177 end if;
eucrypt_ch11_serpent 178 P := C;
eucrypt_ch11_serpent 179 end loop;
eucrypt_ch11_serpent 180
eucrypt_ch11_serpent 181 if C /= (16#BE#, 16#FD#, 16#00#, 16#E0#, 16#D6#, 16#E2#, 16#7E#, 16#56#,
eucrypt_ch11_serpent 182 16#95#, 16#1D#, 16#C6#, 16#61#, 16#44#, 16#40#, 16#D2#, 16#86#)
eucrypt_ch11_serpent 183 then
eucrypt_ch11_serpent 184 raise Test_Fail;
eucrypt_ch11_serpent 185 else
eucrypt_ch11_serpent 186 Put_Line("PASSED: test single case.");
eucrypt_ch11_serpent 187 end if;
eucrypt_ch11_serpent 188
eucrypt_ch11_serpent 189 end test_one;
eucrypt_ch11_serpent 190
eucrypt_ch11_serpent 191 end Test_Serpent;