1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
|
------------------------------------------------------------------------------
-- --
-- GNAT LIBRARY COMPONENTS --
-- --
-- G N A T . S E C U R E _ H A S H E S --
-- --
-- S p e c --
-- --
-- Copyright (C) 2009-2020, 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. --
-- --
------------------------------------------------------------------------------
-- This package provides common supporting code for a family of secure
-- hash functions (including MD5 and the FIPS PUB 180-3 functions SHA-1,
-- SHA-224, SHA-256, SHA-384 and SHA-512).
-- This is an internal unit and should be not used directly in applications.
-- Use GNAT.MD5 and GNAT.SHA* instead.
with Ada.Streams; use Ada.Streams;
with Interfaces;
with System;
package GNAT.Secure_Hashes is
type Buffer_Type is new Stream_Element_Array;
for Buffer_Type'Alignment use 8;
-- Secure hash functions use a string buffer that is also accessed as an
-- array of words, which may require up to 64 bit alignment.
-- The function-independent part of processing state: A buffer of data
-- being accumulated until a complete block is ready for hashing.
type Message_State (Block_Length : Stream_Element_Count) is record
Last : Stream_Element_Offset := 0;
-- Index of last used element in Buffer
Length : Interfaces.Unsigned_64 := 0;
-- Total length of processed data
Buffer : Buffer_Type (1 .. Block_Length);
-- Data buffer
end record;
-- The function-specific part of processing state:
-- Each hash function maintains an internal state as an array of words,
-- which is ultimately converted to a stream representation with the
-- appropriate bit order.
generic
type Word is mod <>;
-- Either 32 or 64 bits
with procedure Swap (X : System.Address);
-- Byte swapping function for a Word at X
Hash_Bit_Order : System.Bit_Order;
-- Bit order of the produced hash
package Hash_Function_State is
type State is array (Stream_Element_Offset range <>) of Word;
-- Used to store a hash function's internal state
procedure To_Hash
(H : State;
H_Bits : out Stream_Element_Array);
-- Convert H to stream representation with the given bit order. If
-- H_Bits is smaller than the internal hash state, then the state
-- is truncated.
end Hash_Function_State;
-- Generic hashing framework: The user interface for each implemented
-- secure hash function is an instance of this generic package.
generic
Block_Words : Stream_Element_Count;
-- Number of words in each block
State_Words : Stream_Element_Count;
-- Number of words in internal state
Hash_Words : Stream_Element_Count;
-- Number of words in the final hash (must be no greater than
-- State_Words).
Hash_Bit_Order : System.Bit_Order;
-- Bit order used for conversion between bit representation and word
-- representation.
with package Hash_State is new Hash_Function_State (<>);
-- Hash function state package
Initial_State : Hash_State.State;
-- Initial value of the hash function state
with procedure Transform
(H : in out Hash_State.State;
M : in out Message_State);
-- Transformation function updating H by processing a complete data
-- block from M.
package H is
-- The visible part of H is the interface to secure hashing functions
-- that is exposed to user applications, and is intended to remain
-- a stable interface.
pragma Assert (Hash_Words <= State_Words);
type Context is private;
-- The internal processing state of the hashing function
function "=" (L, R : Context) return Boolean is abstract;
-- Context is the internal, implementation defined intermediate state
-- in a hash computation, and no specific semantics can be expected on
-- equality of context values. Only equality of final hash values (as
-- returned by the [Wide_]Digest functions below) is meaningful.
Initial_Context : constant Context;
-- Initial value of a Context object. May be used to reinitialize
-- a Context value by simple assignment of this value to the object.
function HMAC_Initial_Context (Key : String) return Context;
-- Initial Context for HMAC computation with the given Key
procedure Update (C : in out Context; Input : String);
procedure Wide_Update (C : in out Context; Input : Wide_String);
procedure Update
(C : in out Context;
Input : Stream_Element_Array);
-- Update C to process the given input. Successive calls to Update are
-- equivalent to a single call with the concatenation of the inputs. For
-- the Wide_String version, each Wide_Character is processed low order
-- byte first.
Word_Length : constant Stream_Element_Offset := Hash_State.Word'Size / 8;
Hash_Length : constant Stream_Element_Offset := Hash_Words * Word_Length;
subtype Binary_Message_Digest is Stream_Element_Array (1 .. Hash_Length);
-- The fixed-length byte array returned by Digest, providing
-- the hash in binary representation.
function Digest (C : Context) return Binary_Message_Digest;
-- Return hash or HMAC for the data accumulated with C
function Digest (S : String) return Binary_Message_Digest;
function Wide_Digest (W : Wide_String) return Binary_Message_Digest;
function Digest
(A : Stream_Element_Array) return Binary_Message_Digest;
-- These functions are equivalent to the corresponding Update (or
-- Wide_Update) on a default initialized Context, followed by Digest
-- on the resulting Context.
subtype Message_Digest is String (1 .. 2 * Integer (Hash_Length));
-- The fixed-length string returned by Digest, providing the hash in
-- hexadecimal representation.
function Digest (C : Context) return Message_Digest;
-- Return hash or HMAC for the data accumulated with C in hexadecimal
-- representation.
function Digest (S : String) return Message_Digest;
function Wide_Digest (W : Wide_String) return Message_Digest;
function Digest (A : Stream_Element_Array) return Message_Digest;
-- These functions are equivalent to the corresponding Update (or
-- Wide_Update) on a default initialized Context, followed by Digest
-- on the resulting Context.
type Hash_Stream (C : access Context) is
new Root_Stream_Type with private;
-- Stream wrapper converting Write calls to Update calls on C.
-- Arbitrary data structures can thus be conveniently hashed using
-- their stream attributes.
private
Block_Length : constant Stream_Element_Count :=
Block_Words * Word_Length;
-- Length in bytes of a data block
subtype Key_Length is
Stream_Element_Offset range 0 .. Block_Length;
-- KL is 0 for a normal hash context, > 0 for HMAC
type Context (KL : Key_Length := 0) is record
H_State : Hash_State.State (0 .. State_Words - 1) := Initial_State;
-- Function-specific state
M_State : Message_State (Block_Length);
-- Function-independent state (block buffer)
Key : Stream_Element_Array (1 .. KL);
-- HMAC key
end record;
Initial_Context : constant Context (KL => 0) := (others => <>);
-- Initial values are provided by default initialization of Context
type Hash_Stream (C : access Context) is
new Root_Stream_Type with null record;
procedure Read
(Stream : in out Hash_Stream;
Item : out Stream_Element_Array;
Last : out Stream_Element_Offset);
-- Raise Program_Error: hash streams are write-only
procedure Write
(Stream : in out Hash_Stream;
Item : Stream_Element_Array);
-- Call Update
end H;
end GNAT.Secure_Hashes;
|