bug-fix for SHA2 + Tests for SHA2

This commit is contained in:
bg nerilex 2015-07-10 11:32:32 +02:00
parent ea6bac4994
commit 17e50a5281
13 changed files with 534 additions and 32 deletions

View File

@ -24,6 +24,12 @@ package SHA2_224 is
type Context_T is private;
BlockSize_Bits : constant := 512;
DigestSize_Bits : constant := 224;
BlockSize_Bytes : constant := (BlockSize_Bits) / 8;
DigestSize_Bytes : constant := (DigestSize_Bits) / 8;
procedure Initialize(Context : out Context_T);
procedure Next_Block(Context : in out Context_T; Block : in Block_512_Bit);
procedure Last_Block(Context : in out Context_T; Block : in u8_Array; Bits : in Integer := -1);

View File

@ -24,12 +24,21 @@ package SHA2_256 is
type Context_T is private;
procedure Initialize(Context : out Context_T);
procedure Next_Block(Context : in out Context_T; Block : in Block_512_Bit);
procedure Last_Block(Context : in out Context_T; Block : in u8_Array; Bits : in Integer := -1);
procedure Get_Digest(Context : in out Context_T; Digest : out Block_256_Bit);
BlockSize_Bits : constant := 512;
DigestSize_Bits : constant := 256;
procedure Hash(Data : in u8_array; Digest : out Block_256_Bit; Bits : in Integer := -1);
BlockSize_Bytes : constant := (BlockSize_Bits) / 8;
DigestSize_Bytes : constant := (DigestSize_Bits) / 8;
subtype Block_T is u8_Array(1 .. BlockSize_Bytes);
subtype Digest_T is u8_Array(1 .. DigestSize_Bytes);
procedure Initialize(Context : out Context_T);
procedure Next_Block(Context : in out Context_T; Block : in Block_T);
procedure Last_Block(Context : in out Context_T; Block : in u8_Array; Bits : in Integer := -1);
procedure Get_Digest(Context : in out Context_T; Digest : out Digest_T);
procedure Hash(Data : in u8_array; Digest : out Digest_T; Bits : in Integer := -1);
private

View File

@ -24,6 +24,12 @@ package SHA2_384 is
type Context_T is private;
BlockSize_Bits : constant := 1024;
DigestSize_Bits : constant := 384;
BlockSize_Bytes : constant := (BlockSize_Bits) / 8;
DigestSize_Bytes : constant := (DigestSize_Bits) / 8;
procedure Initialize(Context : out Context_T);
procedure Next_Block(Context : in out Context_T; Block : in Block_1024_Bit);
procedure Last_Block(Context : in out Context_T; Block : in u8_Array; Bits : in Integer := -1);

View File

@ -24,6 +24,12 @@ package SHA2_512 is
type Context_T is private;
BlockSize_Bits : constant := 1024;
DigestSize_Bits : constant := 512;
BlockSize_Bytes : constant := (BlockSize_Bits) / 8;
DigestSize_Bytes : constant := (DigestSize_Bits) / 8;
procedure Initialize(Context : out Context_T);
procedure Next_Block(Context : in out Context_T; Block : in Block_1024_Bit);
procedure Last_Block(Context : in out Context_T; Block : in u8_Array; Bits : in Integer := -1);

View File

@ -111,8 +111,8 @@ package body SHA2_Large is
r := (s + 7) / 8;
b(1 .. r) := Block(i .. i + r - 1);
b(1 + s / 8) := b(1 + s / 8) or Shift_Right(u8(16#80#), s mod 8);
r := r + 1;
if r > 128 - 16 then
s := s + 1;
if s > 1024 - 128 then
Next_Block(Context, b);
b := (others => 0);
end if;

View File

@ -99,8 +99,8 @@ package body SHA2_Small is
r := (s + 7) / 8;
b(1 .. r) := Block(i .. i + r - 1);
b(1 + s / 8) := b(1 + s / 8) or Shift_Right(u8(16#80#), s mod 8);
r := r + 1;
if r > 64 - 8 then
s := s + 1;
if s > 512 - 64 then
Next_Block(Context, b);
b := (others => 0);
end if;

115
src/crypto_core_types.adb Normal file
View File

@ -0,0 +1,115 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
package body Crypto_Core_Types is
function To_Hex(A : u8) return String is
S : String(1 .. 2);
Hex_Table : constant array (0 .. 15) of Character :=
( '0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f');
begin
S(1) := Hex_Table(Integer(Shift_Right(A, 4)));
S(2) := Hex_Table(Integer(A and 16#0f#));
return S;
end To_Hex;
function To_Hex(A : u8_Array) return String is
S : String(1 .. A'Length * 2);
k : Positive := 1;
begin
for i in A'Range loop
S(k .. k + 1) := To_Hex(A(i));
k := k + 2;
end loop;
return S;
end To_Hex;
function Get_Hex_Value(C : Character) return Integer is
r : Integer;
begin
case C is
when '0' => r := 0;
when '1' => r := 1;
when '2' => r := 2;
when '3' => r := 3;
when '4' => r := 4;
when '5' => r := 5;
when '6' => r := 6;
when '7' => r := 7;
when '8' => r := 8;
when '9' => r := 9;
when 'A' => r := 10;
when 'a' => r := 10;
when 'B' => r := 11;
when 'b' => r := 11;
when 'C' => r := 12;
when 'c' => r := 12;
when 'D' => r := 13;
when 'd' => r := 13;
when 'E' => r := 14;
when 'e' => r := 14;
when 'F' => r := 15;
when 'f' => r := 15;
when others => r:= -1;
end case;
return r;
end;
function From_Hex(S : String) return u8_Array is
A : u8_Array(1 .. (S'Length + 1) / 2);
C : Character;
V : Integer range -1 .. 15;
Index : Positive := 1;
Inside : Boolean := False;
begin
for i in S'Range loop
C := S(i);
if C /= ' ' and then C /= '_' then
V := Get_Hex_Value(C);
if V = -1 then
raise Format_Violation;
else
if Inside then
A(Index) := A(Index) or u8(V);
Inside := False;
Index := Index + 1;
else
A(Index) := Shift_Left(u8(V), 4);
Inside := True;
end if;
end if;
end if;
end loop;
return A;
end From_Hex;
function From_Ascii(S : String) return u8_Array is
A : u8_Array(1 .. S'Length);
Index : Integer := 1;
begin
for i in S'Range loop
A(Index) := u8(Character'Pos(S(i)));
Index := INdex + 1;
end loop;
return A;
end From_Ascii;
end Crypto_Core_types;

View File

@ -55,5 +55,10 @@ package Crypto_Core_Types is
subtype Block_2084_Bit is u8_Array(1 .. 2048 / 8);
Wrong_Opertaion_Order : exception;
Format_Violation : exception;
function To_Hex(A : u8_Array) return String;
function From_Hex(S : String) return u8_Array;
function From_Ascii(S : String) return u8_Array;
end Crypto_Core_Types;

219
src/tests/sha_test_io.adb Normal file
View File

@ -0,0 +1,219 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
--
-- # CAVS 11.0
-- # "SHA-256 ShortMsg" information
-- # SHA-256 tests are configured for BIT oriented implementations
-- # Generated on Tue Mar 15 08:29:11 2011
--
-- [L = 32]
--
-- Len = 0
-- Msg = 00
-- MD = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
--
-- Len = 1
-- Msg = 00
-- MD = bd4f9e98beb68c6ead3243b1b4c7fed75fa4feaab1f84795cbd8a98676a2a375
--
-- Len = 2
-- Msg = 80
-- MD = 18f331f626210ff9bad6995d8cff6e891adba50eb2fdbddcaa921221cdc333ae
--
-- Len = 3
-- Msg = 60
-- MD = 1f7794d4b0b67d3a6edcd17aba2144a95828032f7943ed26bf0c7c7628945f48
--
package body Sha_Test_IO is
procedure Open(Context : out Context_T; FileName : in String) is
begin
Open(Context.File, In_File, FileName);
end Open;
procedure Goto_Data(F : in out File_Type) is
C : Character;
After_Equal : boolean := false;
Ignored : boolean;
begin
loop
exit when End_Of_File(F);
if After_Equal then
Look_Ahead(F, C, ignored);
case C is
when '0' .. '9' => exit;
when 'A' .. 'F' => exit;
when 'a' .. 'f' => exit;
when others => null;
end case;
end if;
Get(F, C);
if C = '=' then
After_Equal := true;
end if;
end loop;
end Goto_Data;
procedure Get_Next_Type(Context : in out Context_T; Next : out Next_Type) is
C : Character;
begin
loop
exit when End_Of_File(Context.File);
Get(Context.File, C);
exit when End_Of_File(Context.File);
case C is
when '#' => Skip_Line(Context.File);
when '[' => exit;
when 'L' => exit;
when 'C' => exit;
when 'S' => Get(Context.File, C); exit;
when 'M' => Get(Context.File, C); exit;
when others => null;
end case;
end loop;
Goto_Data(Context.File);
if End_Of_File(Context.File) then
Close(Context.File);
Next := Finish;
else
case C is
when '[' => Next := Digest_Length;
when 'L' => Next := Message_Length;
when 'e' => Next := Seed; -- second char from "Seed"
when 'C' => Next := Count;
when 's' => Next := Message_Block; -- second char from "Msg"
when 'D' => Next := Message_Digest; -- second char from "MD"
when others => raise Format_Violation;
end case;
end if;
end Get_Next_type;
procedure Get_Integer(Context : in out Context_T; Value : out Integer) is
begin
Get(Context.File, Value);
end Get_Integer;
procedure Get_Data(Context : in out Context_T; Block : out u8_Array) is
L,P : Natural := 0;
I : Integer := Block'First;
S : String(1 .. 80);
begin
L := Block'Length * 2;
loop
if L > S'Length then
P := S'Length;
else
P := L;
end if;
Get(Context.File, S(1 .. P));
Block(I .. I + P / 2 - 1) := From_Hex(S(1 .. P));
L := L - P;
I := I + P / 2;
if L = 0 or End_Of_File(Context.File) then
exit;
end if;
end loop;
end Get_Data;
procedure Test_With_File(FileName : in String) is
f : Context_T;
nt : Next_Type;
count_val : Integer;
dlen : Integer;
len, lenb : Integer;
DigestSize_Bytes : constant Natural := (DigestSize_Bits + 7 ) / 8;
digest, ref_Digest : u8_Array(1 .. DigestSize_Bytes) := (others => 0);
ok_test, fail_test, num : Natural := 0;
seed_val : u8_Array(1 .. DigestSize_Bytes) := (others => 0);
begin
New_Line;
Put("== " & FileName &" ==");
Open(f, FileName);
loop
Get_Next_Type(f, nt);
case nt is
when Sha_Test_IO.Finish =>
New_Line;
Put(" (ok: " & Integer'Image(ok_test) & " / fail: " & Integer'Image(fail_test) & ")");
New_Line;
exit;
when Digest_Length =>
Get_Integer(f, dlen);
when Seed =>
Get_Data(f, Seed_Val);
when Count =>
Get_Integer(f, count_val);
if num mod 64 = 0 then
New_Line;
Put(" ");
Put(Item => num, Width => 6);
Put(" : ");
end if;
num := num + 1;
declare
blob : u8_Array(1 .. 3 * DigestSize_Bytes);
begin
blob(1 + 0 * DigestSize_Bytes .. 1 * DigestSize_Bytes) := Seed_Val;
blob(1 + 1 * DigestSize_Bytes .. 2 * DigestSize_Bytes) := Seed_Val;
blob(1 + 2 * DigestSize_Bytes .. 3 * DigestSize_Bytes) := Seed_Val;
for i in 1 .. 1000 loop
Hash(blob, Digest);
blob(1 .. 2 * DigestSize_Bytes) := blob(1 + 1 * DigestSize_Bytes .. 3 * DigestSize_Bytes);
blob(1 + 2 * DigestSize_Bytes .. 3 * DigestSize_Bytes) := Digest;
end loop;
Seed_Val := Digest;
end;
when Message_Length =>
Get_Integer(f, len);
if len = 0 then
lenb := 1;
else
lenb := (len + 7) / 8;
end if;
when Message_Digest =>
Get_Data(f, ref_digest(1 .. dlen));
if ref_digest = digest then
ok_test := ok_test + 1;
Put('*');
else
fail_test := fail_test + 1;
Put('!');
end if;
when Message_Block =>
declare
buf : u8_Array(1 .. lenb);
begin
if num mod 64 = 0 then
New_Line;
Put(" ");
Put(Item => num, Width => 6);
Put(" : ");
end if;
num := num + 1;
Get_Data(f, buf);
Hash(buf, digest(1 .. dlen), len);
end;
end case;
end loop;
end;
end Sha_Test_IO;

69
src/tests/sha_test_io.ads Normal file
View File

@ -0,0 +1,69 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Ada.Text_IO; use Ada.Text_IO;
with Crypto_Core_Types; use Crypto_Core_Types;
--
-- # CAVS 11.0
-- # "SHA-256 ShortMsg" information
-- # SHA-256 tests are configured for BIT oriented implementations
-- # Generated on Tue Mar 15 08:29:11 2011
--
-- [L = 32]
--
-- Len = 0
-- Msg = 00
-- MD = e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855
--
-- Len = 1
-- Msg = 00
-- MD = bd4f9e98beb68c6ead3243b1b4c7fed75fa4feaab1f84795cbd8a98676a2a375
--
-- Len = 2
-- Msg = 80
-- MD = 18f331f626210ff9bad6995d8cff6e891adba50eb2fdbddcaa921221cdc333ae
--
-- Len = 3
-- Msg = 60
-- MD = 1f7794d4b0b67d3a6edcd17aba2144a95828032f7943ed26bf0c7c7628945f48
--
package Sha_Test_IO is
type Next_Type is (Digest_Length, Message_Length, Message_Block, Message_Digest, Seed, Count, Finish);
type Context_T is limited private;
procedure Open(Context : out Context_T; FileName : in String);
procedure Get_Next_Type(Context : in out Context_T; next : out Next_Type);
procedure Get_Integer(Context : in out Context_T; Value : out Integer);
procedure Get_Data(Context : in out Context_T; Block : out u8_Array);
generic
-- type Context_T is limited private;
-- BlockSize_Bits : Natural;
DigestSize_Bits : Natural;
with procedure Hash(Data : in u8_Array; Digest : out u8_Array; Bits : in Integer := -1);
procedure Test_With_File(FileName : in String);
private
type Context_T is record
File : File_Type;
end record;
end Sha_Test_IO;

72
src/tests/test_sha2.adb Normal file
View File

@ -0,0 +1,72 @@
-- Copyright (C) 2015 Daniel Otte <bg@nerilex.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Ada.Text_IO; use Ada.Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Crypto_Core_Types; use Crypto_Core_Types;
with Crypto_Types; use Crypto_Types;
with Sha_Test_IO;
with SHA2_224;
with SHA2_256;
with SHA2_384;
with SHA2_512;
use Crypto_Types.Crypto_Types_u8;
procedure Test_SHA2 is
procedure test_sha224_with_File is new Sha_Test_IO.Test_With_File(DigestSize_Bits => SHA2_224.DigestSize_Bits, Hash => SHA2_224.Hash);
procedure test_sha256_with_File is new Sha_Test_IO.Test_With_File(DigestSize_Bits => SHA2_256.DigestSize_Bits, Hash => SHA2_256.Hash);
procedure test_sha384_with_File is new Sha_Test_IO.Test_With_File(DigestSize_Bits => SHA2_384.DigestSize_Bits, Hash => SHA2_384.Hash);
procedure test_sha512_with_File is new Sha_Test_IO.Test_With_File(DigestSize_Bits => SHA2_512.DigestSize_Bits, Hash => SHA2_512.Hash);
begin
New_Line;
test_sha224_with_File("testvectors/sha2/bit/SHA224ShortMsg.rsp");
test_sha224_with_File("testvectors/sha2/bit/SHA224LongMsg.rsp");
test_sha224_with_File("testvectors/sha2/bit/SHA224Monte.rsp");
test_sha224_with_File("testvectors/sha2/byte/SHA224ShortMsg.rsp");
test_sha224_with_File("testvectors/sha2/byte/SHA224LongMsg.rsp");
test_sha224_with_File("testvectors/sha2/byte/SHA224Monte.rsp");
New_Line;
test_sha256_with_File("testvectors/sha2/bit/SHA256ShortMsg.rsp");
test_sha256_with_File("testvectors/sha2/bit/SHA256LongMsg.rsp");
test_sha256_with_File("testvectors/sha2/bit/SHA256Monte.rsp");
test_sha256_with_File("testvectors/sha2/byte/SHA256ShortMsg.rsp");
test_sha256_with_File("testvectors/sha2/byte/SHA256LongMsg.rsp");
test_sha256_with_File("testvectors/sha2/byte/SHA256Monte.rsp");
New_Line;
test_sha384_with_File("testvectors/sha2/bit/SHA384ShortMsg.rsp");
test_sha384_with_File("testvectors/sha2/bit/SHA384LongMsg.rsp");
test_sha384_with_File("testvectors/sha2/bit/SHA384Monte.rsp");
test_sha384_with_File("testvectors/sha2/byte/SHA384ShortMsg.rsp");
test_sha384_with_File("testvectors/sha2/byte/SHA384LongMsg.rsp");
test_sha384_with_File("testvectors/sha2/byte/SHA384Monte.rsp");
New_Line;
test_sha512_with_File("testvectors/sha2/bit/SHA512ShortMsg.rsp");
test_sha512_with_File("testvectors/sha2/bit/SHA512LongMsg.rsp");
test_sha512_with_File("testvectors/sha2/bit/SHA512Monte.rsp");
test_sha512_with_File("testvectors/sha2/byte/SHA512ShortMsg.rsp");
test_sha512_with_File("testvectors/sha2/byte/SHA512LongMsg.rsp");
test_sha512_with_File("testvectors/sha2/byte/SHA512Monte.rsp");
New_Line;
end Test_SHA2;

View File

@ -14,10 +14,11 @@
-- along with this program. If not, see <http://www.gnu.org/licenses/>.
with Ada.Text_IO; use Ada.Text_IO;
-- with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
with Crypto_Core_Types; use Crypto_Core_Types;
with Crypto_Types; use Crypto_Types;
with Sha_Test_IO;
with SHA2_256;
use Crypto_Types.Crypto_Types_u8;
@ -25,23 +26,10 @@ use Crypto_Types.Crypto_Types_u8;
procedure main is
-- package u8_IO is new Crypto_Types.u8_Sequential_IO;
procedure Print_Hex(value : in u8) is
hex_table : constant array (0 .. 15) of Character :=
( '0', '1', '2', '3',
'4', '5', '6', '7',
'8', '9', 'a', 'b',
'c', 'd', 'e', 'f');
begin
Put(hex_table(Integer(Shift_Right(value, 4))));
Put(hex_table(Integer(value and 16#F#)));
end;
procedure Print_Hex(value : in u8_Array) is
begin
for i in value'Range loop
print_hex(value(i));
Put(" ");
end loop;
Put(To_Hex(value));
Put(" ");
end;
@ -70,13 +58,20 @@ procedure main is
New_Line;
end test_sha256;
a : u8_Array(1 .. 12);
procedure test_sha256_with_File is new Sha_Test_IO.Test_With_File(DigestSize_Bits => SHA2_256.DigestSize_Bits, Hash => SHA2_256.Hash);
begin
Put_Line("SHA2_256.Context_T'Size: " & Integer'Image(SHA2_256.Context_T'Size / 8));
test_sha256("");
a(1) := 16#80#;
test_sha256(a(1..1), 2);
test_sha256("abc");
test_sha256("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
-- test_sha256("");
-- a(1) := 16#80#;
-- test_sha256(a(1..1), 2);
-- test_sha256("abc");
-- test_sha256("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq");
New_Line;
test_sha256_with_File("testvectors/sha2/bit/SHA256ShortMsg.rsp");
test_sha256_with_File("testvectors/sha2/bit/SHA256LongMsg.rsp");
test_sha256_with_File("testvectors/sha2/bit/SHA256Monte.rsp");
test_sha256_with_File("testvectors/sha2/byte/SHA256ShortMsg.rsp");
test_sha256_with_File("testvectors/sha2/byte/SHA256LongMsg.rsp");
test_sha256_with_File("testvectors/sha2/byte/SHA256Monte.rsp");
end main;

View File

@ -3,7 +3,7 @@ project Steelcrypt is
type Build_Modes is
("Release", "Debug");
Mode : Build_Modes := external ("BUILD", "Debug");
for Main use ("main.adb", "test_sha224.adb", "test_sha256.adb", "test_sha384.adb", "test_sha512.adb");
for Main use ("main.adb", "test_sha2.adb", "test_sha224.adb", "test_sha256.adb", "test_sha384.adb", "test_sha512.adb");
case Mode is