1------------------------------------------------------------------------------ 2-- -- 3-- GNAT LIBRARY COMPONENTS -- 4-- -- 5-- G N A T . S E C U R E _ H A S H E S -- 6-- -- 7-- S p e c -- 8-- -- 9-- Copyright (C) 2009-2021, Free Software Foundation, Inc. -- 10-- -- 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. -- 17-- -- 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. -- 21-- -- 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/>. -- 26-- -- 27-- GNAT was originally developed by the GNAT team at New York University. -- 28-- Extensive contributions were provided by Ada Core Technologies Inc. -- 29-- -- 30------------------------------------------------------------------------------ 31 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). 35 36-- This is an internal unit and should be not used directly in applications. 37-- Use GNAT.MD5 and GNAT.SHA* instead. 38 39with Ada.Streams; use Ada.Streams; 40 41with Interfaces; 42 43with System; 44 45package GNAT.Secure_Hashes is 46 47 type Buffer_Type is new Stream_Element_Array; 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. 51 52 -- The function-independent part of processing state: A buffer of data 53 -- being accumulated until a complete block is ready for hashing. 54 55 type Message_State (Block_Length : Stream_Element_Count) is record 56 Last : Stream_Element_Offset := 0; 57 -- Index of last used element in Buffer 58 59 Length : Interfaces.Unsigned_64 := 0; 60 -- Total length of processed data 61 62 Buffer : Buffer_Type (1 .. Block_Length); 63 -- Data buffer 64 end record; 65 66 -- The function-specific part of processing state: 67 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. 71 72 generic 73 type Word is mod <>; 74 -- Either 32 or 64 bits 75 76 with procedure Swap (X : System.Address); 77 -- Byte swapping function for a Word at X 78 79 Hash_Bit_Order : System.Bit_Order; 80 -- Bit order of the produced hash 81 82 package Hash_Function_State is 83 84 type State is array (Stream_Element_Offset range <>) of Word; 85 -- Used to store a hash function's internal state 86 87 procedure To_Hash 88 (H : 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 92 -- is truncated. 93 94 end Hash_Function_State; 95 96 -- Generic hashing framework: The user interface for each implemented 97 -- secure hash function is an instance of this generic package. 98 99 generic 100 Block_Words : Stream_Element_Count; 101 -- Number of words in each block 102 103 State_Words : Stream_Element_Count; 104 -- Number of words in internal state 105 106 Hash_Words : Stream_Element_Count; 107 -- Number of words in the final hash (must be no greater than 108 -- State_Words). 109 110 Hash_Bit_Order : System.Bit_Order; 111 -- Bit order used for conversion between bit representation and word 112 -- representation. 113 114 with package Hash_State is new Hash_Function_State (<>); 115 -- Hash function state package 116 117 Initial_State : Hash_State.State; 118 -- Initial value of the hash function state 119 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 124 -- block from M. 125 126 package H is 127 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. 131 132 pragma Assert (Hash_Words <= State_Words); 133 134 type Context is private; 135 -- The internal processing state of the hashing function 136 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. 142 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. 146 147 function HMAC_Initial_Context (Key : String) return Context; 148 -- Initial Context for HMAC computation with the given Key 149 150 procedure Update (C : in out Context; Input : String); 151 procedure Wide_Update (C : in out Context; Input : Wide_String); 152 procedure Update 153 (C : in out Context; 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 158 -- byte first. 159 160 Word_Length : constant Stream_Element_Offset := Hash_State.Word'Size / 8; 161 Hash_Length : constant Stream_Element_Offset := Hash_Words * Word_Length; 162 163 subtype Binary_Message_Digest is Stream_Element_Array (1 .. Hash_Length); 164 -- The fixed-length byte array returned by Digest, providing 165 -- the hash in binary representation. 166 167 function Digest (C : Context) return Binary_Message_Digest; 168 -- Return hash or HMAC for the data accumulated with C 169 170 function Digest (S : String) return Binary_Message_Digest; 171 function Wide_Digest (W : Wide_String) return Binary_Message_Digest; 172 function Digest 173 (A : Stream_Element_Array) return Binary_Message_Digest; 174 -- These functions are equivalent to the corresponding Update (or 175 -- Wide_Update) on a default initialized Context, followed by Digest 176 -- on the resulting Context. 177 178 subtype Message_Digest is String (1 .. 2 * Integer (Hash_Length)); 179 -- The fixed-length string returned by Digest, providing the hash in 180 -- hexadecimal representation. 181 182 function Digest (C : Context) return Message_Digest; 183 -- Return hash or HMAC for the data accumulated with C in hexadecimal 184 -- representation. 185 186 function Digest (S : String) return Message_Digest; 187 function Wide_Digest (W : Wide_String) return Message_Digest; 188 function Digest (A : Stream_Element_Array) return Message_Digest; 189 -- These functions are equivalent to the corresponding Update (or 190 -- Wide_Update) on a default initialized Context, followed by Digest 191 -- on the resulting Context. 192 193 type Hash_Stream (C : access Context) is 194 new Root_Stream_Type with private; 195 -- Stream wrapper converting Write calls to Update calls on C. 196 -- Arbitrary data structures can thus be conveniently hashed using 197 -- their stream attributes. 198 199 private 200 201 Block_Length : constant Stream_Element_Count := 202 Block_Words * Word_Length; 203 -- Length in bytes of a data block 204 205 subtype Key_Length is 206 Stream_Element_Offset range 0 .. Block_Length; 207 208 -- KL is 0 for a normal hash context, > 0 for HMAC 209 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 213 214 M_State : Message_State (Block_Length); 215 -- Function-independent state (block buffer) 216 217 Key : Stream_Element_Array (1 .. KL); 218 -- HMAC key 219 end record; 220 221 pragma Warnings (Off, "aggregate not fully initialized"); 222 Initial_Context : constant Context (KL => 0) := (others => <>); 223 pragma Warnings (On, "aggregate not fully initialized"); 224 -- Initial values are provided by default initialization of Context 225 226 type Hash_Stream (C : access Context) is 227 new Root_Stream_Type with null record; 228 229 procedure Read 230 (Stream : in out Hash_Stream; 231 Item : out Stream_Element_Array; 232 Last : out Stream_Element_Offset); 233 -- Raise Program_Error: hash streams are write-only 234 235 procedure Write 236 (Stream : in out Hash_Stream; 237 Item : Stream_Element_Array); 238 -- Call Update 239 240 end H; 241 242end GNAT.Secure_Hashes; 243