1-- This program is free software; you can redistribute it and/or 2-- modify it under the terms of the GNU General Public License as 3-- published by the Free Software Foundation; either version 2 of the 4-- License, or (at your option) any later version. 5 6-- This program is distributed in the hope that it will be useful, 7-- but WITHOUT ANY WARRANTY; without even the implied warranty of 8-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 9-- General Public License for more details. 10 11-- You should have received a copy of the GNU General Public License 12-- along with this program; if not, write to the Free Software 13-- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 14-- 02111-1307, USA. 15 16-- As a special exception, if other files instantiate generics from 17-- this unit, or you link this unit with other files to produce an 18-- executable, this unit does not by itself cause the resulting 19-- executable to be covered by the GNU General Public License. This 20-- exception does not however invalidate any other reasons why the 21-- executable file might be covered by the GNU Public License. 22 23with Crypto.Symmetric.Algorithm.Aes.Tables; 24use Crypto.Symmetric.Algorithm.Aes.Tables; 25 26package body Crypto.Symmetric.Algorithm.AES is 27 28 29 --------------------------------------------------------------------------- 30 --------------------------BUILD_ENCRYPT_KEY-------------------------------- 31 --------------------------------------------------------------------------- 32 33 procedure Build_Encrypt_Key(Key : in Bytes; 34 Encrypt_Key : in out Words; 35 Nk : in Positive) is 36 Temp : Word; 37 38 begin 39 -- copy user material bytes into temporary ints 40 for I in 0..Nk-1 loop 41 Encrypt_Key(I) := To_Word(Key(Nb*i), Key(Nb*i+1), 42 Key(Nb*i+2), Key(Nb*i+3)); 43 end loop; 44 for I in Nk..Encrypt_Key'Length-1 loop 45 Temp := Encrypt_Key(I-1); 46 47 if (I mod Nk) = 0 then 48 Temp := To_Word(S(Byte1(Temp)), S(Byte2(Temp)), 49 S(Byte3(Temp)), S(Byte0(Temp))) 50 xor Rcon(I / Nk ); 51 52 elsif (Nk > 6) and ((I mod Nk) = Nb) then 53 Temp:=To_Word(S(Byte0(Temp)), S(Byte1(Temp)), 54 S(Byte2(Temp)), S(Byte3(Temp))); 55 end if; 56 57 Encrypt_Key(I) := Encrypt_Key(I-Nk) xor Temp; 58 59 end loop; 60 end Build_Encrypt_Key; 61 62 ------------------------------------------------------------------------- 63 -------------------------BUILD_DECRYPT_KEY------------------------------- 64 ------------------------------------------------------------------------- 65 66 procedure Build_Decrypt_Key(Encrypt_Key : in Words; 67 Decrypt_Key : out Words) is 68 69 Rounds : constant Positive := Encrypt_Key'Length/Nb-1; 70 A0, A1, A2, A3 : Word; -- Working variables 71 Index : Natural:=Nb; -- current Roundkey index 72 begin 73 74 Decrypt_Key := Encrypt_Key; 75 76 for R in 1..Rounds-1 loop -- R*Nb 77 A0 := Decrypt_Key(Index); -- Index = R*Nb 78 Index:=Index+1; 79 A1 := Decrypt_Key(Index); -- Index = R*Nb+1 80 Index:=Index+1; 81 A2 := Decrypt_Key(Index); -- Index = R*Nb+2 82 Index:=Index+1; 83 A3 := Decrypt_Key(Index); -- Index := R*Nb+3 84 85 Index:=Index-3; -- Index := R*Nb; 86 87 Decrypt_Key(Index) := U1(Byte0(A0)) xor U2(Byte1(A0)) xor 88 U3(Byte2(A0)) xor U4(Byte3(A0)); 89 Index:= Index+1; -- Index := R*Nb+1; 90 Decrypt_Key(Index) := U1(Byte0(A1)) xor U2(Byte1(A1)) xor 91 U3(Byte2(A1)) xor U4(Byte3(A1)); 92 Index:= Index+1; -- Index := R*Nb+2; 93 Decrypt_Key(Index) := U1(Byte0(A2)) xor U2(Byte1(A2)) xor 94 U3(Byte2(A2)) xor U4(Byte3(A2)); 95 Index:= Index+1; -- Index := R*Nb+3; 96 Decrypt_Key(Index) := U1(Byte0(A3)) xor U2(Byte1(A3)) xor 97 U3(Byte2(A3)) xor U4(Byte3(A3)); 98 Index:= Index+1; -- Index := (R+1)*Nb; 99 end loop; 100 101 end Build_Decrypt_KEY; 102 103 ------------------------------------------------------------------------- 104 ---------------------------PREPARE_KEY----------------------------------- 105 ------------------------------------------------------------------------- 106 107 procedure Prepare_Key128(Key : in B_Block128; 108 Cipherkey : out Cipherkey_AES128) is 109 begin 110 Build_Encrypt_Key(Bytes(Key), Words(Cipherkey.Encrypt_Key), Nk=> Nk128); 111 Build_Decrypt_Key(Words(Cipherkey.Encrypt_Key), 112 Words(Cipherkey.Decrypt_Key)); 113 end Prepare_Key128; 114 115 --------------------------------------------------------------------------- 116 117 procedure Prepare_Key192(Key : in B_Block192; 118 Cipherkey : out Cipherkey_AES192) is 119 begin 120 Build_Encrypt_Key(Bytes(Key), Words(Cipherkey.Encrypt_Key), Nk=> Nk192); 121 Build_Decrypt_Key(Words(Cipherkey.Encrypt_Key), 122 Words(Cipherkey.Decrypt_Key)); 123 end Prepare_Key192; 124 125 --------------------------------------------------------------------------- 126 127 procedure Prepare_Key256(Key : in B_Block256; 128 Cipherkey : out Cipherkey_AES256) is 129 begin 130 Build_Encrypt_Key(Bytes(Key), Words(Cipherkey.Encrypt_Key), 131 Nk=> Nk256); 132 Build_Decrypt_Key(Words(Cipherkey.Encrypt_Key), 133 Words(Cipherkey.Decrypt_Key)); 134 end Prepare_Key256; 135 136 ------------------------------------------------------------------------- 137 ------------------------------ENCRYPT------------------------------------ 138 ------------------------------------------------------------------------- 139 140 function Encrypt(Encrypt_Key : in Words; Plaintext : in B_Block128) 141 return B_Block128 is 142 X0, X1, X2, X3 : Word; 143 A0, A1, A2, A3 : Word; 144 Index : Natural := Nb; -- current Encrypt_Key index 145 Ciphertext : B_Block128; 146 Rounds : constant Positive:= Encrypt_Key'Length/Nb-1; 147 begin 148 149 X0 := To_Word(Plaintext(0), Plaintext(1), Plaintext(2), 150 Plaintext(3)) xor Encrypt_Key(0); 151 X1 := To_Word(Plaintext(4), Plaintext(5), Plaintext(6), 152 Plaintext(7)) xor Encrypt_Key(1); 153 X2 := To_Word(Plaintext(8), Plaintext(9), Plaintext(10), 154 Plaintext(11)) xor Encrypt_Key(2); 155 X3 := To_Word(Plaintext(12), Plaintext(13), Plaintext(14), 156 Plaintext(15)) xor Encrypt_Key(3); 157 158 159 160 -- AES with table lookup ("The Rijndael Block Cipher", 161 -- AES Proposal, Document version 2, Date:03/09/99, page 18) 162 for R in 1..Rounds-1 loop 163 A0 := (T1(Byte0(X0)) xor T2(Byte1(X1)) xor T3(Byte2(X2)) xor 164 T4(Byte3(X3))) xor Encrypt_Key(Index); 165 Index := Index+1; 166 A1 := (T1(Byte0(X1)) xor T2(Byte1(X2)) xor T3(Byte2(X3)) xor 167 T4(Byte3(X0))) xor Encrypt_Key(Index); 168 Index := Index+1; 169 A2 := (T1(Byte0(X2)) xor T2(Byte1(X3)) xor T3(Byte2(X0)) xor 170 T4(Byte3(X1))) xor Encrypt_Key(Index); 171 Index := Index+1; 172 A3 := (T1(Byte0(X3)) xor T2(Byte1(X0)) xor T3(Byte2(X1)) xor 173 T4(Byte3(X2))) xor Encrypt_Key(Index); 174 175 Index := Index+1; -- Index := (R+1)*Nb; 176 177 X0 := A0; 178 X1 := A1; 179 X2 := A2; 180 X3 := A3; 181 182 end loop; 183 184 -- Index = Rounds*Nb 185 186 -- last round is special 187 Ciphertext(0) := S(Byte0(X0)) xor Byte0(Encrypt_Key(Index)); 188 Ciphertext(1) := S(Byte1(X1)) xor Byte1(Encrypt_Key(Index)); 189 Ciphertext(2) := S(Byte2(X2)) xor Byte2(Encrypt_Key(Index)); 190 Ciphertext(3) := S(Byte3(X3)) xor Byte3(Encrypt_Key(Index)); 191 192 Index := Index+1; 193 194 Ciphertext(4) := S(Byte0(X1)) xor Byte0(Encrypt_Key(Index)); 195 Ciphertext(5) := S(Byte1(X2)) xor Byte1(Encrypt_Key(Index)); 196 Ciphertext(6) := S(Byte2(X3)) xor Byte2(Encrypt_Key(Index)); 197 Ciphertext(7) := S(Byte3(X0)) xor Byte3(Encrypt_Key(Index)); 198 199 Index := Index+1; 200 201 Ciphertext(8) := S(Byte0(X2)) xor Byte0(Encrypt_Key(Index)); 202 Ciphertext(9) := S(Byte1(X3)) xor Byte1(Encrypt_Key(Index)); 203 Ciphertext(10) := S(Byte2(X0)) xor Byte2(Encrypt_Key(Index)); 204 Ciphertext(11) := S(Byte3(X1)) xor Byte3(Encrypt_Key(Index)); 205 206 Index := Index+1; 207 208 Ciphertext(12) := S(Byte0(X3)) xor Byte0(Encrypt_Key(Index)); 209 Ciphertext(13) := S(Byte1(X0)) xor Byte1(Encrypt_Key(Index)); 210 Ciphertext(14) := S(Byte2(X1)) xor Byte2(Encrypt_Key(Index)); 211 Ciphertext(15) := S(Byte3(X2)) xor Byte3(Encrypt_Key(Index)); 212 213 return Ciphertext; 214 end Encrypt; 215 216 ------------------------------------------------------------------------- 217 ------------------------------------------------------------------------- 218 219 procedure Encrypt128(Cipherkey : in Cipherkey_AES128; 220 Plaintext : in B_Block128; 221 Ciphertext : out B_Block128) is 222 begin 223 Ciphertext := Encrypt(Words(Cipherkey.Encrypt_Key), Plaintext); 224 end Encrypt128; 225 226 ------------------------------------------------------------------------- 227 228 procedure Encrypt192(Cipherkey : in Cipherkey_AES192; 229 Plaintext : in B_Block128; 230 Ciphertext : out B_Block128) is 231 begin 232 Ciphertext := Encrypt(Words(Cipherkey.Encrypt_Key), Plaintext); 233 end Encrypt192; 234 235 ------------------------------------------------------------------------- 236 237 procedure Encrypt256(Cipherkey : in Cipherkey_AES256; 238 Plaintext : in B_Block128; 239 Ciphertext : out B_Block128) is 240 begin 241 Ciphertext := Encrypt(Words(Cipherkey.Encrypt_Key), Plaintext); 242 end Encrypt256; 243 244 245 ------------------------------------------------------------------------- 246 --------------------------DECRYPT---------------------------------------- 247 ------------------------------------------------------------------------- 248 249 function Decrypt(Decrypt_Key : in Words; Ciphertext : B_Block128) 250 return B_Block128 is 251 Rounds : constant Positive := Decrypt_Key'Length/Nb-1; 252 Index : Natural:=Rounds*Nb; -- current Decrypt_Key index 253 A0, A1, A2, A3 : Word; -- working variables 254 X0, X1, X2, X3 : Word; -- working variables 255 Plaintext : B_Block128; 256 begin 257 258 -- ciphertext To B_Block + key 259 X0 := To_Word(Ciphertext(0), Ciphertext(1), Ciphertext(2), 260 Ciphertext(3)) xor Decrypt_Key(Index); 261 Index:= Index+1; -- Index := Rounds*Nb+1; 262 X1 := To_Word(Ciphertext(4), Ciphertext(5), Ciphertext(6), 263 Ciphertext(7)) xor Decrypt_Key(Index); 264 Index:= Index+1; -- Index := Rounds*Nb+2; 265 X2 := To_Word(Ciphertext(8), Ciphertext(9), Ciphertext(10), 266 Ciphertext(11)) xor Decrypt_Key(Index); 267 Index:= Index+1; -- Index := Rounds*Nb+3; 268 X3 := To_Word(Ciphertext(12), Ciphertext(13), Ciphertext(14), 269 Ciphertext(15)) xor Decrypt_Key(Index); 270 271 272 for R in 1..Rounds-1 loop 273 Index:=(Rounds-R)*Nb; 274 275 A0 := (T5(Byte0(X0)) xor T6(Byte1(X3)) xor T7(Byte2(X2)) xor 276 T8(Byte3(X1))) xor Decrypt_Key(Index); 277 278 Index:= Index+1; 279 280 A1 := (T5(Byte0(X1)) xor T6(Byte1(X0)) xor T7(Byte2(X3)) xor 281 T8(Byte3(X2))) xor Decrypt_Key(Index); 282 283 Index:= Index+1; 284 285 A2 := (T5(Byte0(X2)) xor T6(Byte1(X1)) xor T7(Byte2(X0)) xor 286 T8(Byte3(X3))) xor Decrypt_Key(Index); 287 288 Index:= Index+1; 289 290 A3 := (T5(Byte0(X3)) xor T6(Byte1(X2)) xor T7(Byte2(X1)) xor 291 T8(Byte3(X0))) xor Decrypt_Key(Index); 292 293 X0 := A0; 294 X1 := A1; 295 X2 := A2; 296 X3 := A3; 297 298 end loop; 299 300 -- last round is special 301 Plaintext(0) := Si(Byte0(X0)) xor Byte0(Decrypt_Key(0)); 302 Plaintext(1) := Si(Byte1(X3)) xor Byte1(Decrypt_Key(0)); 303 Plaintext(2) := Si(Byte2(X2)) xor Byte2(Decrypt_Key(0)); 304 Plaintext(3) := Si(Byte3(X1)) xor Byte3(Decrypt_Key(0)); 305 306 Plaintext(4) := Si(Byte0(X1)) xor Byte0(Decrypt_Key(1)); 307 Plaintext(5) := Si(Byte1(X0)) xor Byte1(Decrypt_Key(1)); 308 Plaintext(6) := Si(Byte2(X3)) xor Byte2(Decrypt_Key(1)); 309 Plaintext(7) := Si(Byte3(X2)) xor Byte3(Decrypt_Key(1)); 310 311 Plaintext(8) := Si(Byte0(X2)) xor Byte0(Decrypt_Key(2)); 312 Plaintext(9) := Si(Byte1(X1)) xor Byte1(Decrypt_Key(2)); 313 Plaintext(10) := Si(Byte2(X0)) xor Byte2(Decrypt_Key(2)); 314 Plaintext(11) := Si(Byte3(X3)) xor Byte3(Decrypt_Key(2)); 315 316 Plaintext(12) := Si(Byte0(X3)) xor Byte0(Decrypt_Key(3)); 317 Plaintext(13) := Si(Byte1(X2)) xor Byte1(Decrypt_Key(3)); 318 Plaintext(14) := Si(Byte2(X1)) xor Byte2(Decrypt_Key(3)); 319 Plaintext(15) := Si(Byte3(X0)) xor Byte3(Decrypt_Key(3)); 320 321 return Plaintext; 322 end Decrypt; 323 324 ------------------------------------------------------------------------- 325 ------------------------------------------------------------------------- 326 327 procedure Decrypt128(Cipherkey : in Cipherkey_AES128; 328 Ciphertext : in B_Block128; 329 Plaintext : out B_Block128) is 330 begin 331 Plaintext := Decrypt(Words(Cipherkey.Decrypt_Key), Ciphertext); 332 end Decrypt128; 333 334 ------------------------------------------------------------------------- 335 336 procedure Decrypt192(Cipherkey : in Cipherkey_AES192; 337 Ciphertext : in B_Block128; 338 Plaintext : out B_Block128) is 339 begin 340 Plaintext := Decrypt(Words(Cipherkey.Decrypt_Key), Ciphertext); 341 end Decrypt192; 342 343 ------------------------------------------------------------------------- 344 345 procedure Decrypt256(Cipherkey : in Cipherkey_AES256; 346 Ciphertext : in B_Block128; 347 Plaintext : out B_Block128) is 348 begin 349 Plaintext := Decrypt(Words(Cipherkey.Decrypt_Key), Ciphertext); 350 end Decrypt256; 351 352end Crypto.Symmetric.Algorithm.AES; 353