1------------------------------------------------------------------------------ 2-- -- 3-- GNAT LIBRARY COMPONENTS -- 4-- -- 5-- G N A T . S E C U R E _ H A S H E S . S H A 1 -- 6-- -- 7-- B o d y -- 8-- -- 9-- Copyright (C) 2002-2009, Free Software Foundation, Inc. -- 10-- -- 11-- GNAT is free software; you can redistribute it and/or modify it under -- 12-- terms of the GNU General Public License as published by the Free Soft- -- 13-- ware Foundation; either version 3, or (at your option) any later ver- -- 14-- sion. GNAT is distributed in the hope that it will be useful, but WITH- -- 15-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY -- 16-- or FITNESS FOR A PARTICULAR PURPOSE. -- 17-- -- 18-- As a special exception under Section 7 of GPL version 3, you are granted -- 19-- additional permissions described in the GCC Runtime Library Exception, -- 20-- version 3.1, as published by the Free Software Foundation. -- 21-- -- 22-- You should have received a copy of the GNU General Public License and -- 23-- a copy of the GCC Runtime Library Exception along with this program; -- 24-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- 25-- <http://www.gnu.org/licenses/>. -- 26-- -- 27-- GNAT was originally developed by the GNAT team at New York University. -- 28-- Extensive contributions were provided by Ada Core Technologies Inc. -- 29-- -- 30------------------------------------------------------------------------------ 31 32package body GNAT.Secure_Hashes.SHA1 is 33 34 use Interfaces; 35 use GNAT.Byte_Swapping; 36 37 -- The following functions are the four elementary components of each 38 -- of the four round groups (0 .. 19, 20 .. 39, 40 .. 59, and 60 .. 79) 39 -- defined in RFC 3174. 40 41 function F0 (B, C, D : Unsigned_32) return Unsigned_32; 42 pragma Inline (F0); 43 44 function F1 (B, C, D : Unsigned_32) return Unsigned_32; 45 pragma Inline (F1); 46 47 function F2 (B, C, D : Unsigned_32) return Unsigned_32; 48 pragma Inline (F2); 49 50 function F3 (B, C, D : Unsigned_32) return Unsigned_32; 51 pragma Inline (F3); 52 53 -------- 54 -- F0 -- 55 -------- 56 57 function F0 58 (B, C, D : Interfaces.Unsigned_32) return Interfaces.Unsigned_32 59 is 60 begin 61 return (B and C) or ((not B) and D); 62 end F0; 63 64 -------- 65 -- F1 -- 66 -------- 67 68 function F1 69 (B, C, D : Interfaces.Unsigned_32) return Interfaces.Unsigned_32 70 is 71 begin 72 return B xor C xor D; 73 end F1; 74 75 -------- 76 -- F2 -- 77 -------- 78 79 function F2 80 (B, C, D : Interfaces.Unsigned_32) return Interfaces.Unsigned_32 81 is 82 begin 83 return (B and C) or (B and D) or (C and D); 84 end F2; 85 86 -------- 87 -- F3 -- 88 -------- 89 90 function F3 91 (B, C, D : Interfaces.Unsigned_32) return Interfaces.Unsigned_32 92 renames F1; 93 94 --------------- 95 -- Transform -- 96 --------------- 97 98 procedure Transform 99 (H : in out Hash_State.State; 100 M : in out Message_State) 101 is 102 use System; 103 104 type Words is array (Natural range <>) of Interfaces.Unsigned_32; 105 106 X : Words (0 .. 15); 107 for X'Address use M.Buffer'Address; 108 pragma Import (Ada, X); 109 110 W : Words (0 .. 79); 111 112 A, B, C, D, E, Temp : Interfaces.Unsigned_32; 113 114 begin 115 if Default_Bit_Order /= High_Order_First then 116 for J in X'Range loop 117 Swap4 (X (J)'Address); 118 end loop; 119 end if; 120 121 -- a. Divide data block into sixteen words 122 123 W (0 .. 15) := X; 124 125 -- b. Prepare working block of 80 words 126 127 for T in 16 .. 79 loop 128 129 -- W(t) = S^1(W(t-3) XOR W(t-8) XOR W(t-14) XOR W(t-16)) 130 131 W (T) := Rotate_Left 132 (W (T - 3) xor W (T - 8) xor W (T - 14) xor W (T - 16), 1); 133 134 end loop; 135 136 -- c. Set up transformation variables 137 138 A := H (0); 139 B := H (1); 140 C := H (2); 141 D := H (3); 142 E := H (4); 143 144 -- d. For each of the 80 rounds, compute: 145 146 -- TEMP = S^5(A) + f(t;B,C,D) + E + W(t) + K(t); 147 -- E = D; D = C; C = S^30(B); B = A; A = TEMP; 148 149 for T in 0 .. 19 loop 150 Temp := Rotate_Left (A, 5) + F0 (B, C, D) + E + W (T) + 16#5A827999#; 151 E := D; D := C; C := Rotate_Left (B, 30); B := A; A := Temp; 152 end loop; 153 154 for T in 20 .. 39 loop 155 Temp := Rotate_Left (A, 5) + F1 (B, C, D) + E + W (T) + 16#6ED9EBA1#; 156 E := D; D := C; C := Rotate_Left (B, 30); B := A; A := Temp; 157 end loop; 158 159 for T in 40 .. 59 loop 160 Temp := Rotate_Left (A, 5) + F2 (B, C, D) + E + W (T) + 16#8F1BBCDC#; 161 E := D; D := C; C := Rotate_Left (B, 30); B := A; A := Temp; 162 end loop; 163 164 for T in 60 .. 79 loop 165 Temp := Rotate_Left (A, 5) + F3 (B, C, D) + E + W (T) + 16#CA62C1D6#; 166 E := D; D := C; C := Rotate_Left (B, 30); B := A; A := Temp; 167 end loop; 168 169 -- e. Update context: 170 -- H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E 171 172 H (0) := H (0) + A; 173 H (1) := H (1) + B; 174 H (2) := H (2) + C; 175 H (3) := H (3) + D; 176 H (4) := H (4) + E; 177 end Transform; 178 179end GNAT.Secure_Hashes.SHA1; 180