180 lines
5.8 KiB
Ada
180 lines
5.8 KiB
Ada
|
------------------------------------------------------------------------------
|
||
|
-- --
|
||
|
-- GNAT LIBRARY COMPONENTS --
|
||
|
-- --
|
||
|
-- G N A T . S E C U R E _ H A S H E S . S H A 1 --
|
||
|
-- --
|
||
|
-- B o d y --
|
||
|
-- --
|
||
|
-- Copyright (C) 2002-2009, Free Software Foundation, Inc. --
|
||
|
-- --
|
||
|
-- GNAT is free software; you can redistribute it and/or modify it under --
|
||
|
-- terms of the GNU General Public License as published by the Free Soft- --
|
||
|
-- ware Foundation; either version 3, or (at your option) any later ver- --
|
||
|
-- sion. GNAT is distributed in the hope that it will be useful, but WITH- --
|
||
|
-- OUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY --
|
||
|
-- or FITNESS FOR A PARTICULAR PURPOSE. --
|
||
|
-- --
|
||
|
-- As a special exception under Section 7 of GPL version 3, you are granted --
|
||
|
-- additional permissions described in the GCC Runtime Library Exception, --
|
||
|
-- version 3.1, as published by the Free Software Foundation. --
|
||
|
-- --
|
||
|
-- You should have received a copy of the GNU General Public License and --
|
||
|
-- a copy of the GCC Runtime Library Exception along with this program; --
|
||
|
-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see --
|
||
|
-- <http://www.gnu.org/licenses/>. --
|
||
|
-- --
|
||
|
-- GNAT was originally developed by the GNAT team at New York University. --
|
||
|
-- Extensive contributions were provided by Ada Core Technologies Inc. --
|
||
|
-- --
|
||
|
------------------------------------------------------------------------------
|
||
|
|
||
|
package body GNAT.Secure_Hashes.SHA1 is
|
||
|
|
||
|
use Interfaces;
|
||
|
use GNAT.Byte_Swapping;
|
||
|
|
||
|
-- The following functions are the four elementary components of each
|
||
|
-- of the four round groups (0 .. 19, 20 .. 39, 40 .. 59, and 60 .. 79)
|
||
|
-- defined in RFC 3174.
|
||
|
|
||
|
function F0 (B, C, D : Unsigned_32) return Unsigned_32;
|
||
|
pragma Inline (F0);
|
||
|
|
||
|
function F1 (B, C, D : Unsigned_32) return Unsigned_32;
|
||
|
pragma Inline (F1);
|
||
|
|
||
|
function F2 (B, C, D : Unsigned_32) return Unsigned_32;
|
||
|
pragma Inline (F2);
|
||
|
|
||
|
function F3 (B, C, D : Unsigned_32) return Unsigned_32;
|
||
|
pragma Inline (F3);
|
||
|
|
||
|
--------
|
||
|
-- F0 --
|
||
|
--------
|
||
|
|
||
|
function F0
|
||
|
(B, C, D : Interfaces.Unsigned_32) return Interfaces.Unsigned_32
|
||
|
is
|
||
|
begin
|
||
|
return (B and C) or ((not B) and D);
|
||
|
end F0;
|
||
|
|
||
|
--------
|
||
|
-- F1 --
|
||
|
--------
|
||
|
|
||
|
function F1
|
||
|
(B, C, D : Interfaces.Unsigned_32) return Interfaces.Unsigned_32
|
||
|
is
|
||
|
begin
|
||
|
return B xor C xor D;
|
||
|
end F1;
|
||
|
|
||
|
--------
|
||
|
-- F2 --
|
||
|
--------
|
||
|
|
||
|
function F2
|
||
|
(B, C, D : Interfaces.Unsigned_32) return Interfaces.Unsigned_32
|
||
|
is
|
||
|
begin
|
||
|
return (B and C) or (B and D) or (C and D);
|
||
|
end F2;
|
||
|
|
||
|
--------
|
||
|
-- F3 --
|
||
|
--------
|
||
|
|
||
|
function F3
|
||
|
(B, C, D : Interfaces.Unsigned_32) return Interfaces.Unsigned_32
|
||
|
renames F1;
|
||
|
|
||
|
---------------
|
||
|
-- Transform --
|
||
|
---------------
|
||
|
|
||
|
procedure Transform
|
||
|
(H : in out Hash_State.State;
|
||
|
M : in out Message_State)
|
||
|
is
|
||
|
use System;
|
||
|
|
||
|
type Words is array (Natural range <>) of Interfaces.Unsigned_32;
|
||
|
|
||
|
X : Words (0 .. 15);
|
||
|
for X'Address use M.Buffer'Address;
|
||
|
pragma Import (Ada, X);
|
||
|
|
||
|
W : Words (0 .. 79);
|
||
|
|
||
|
A, B, C, D, E, Temp : Interfaces.Unsigned_32;
|
||
|
|
||
|
begin
|
||
|
if Default_Bit_Order /= High_Order_First then
|
||
|
for J in X'Range loop
|
||
|
Swap4 (X (J)'Address);
|
||
|
end loop;
|
||
|
end if;
|
||
|
|
||
|
-- a. Divide data block into sixteen words
|
||
|
|
||
|
W (0 .. 15) := X;
|
||
|
|
||
|
-- b. Prepare working block of 80 words
|
||
|
|
||
|
for T in 16 .. 79 loop
|
||
|
|
||
|
-- W(t) = S^1(W(t-3) XOR W(t-8) XOR W(t-14) XOR W(t-16))
|
||
|
|
||
|
W (T) := Rotate_Left
|
||
|
(W (T - 3) xor W (T - 8) xor W (T - 14) xor W (T - 16), 1);
|
||
|
|
||
|
end loop;
|
||
|
|
||
|
-- c. Set up transformation variables
|
||
|
|
||
|
A := H (0);
|
||
|
B := H (1);
|
||
|
C := H (2);
|
||
|
D := H (3);
|
||
|
E := H (4);
|
||
|
|
||
|
-- d. For each of the 80 rounds, compute:
|
||
|
|
||
|
-- TEMP = S^5(A) + f(t;B,C,D) + E + W(t) + K(t);
|
||
|
-- E = D; D = C; C = S^30(B); B = A; A = TEMP;
|
||
|
|
||
|
for T in 0 .. 19 loop
|
||
|
Temp := Rotate_Left (A, 5) + F0 (B, C, D) + E + W (T) + 16#5A827999#;
|
||
|
E := D; D := C; C := Rotate_Left (B, 30); B := A; A := Temp;
|
||
|
end loop;
|
||
|
|
||
|
for T in 20 .. 39 loop
|
||
|
Temp := Rotate_Left (A, 5) + F1 (B, C, D) + E + W (T) + 16#6ED9EBA1#;
|
||
|
E := D; D := C; C := Rotate_Left (B, 30); B := A; A := Temp;
|
||
|
end loop;
|
||
|
|
||
|
for T in 40 .. 59 loop
|
||
|
Temp := Rotate_Left (A, 5) + F2 (B, C, D) + E + W (T) + 16#8F1BBCDC#;
|
||
|
E := D; D := C; C := Rotate_Left (B, 30); B := A; A := Temp;
|
||
|
end loop;
|
||
|
|
||
|
for T in 60 .. 79 loop
|
||
|
Temp := Rotate_Left (A, 5) + F3 (B, C, D) + E + W (T) + 16#CA62C1D6#;
|
||
|
E := D; D := C; C := Rotate_Left (B, 30); B := A; A := Temp;
|
||
|
end loop;
|
||
|
|
||
|
-- e. Update context:
|
||
|
-- H0 = H0 + A, H1 = H1 + B, H2 = H2 + C, H3 = H3 + D, H4 = H4 + E
|
||
|
|
||
|
H (0) := H (0) + A;
|
||
|
H (1) := H (1) + B;
|
||
|
H (2) := H (2) + C;
|
||
|
H (3) := H (3) + D;
|
||
|
H (4) := H (4) + E;
|
||
|
end Transform;
|
||
|
|
||
|
end GNAT.Secure_Hashes.SHA1;
|