1 ------------------------------------------------------------------------------
3 -- GNAT LIBRARY COMPONENTS --
5 -- G N A T . S E C U R E _ H A S H E S --
9 -- Copyright (C) 2009-2017, Free Software Foundation, Inc. --
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. --
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. --
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/>. --
27 -- GNAT was originally developed by the GNAT team at New York University. --
28 -- Extensive contributions were provided by Ada Core Technologies Inc. --
30 ------------------------------------------------------------------------------
32 -- This package provides common supporting code for a family of secure
33 -- hash functions (including MD5 and the FIPS PUB 180-3 functions SHA-1,
34 -- SHA-224, SHA-256, SHA-384 and SHA-512).
36 -- This is an internal unit and should be not used directly in applications.
37 -- Use GNAT.MD5 and GNAT.SHA* instead.
39 with Ada
.Streams
; use Ada
.Streams
;
45 package GNAT
.Secure_Hashes
is
47 type Buffer_Type
is new String;
48 for Buffer_Type
'Alignment use 8;
49 -- Secure hash functions use a string buffer that is also accessed as an
50 -- array of words, which may require up to 64 bit alignment.
52 -- The function-independent part of processing state: A buffer of data
53 -- being accumulated until a complete block is ready for hashing.
55 type Message_State
(Block_Length
: Natural) is record
57 -- Index of last used element in Buffer
59 Length
: Interfaces
.Unsigned_64
:= 0;
60 -- Total length of processed data
62 Buffer
: Buffer_Type
(1 .. Block_Length
);
66 -- The function-specific part of processing state:
68 -- Each hash function maintains an internal state as an array of words,
69 -- which is ultimately converted to a stream representation with the
70 -- appropriate bit order.
74 -- Either 32 or 64 bits
76 with procedure Swap
(X
: System
.Address
);
77 -- Byte swapping function for a Word at X
79 Hash_Bit_Order
: System
.Bit_Order
;
80 -- Bit order of the produced hash
82 package Hash_Function_State
is
84 type State
is array (Natural range <>) of Word
;
85 -- Used to store a hash function's internal state
89 H_Bits
: out Stream_Element_Array
);
90 -- Convert H to stream representation with the given bit order. If
91 -- H_Bits is smaller than the internal hash state, then the state
94 end Hash_Function_State
;
96 -- Generic hashing framework: The user interface for each implemented
97 -- secure hash function is an instance of this generic package.
100 Block_Words
: Natural;
101 -- Number of words in each block
103 State_Words
: Natural;
104 -- Number of words in internal state
106 Hash_Words
: Natural;
107 -- Number of words in the final hash (must be no greater than
110 Hash_Bit_Order
: System
.Bit_Order
;
111 -- Bit order used for conversion between bit representation and word
114 with package Hash_State
is new Hash_Function_State
(<>);
115 -- Hash function state package
117 Initial_State
: Hash_State
.State
;
118 -- Initial value of the hash function state
120 with procedure Transform
121 (H
: in out Hash_State
.State
;
122 M
: in out Message_State
);
123 -- Transformation function updating H by processing a complete data
128 -- The visible part of H is the interface to secure hashing functions
129 -- that is exposed to user applications, and is intended to remain
130 -- a stable interface.
132 pragma Assert
(Hash_Words
<= State_Words
);
134 type Context
is private;
135 -- The internal processing state of the hashing function
137 function "=" (L
, R
: Context
) return Boolean is abstract;
138 -- Context is the internal, implementation defined intermediate state
139 -- in a hash computation, and no specific semantics can be expected on
140 -- equality of context values. Only equality of final hash values (as
141 -- returned by the [Wide_]Digest functions below) is meaningful.
143 Initial_Context
: constant Context
;
144 -- Initial value of a Context object. May be used to reinitialize
145 -- a Context value by simple assignment of this value to the object.
147 function HMAC_Initial_Context
(Key
: String) return Context
;
148 -- Initial Context for HMAC computation with the given Key
150 procedure Update
(C
: in out Context
; Input
: String);
151 procedure Wide_Update
(C
: in out Context
; Input
: Wide_String);
154 Input
: Stream_Element_Array
);
155 -- Update C to process the given input. Successive calls to Update are
156 -- equivalent to a single call with the concatenation of the inputs. For
157 -- the Wide_String version, each Wide_Character is processed low order
160 Word_Length
: constant Natural := Hash_State
.Word
'Size / 8;
161 Hash_Length
: constant Natural := Hash_Words
* Word_Length
;
163 subtype Binary_Message_Digest
is
164 Stream_Element_Array
(1 .. Stream_Element_Offset
(Hash_Length
));
165 -- The fixed-length byte array returned by Digest, providing
166 -- the hash in binary representation.
168 function Digest
(C
: Context
) return Binary_Message_Digest
;
169 -- Return hash or HMAC for the data accumulated with C
171 function Digest
(S
: String) return Binary_Message_Digest
;
172 function Wide_Digest
(W
: Wide_String) return Binary_Message_Digest
;
174 (A
: Stream_Element_Array
) return Binary_Message_Digest
;
175 -- These functions are equivalent to the corresponding Update (or
176 -- Wide_Update) on a default initialized Context, followed by Digest
177 -- on the resulting Context.
179 subtype Message_Digest
is String (1 .. 2 * Hash_Length
);
180 -- The fixed-length string returned by Digest, providing the hash in
181 -- hexadecimal representation.
183 function Digest
(C
: Context
) return Message_Digest
;
184 -- Return hash or HMAC for the data accumulated with C in hexadecimal
187 function Digest
(S
: String) return Message_Digest
;
188 function Wide_Digest
(W
: Wide_String) return Message_Digest
;
189 function Digest
(A
: Stream_Element_Array
) return Message_Digest
;
190 -- These functions are equivalent to the corresponding Update (or
191 -- Wide_Update) on a default initialized Context, followed by Digest
192 -- on the resulting Context.
194 type Hash_Stream
(C
: access Context
) is
195 new Root_Stream_Type
with private;
196 -- Stream wrapper converting Write calls to Update calls on C.
197 -- Arbitrary data structures can thus be conveniently hashed using
198 -- their stream attributes.
202 Block_Length
: constant Natural := Block_Words
* Word_Length
;
203 -- Length in bytes of a data block
205 subtype Key_Length
is
206 Stream_Element_Offset
range 0 .. Stream_Element_Offset
(Block_Length
);
208 -- KL is 0 for a normal hash context, > 0 for HMAC
210 type Context
(KL
: Key_Length
:= 0) is record
211 H_State
: Hash_State
.State
(0 .. State_Words
- 1) := Initial_State
;
212 -- Function-specific state
214 M_State
: Message_State
(Block_Length
);
215 -- Function-independent state (block buffer)
217 Key
: Stream_Element_Array
(1 .. KL
);
221 Initial_Context
: constant Context
(KL
=> 0) := (others => <>);
222 -- Initial values are provided by default initialization of Context
224 type Hash_Stream
(C
: access Context
) is
225 new Root_Stream_Type
with null record;
228 (Stream
: in out Hash_Stream
;
229 Item
: out Stream_Element_Array
;
230 Last
: out Stream_Element_Offset
);
231 -- Raise Program_Error: hash streams are write-only
234 (Stream
: in out Hash_Stream
;
235 Item
: Stream_Element_Array
);
240 end GNAT
.Secure_Hashes
;