aboutsummaryrefslogtreecommitdiff
path: root/gcc/ada/g-sechas.adb
diff options
context:
space:
mode:
authorArnaud Charlet <charlet@gcc.gnu.org>2014-08-04 14:47:56 +0200
committerArnaud Charlet <charlet@gcc.gnu.org>2014-08-04 14:47:56 +0200
commit4ff2b6dcc98d42fb75c4491ab3871cef10857ebf (patch)
treef3848bfb928022bf983a63f33a0f1da48ac0aa85 /gcc/ada/g-sechas.adb
parente72a92e447fc0d13a6744e4d4a5e2c50c8515f79 (diff)
downloadgcc-4ff2b6dcc98d42fb75c4491ab3871cef10857ebf.zip
gcc-4ff2b6dcc98d42fb75c4491ab3871cef10857ebf.tar.gz
gcc-4ff2b6dcc98d42fb75c4491ab3871cef10857ebf.tar.bz2
[multiple changes]
2014-08-04 Robert Dewar <dewar@adacore.com> * sem_prag.adb, osint.adb, osint.ads: Minor reformatting. 2014-08-04 Yannick Moy <moy@adacore.com> * sem_ch3.adb (Derive_Type_Declaration, Process_Discriminants): Remove SPARK-specific legality checks. 2014-08-04 Thomas Quinot <quinot@adacore.com> * g-sechas.ads, g-sechas.adb (HMAC_Initial_Context): New subprogram. * gnat_rm.texi (GNAT.MD5/SHA1/SHA224/SHA256/SHA512): Document support for HMAC. From-SVN: r213577
Diffstat (limited to 'gcc/ada/g-sechas.adb')
-rw-r--r--gcc/ada/g-sechas.adb74
1 files changed, 70 insertions, 4 deletions
diff --git a/gcc/ada/g-sechas.adb b/gcc/ada/g-sechas.adb
index 4b396f1..0e70b5d 100644
--- a/gcc/ada/g-sechas.adb
+++ b/gcc/ada/g-sechas.adb
@@ -6,7 +6,7 @@
-- --
-- B o d y --
-- --
--- Copyright (C) 2009-2012, Free Software Foundation, Inc. --
+-- Copyright (C) 2009-2014, 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- --
@@ -218,8 +218,8 @@ package body GNAT.Secure_Hashes is
-- the message size in bits (excluding padding).
procedure Final
- (C : Context;
- Hash_Bits : out Stream_Element_Array)
+ (C : Context;
+ Hash_Bits : out Stream_Element_Array)
is
FC : Context := C;
@@ -274,8 +274,73 @@ package body GNAT.Secure_Hashes is
pragma Assert (FC.M_State.Last = 0);
Hash_State.To_Hash (FC.H_State, Hash_Bits);
+
+ -- HMAC case: hash outer pad
+
+ if C.KL /= 0 then
+ declare
+ Outer_C : Context;
+ Opad : Stream_Element_Array :=
+ (1 .. Stream_Element_Offset (Block_Length) => 16#5c#);
+
+ begin
+ for J in C.Key'Range loop
+ Opad (J) := Opad (J) xor C.Key (J);
+ end loop;
+
+ Update (Outer_C, Opad);
+ Update (Outer_C, Hash_Bits);
+
+ Final (Outer_C, Hash_Bits);
+ end;
+ end if;
end Final;
+ --------------------------
+ -- HMAC_Initial_Context --
+ --------------------------
+
+ function HMAC_Initial_Context (Key : String) return Context is
+ begin
+ if Key'Length = 0 then
+ raise Constraint_Error with "null key";
+ end if;
+
+ return C : Context (KL => (if Key'Length <= Key_Length'Last
+ then Key'Length
+ else Stream_Element_Offset (Hash_Length)))
+ do
+ -- Set Key (if longer than block length, first hash it)
+
+ if C.KL = Key'Length then
+ declare
+ SK : String (1 .. Key'Length);
+ for SK'Address use C.Key'Address;
+ pragma Import (Ada, SK);
+ begin
+ SK := Key;
+ end;
+
+ else
+ C.Key := Digest (Key);
+ end if;
+
+ -- Hash inner pad
+
+ declare
+ Ipad : Stream_Element_Array :=
+ (1 .. Stream_Element_Offset (Block_Length) => 16#36#);
+
+ begin
+ for J in C.Key'Range loop
+ Ipad (J) := Ipad (J) xor C.Key (J);
+ end loop;
+
+ Update (C, Ipad);
+ end;
+ end return;
+ end HMAC_Initial_Context;
+
------------
-- Update --
------------
@@ -285,11 +350,12 @@ package body GNAT.Secure_Hashes is
S : String;
Fill_Buffer : Fill_Buffer_Access)
is
- Last : Natural := S'First - 1;
+ Last : Natural;
begin
C.M_State.Length := C.M_State.Length + S'Length;
+ Last := S'First - 1;
while Last < S'Last loop
Fill_Buffer (C.M_State, S, Last + 1, Last);