raw
smg_comms_rsa_oaep      1  --S.MG, 2018
smg_comms_rsa_oaep 2
smg_comms_rsa_oaep 3 with Interfaces; use Interfaces;
smg_comms_rsa_oaep 4 with Interfaces.C; use Interfaces.C;
smg_comms_80cols 5 with Ada.Text_IO; use Ada.Text_IO;
smg_comms_80cols 6 with Ada.Sequential_IO;
smg_comms_rsa_oaep 7 with RSA_OAEP; use RSA_OAEP;
smg_comms_rsa_oaep 8 with OAEP; use OAEP;
smg_comms_rsa_oaep 9 with Raw_Types; use Raw_Types;
smg_comms_rsa_oaep 10 with RNG; use RNG;
smg_comms_rsa_oaep 11 with Keccak; use Keccak;
smg_comms_rsa_oaep 12
smg_comms_rsa_oaep 13 package body Test_RSA_OAEP is
smg_comms_rsa_oaep 14
smg_comms_rsa_oaep 15 procedure test_char_array is
smg_comms_rsa_oaep 16 S : String := OAEP.TMSR_STR;
smg_comms_packing... 17 O : Octets := Raw_Types.OAEP_RESERVED;
smg_comms_rsa_oaep 18 A : char_array(0..O'Length-1) := (others => '0');
smg_comms_rsa_oaep 19 B : Octets(0..O'Length -1) := (others => 0);
smg_comms_rsa_oaep 20 Fail : Boolean := FALSE;
smg_comms_rsa_oaep 21 begin
smg_comms_rsa_oaep 22 Octets_To_Char_Array(O, A);
smg_comms_rsa_oaep 23 Char_Array_To_Octets(A, B);
smg_comms_rsa_oaep 24
smg_comms_rsa_oaep 25 if B /= O then
smg_comms_rsa_oaep 26 Put_Line("FAIL: char_array_to_octets");
smg_comms_rsa_oaep 27 else
smg_comms_rsa_oaep 28 Put_Line("PASS: char_array_to_octets");
smg_comms_rsa_oaep 29 end if;
smg_comms_rsa_oaep 30
smg_comms_rsa_oaep 31 for I in 0..S'Length-1 loop
smg_comms_rsa_oaep 32 declare
smg_comms_rsa_oaep 33 C : Character := Character(A(A'First + size_t(I)));
smg_comms_rsa_oaep 34 E : Character := S(S'First + I);
smg_comms_rsa_oaep 35 begin
smg_comms_rsa_oaep 36 if C /= E then
smg_comms_rsa_oaep 37 Fail := TRUE;
smg_comms_rsa_oaep 38 Put("Error at pos " & Integer'Image(I) & ": ");
smg_comms_rsa_oaep 39 Put(Integer'Image(Character'Pos(C)));
smg_comms_rsa_oaep 40 Put_Line(" instead of " & Integer'Image(Character'Pos(E)));
smg_comms_rsa_oaep 41 end if;
smg_comms_rsa_oaep 42 end;
smg_comms_rsa_oaep 43 end loop;
smg_comms_rsa_oaep 44 if FAIL then
smg_comms_rsa_oaep 45 Put_Line("FAIL: test octets_to_char_array");
smg_comms_rsa_oaep 46 else
smg_comms_rsa_oaep 47 Put_Line("PASS: test octets_to_char_array");
smg_comms_rsa_oaep 48 end if;
smg_comms_rsa_oaep 49 end test_char_array;
smg_comms_rsa_oaep 50
smg_comms_rsa_oaep 51 -- test OAEP encrypt + decrypt
smg_comms_rsa_oaep 52 procedure test_oaep is
smg_comms_rsa_oaep 53 Plain: Octets(1..MAX_LEN_MSG);
smg_comms_rsa_oaep 54 Short: Octets(0..10);
smg_comms_rsa_oaep 55 Encr : OAEP_Block;
smg_comms_rsa_oaep 56 Decr : OAEP_HALF;
smg_comms_rsa_oaep 57 Len : Natural;
smg_comms_rsa_oaep 58 Entropy: OAEP_Block;
smg_comms_rsa_oaep 59 Success : Boolean;
smg_comms_rsa_oaep 60 begin
smg_comms_rsa_oaep 61 RNG.Get_Octets(Plain);
smg_comms_rsa_oaep 62 RNG.Get_Octets(Entropy);
smg_comms_rsa_oaep 63 RNG.Get_Octets(Short);
smg_comms_rsa_oaep 64
smg_comms_rsa_oaep 65 -- test full length message
smg_comms_rsa_oaep 66 OAEP_Encrypt(Plain, Entropy, Encr);
smg_comms_rsa_oaep 67 OAEP_Decrypt(Encr, Len, Decr, Success);
smg_comms_rsa_oaep 68
smg_comms_rsa_oaep 69 if not Success or Len/8 /= Plain'Length then
smg_comms_rsa_oaep 70 Put_Line("FAIL: oaep encrypt/decrypt on max len message.");
smg_comms_rsa_oaep 71 else
smg_comms_rsa_oaep 72 if Decr(Decr'First..Decr'First+Len/8-1) /=
smg_comms_rsa_oaep 73 Plain(Plain'First..Plain'First+Len/8-1) then
smg_comms_rsa_oaep 74 Put_Line("FAIL: oaep encrypt/decrypt on max len message - " &
smg_comms_rsa_oaep 75 "result different from expected.");
smg_comms_rsa_oaep 76 else
smg_comms_rsa_oaep 77 Put_Line("PASS: oaep encrypt/decrypt on max len message.");
smg_comms_rsa_oaep 78 end if;
smg_comms_rsa_oaep 79 end if;
smg_comms_rsa_oaep 80
smg_comms_rsa_oaep 81 -- test short message
smg_comms_rsa_oaep 82 OAEP_Encrypt(Short, Entropy, Encr);
smg_comms_rsa_oaep 83 OAEP_Decrypt(Encr, Len, Decr, Success);
smg_comms_rsa_oaep 84 if not Success or Len/8 /= Short'Length then
smg_comms_rsa_oaep 85 Put_Line("FAIL: oaep encrypt/decrypt on short message.");
smg_comms_rsa_oaep 86 else
smg_comms_rsa_oaep 87 if Decr(Decr'First..Decr'First+Len/8-1) /=
smg_comms_rsa_oaep 88 Short(Short'First..Short'First+Len/8-1) then
smg_comms_rsa_oaep 89 Put_Line("FAIL: oaep encrypt/decrypt on short message - " &
smg_comms_rsa_oaep 90 "result different from expected.");
smg_comms_rsa_oaep 91 else
smg_comms_rsa_oaep 92 Put_Line("PASS: oaep encrypt/decrypt on short message.");
smg_comms_rsa_oaep 93 end if;
smg_comms_rsa_oaep 94 end if;
smg_comms_rsa_oaep 95
smg_comms_rsa_oaep 96 end test_oaep;
smg_comms_rsa_oaep 97
smg_comms_rsa_oaep 98 -- test JUST RSA (i.e. without oaep) with RSA key pair previously generated
smg_comms_rsa_oaep 99 procedure test_rsa is
smg_comms_rsa_oaep 100 Plain: OAEP_Block := (others => 0);
smg_comms_rsa_oaep 101 Decr : OAEP_Block := (others => 0);
smg_comms_rsa_oaep 102 Encr : RSA_len;
smg_comms_rsa_oaep 103 pkey: RSA_pkey;
smg_comms_rsa_oaep 104 skey: RSA_skey;
smg_comms_rsa_oaep 105 begin
smg_comms_rsa_oaep 106 -- initialize with RSA pair previously generated
smg_comms_80cols 107 ReadRSAKey( "keys_rsa.txt", skey );
smg_comms_80cols 108
smg_comms_rsa_oaep 109 -- copy n and e for public key
smg_comms_rsa_oaep 110 pkey.n := skey.n;
smg_comms_rsa_oaep 111 pkey.e := skey.e;
smg_comms_rsa_oaep 112 -- get random data
smg_comms_rsa_oaep 113 RNG.Get_Octets(Plain);
smg_comms_rsa_oaep 114 -- make first octet < RSA key's modulus first octet
smg_comms_rsa_oaep 115 Plain(Plain'First) := 16#00#;
smg_comms_rsa_oaep 116 -- naked rsa encrypt/decrypt
smg_comms_rsa_oaep 117 Put_Line("Encrypting with RSA public key...");
smg_comms_rsa_oaep 118 Public_RSA( Plain, pkey, Encr );
smg_comms_rsa_oaep 119 Put_Line("Decrypting with RSA private key...");
smg_comms_rsa_oaep 120 Private_RSA( Encr, skey, Decr );
smg_comms_rsa_oaep 121 Put_Line("Checking...");
smg_comms_rsa_oaep 122
smg_comms_rsa_oaep 123 -- check result
smg_comms_rsa_oaep 124 if Decr /= Plain then
smg_comms_rsa_oaep 125 Put_Line("FAIL: RSA encrypt/decrypt result doesn't match plain.");
smg_comms_rsa_oaep 126 else
smg_comms_rsa_oaep 127 Put_Line("PASS: RSA encrypt/decrypt");
smg_comms_rsa_oaep 128 end if;
smg_comms_rsa_oaep 129 end test_rsa;
smg_comms_rsa_oaep 130
smg_comms_rsa_oaep 131 -- test rsa+oaep with RSA key pair previously generated
smg_comms_rsa_oaep 132 procedure test_rsa_oaep is
smg_comms_rsa_oaep 133 Plain: Octets(1..MAX_LEN_MSG) := (others=>20);
smg_comms_rsa_oaep 134 Short: Octets(1..10);
smg_comms_rsa_oaep 135 Decr : RSA_len;
smg_comms_rsa_oaep 136 Encr : RSA_len;
smg_comms_rsa_oaep 137 pkey: RSA_pkey;
smg_comms_rsa_oaep 138 skey: RSA_skey;
smg_comms_rsa_oaep 139 Success: Boolean;
smg_comms_rsa_oaep 140 Len : Natural;
smg_comms_rsa_oaep 141 begin
smg_comms_rsa_oaep 142 -- initialize with RSA pair previously generated
smg_comms_80cols 143 ReadRSAKey( "keys_rsa.txt", skey );
smg_comms_rsa_oaep 144 -- copy n and e for public key
smg_comms_rsa_oaep 145 pkey.n := skey.n;
smg_comms_rsa_oaep 146 pkey.e := skey.e;
smg_comms_rsa_oaep 147
smg_comms_rsa_oaep 148 -- test with 0 message of length Plain'Length
smg_comms_rsa_oaep 149 RSA_OAEP.Encrypt(Plain, pkey, Encr);
smg_comms_rsa_oaep 150 RSA_OAEP.Decrypt(Encr, skey, Decr, Len, Success);
smg_comms_rsa_oaep 151 if (not Success) or Len /= Plain'Length
smg_comms_rsa_oaep 152 or Plain /= Decr(Decr'First..Decr'First+Plain'Length-1) then
smg_comms_rsa_oaep 153 Put_Line("FAIL: RSA_OAEP on max len message 20-filled.");
smg_comms_rsa_oaep 154 else
smg_comms_rsa_oaep 155 Put_Line("PASS: RSA_OAEP on max len message 20-filled.");
smg_comms_rsa_oaep 156 end if;
smg_comms_rsa_oaep 157
smg_comms_rsa_oaep 158 -- get random data for "plain" message
smg_comms_rsa_oaep 159 RNG.Get_Octets(Plain);
smg_comms_rsa_oaep 160 RSA_OAEP.Encrypt(Plain, pkey, Encr);
smg_comms_rsa_oaep 161 RSA_OAEP.Decrypt(Encr, skey, Decr, Len, Success);
smg_comms_rsa_oaep 162 if (not Success) or Len /= Plain'Length
smg_comms_rsa_oaep 163 or Plain /= Decr(Decr'First..Decr'First+Plain'Length-1) then
smg_comms_rsa_oaep 164 Put_Line("FAIL: RSA_OAEP on random data of max length.");
smg_comms_rsa_oaep 165 else
smg_comms_rsa_oaep 166 Put_Line("PASS: RSA_OAEP on random data of max length.");
smg_comms_rsa_oaep 167 end if;
smg_comms_rsa_oaep 168
smg_comms_rsa_oaep 169 -- get random data for "short" message
smg_comms_rsa_oaep 170 RNG.Get_Octets(Short);
smg_comms_rsa_oaep 171 RSA_OAEP.Encrypt(Short, pkey, Encr);
smg_comms_rsa_oaep 172 RSA_OAEP.Decrypt(Encr, skey, Decr, Len, Success);
smg_comms_rsa_oaep 173 if (not Success) or Len /= Short'Length
smg_comms_rsa_oaep 174 or Short /= Decr(Decr'First..Decr'First+Short'Length-1) then
smg_comms_rsa_oaep 175 Put_Line("FAIL: RSA_OAEP on random data of short length.");
smg_comms_rsa_oaep 176 else
smg_comms_rsa_oaep 177 Put_Line("PASS: RSA_OAEP on random data of short length.");
smg_comms_rsa_oaep 178 end if;
smg_comms_rsa_oaep 179
smg_comms_rsa_oaep 180 end test_rsa_oaep;
smg_comms_rsa_oaep 181
smg_comms_rsa_oaep 182 -- helper methods
smg_comms_rsa_oaep 183 procedure Hex2Octets( Hex: in String; O: out Raw_Types.Octets ) is
smg_comms_rsa_oaep 184 S : String := "16#AA#";
smg_comms_rsa_oaep 185 -- to make sure that input String has EVEN number of chars (ie full octets)
smg_comms_rsa_oaep 186 H : String(1..Hex'Length+Hex'Length mod 2) := (others=>'0');
smg_comms_rsa_oaep 187 begin
smg_comms_rsa_oaep 188 -- first char is 0 if needed to cover full octet...
smg_comms_rsa_oaep 189 H(H'Length-Hex'Length+1..H'Length) := Hex;
smg_comms_rsa_oaep 190 O := (others => 0);
smg_comms_rsa_oaep 191 for I in 0 .. H'Length/2-1 loop
smg_comms_rsa_oaep 192 S := "16#" & H(H'First + I*2 .. H'First + I*2 + 1) & "#";
smg_comms_rsa_oaep 193 O(O'Last - H'Length/2 + 1 + I) := Unsigned_8'Value(S);
smg_comms_rsa_oaep 194 end loop;
smg_comms_rsa_oaep 195 end Hex2Octets;
smg_comms_rsa_oaep 196
smg_comms_rsa_oaep 197 procedure PrintOctets( O: in Raw_Types.Octets; Title: in String ) is
smg_comms_rsa_oaep 198 begin
smg_comms_rsa_oaep 199 Put_Line(Title);
smg_comms_rsa_oaep 200 for V of O loop
smg_comms_rsa_oaep 201 Put(Unsigned_8'Image(V) & " ");
smg_comms_rsa_oaep 202 end loop;
smg_comms_rsa_oaep 203 New_Line;
smg_comms_rsa_oaep 204 end PrintOctets;
smg_comms_rsa_oaep 205
smg_comms_80cols 206 procedure ReadRSAKey( Filename: in String; Key: out RSA_OAEP.RSA_skey ) is
smg_comms_80cols 207 package Char_IO is new Ada.Sequential_IO(Character);
smg_comms_80cols 208 use Char_IO;
smg_comms_80cols 209 Full : String(1..RSA_len'Length*2) := (others => '0');
smg_comms_80cols 210 Half : String(1..RSA_half'Length*2) := (others => '0');
smg_comms_80cols 211 F : Char_IO.File_Type;
smg_comms_80cols 212 C : Character;
smg_comms_80cols 213 begin
smg_comms_80cols 214 Open( File => F, Mode => In_File, Name => Filename );
smg_comms_80cols 215
smg_comms_80cols 216 -- read n
smg_comms_80cols 217 for I in Full'Range loop
smg_comms_80cols 218 Read(F, Full(I));
smg_comms_80cols 219 end loop;
smg_comms_80cols 220 -- read new line character and convert to hex
smg_comms_80cols 221 Read(F, C);
smg_comms_80cols 222 Hex2Octets(Full, Key.n);
smg_comms_80cols 223
smg_comms_80cols 224 -- read e
smg_comms_80cols 225 for I in Half'Range loop
smg_comms_80cols 226 Read(F, Half(I));
smg_comms_80cols 227 end loop;
smg_comms_80cols 228 -- read new line character and convert to hex
smg_comms_80cols 229 Read(F, C);
smg_comms_80cols 230 Hex2Octets(Half, Key.e);
smg_comms_80cols 231
smg_comms_80cols 232 -- read d
smg_comms_80cols 233 for I in Full'Range loop
smg_comms_80cols 234 Read(F, Full(I));
smg_comms_80cols 235 end loop;
smg_comms_80cols 236 -- read new line character and convert to hex
smg_comms_80cols 237 Read(F, C);
smg_comms_80cols 238 Hex2Octets(Full, Key.d);
smg_comms_80cols 239
smg_comms_80cols 240 -- read p
smg_comms_80cols 241 for I in Half'Range loop
smg_comms_80cols 242 Read(F, Half(I));
smg_comms_80cols 243 end loop;
smg_comms_80cols 244 -- read new line character and convert to hex
smg_comms_80cols 245 Read(F, C);
smg_comms_80cols 246 Hex2Octets(Half, Key.p);
smg_comms_80cols 247
smg_comms_80cols 248 -- read q
smg_comms_80cols 249 for I in Half'Range loop
smg_comms_80cols 250 Read(F, Half(I));
smg_comms_80cols 251 end loop;
smg_comms_80cols 252 -- read new line character and convert to hex
smg_comms_80cols 253 Read(F, C);
smg_comms_80cols 254 Hex2Octets(Half, Key.q);
smg_comms_80cols 255
smg_comms_80cols 256 -- read u
smg_comms_80cols 257 for I in Half'Range loop
smg_comms_80cols 258 Read(F, Half(I));
smg_comms_80cols 259 end loop;
smg_comms_80cols 260 Hex2Octets(Half, Key.u);
smg_comms_80cols 261
smg_comms_80cols 262 -- Close file
smg_comms_80cols 263 Close( F );
smg_comms_80cols 264
smg_comms_80cols 265 exception
smg_comms_80cols 266 when Char_IO.End_Error =>
smg_comms_80cols 267 Put_Line("ReadRSAKey ERROR: Unexpected end of file in " & Filename);
smg_comms_80cols 268 when others =>
smg_comms_80cols 269 Put_Line("ReadRSAKey ERROR: can not open file " & Filename);
smg_comms_80cols 270
smg_comms_80cols 271 end ReadRSAKey;
smg_comms_80cols 272
smg_comms_rsa_oaep 273 end Test_RSA_OAEP;