1 /*
2  * SHA-512 functions
3  *
4  * Copyright (C) 2011-2020, Joachim Metz <joachim.metz@gmail.com>
5  *
6  * Refer to AUTHORS for acknowledgements.
7  *
8  * This program is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #include <common.h>
23 #include <byte_stream.h>
24 #include <memory.h>
25 #include <types.h>
26 
27 #if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_SHA_H )
28 #include <openssl/sha.h>
29 
30 #elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H )
31 #include <openssl/err.h>
32 #include <openssl/evp.h>
33 
34 #endif
35 
36 #include "libhmac_byte_stream.h"
37 #include "libhmac_definitions.h"
38 #include "libhmac_libcerror.h"
39 #include "libhmac_sha512.h"
40 
41 #if !defined( LIBHMAC_HAVE_SHA512_SUPPORT )
42 
43 /* FIPS 180-2 based SHA-512 functions
44  */
45 
46 /* The first 64-bits of the fractional parts of the square roots of the first 8 primes [ 2, 19 ]
47  */
48 uint64_t libhmac_sha512_prime_square_roots[ 8 ] = {
49 	0x6a09e667f3bcc908, 0xbb67ae8584caa73b, 0x3c6ef372fe94f82b, 0xa54ff53a5f1d36f1,
50         0x510e527fade682d1, 0x9b05688c2b3e6c1f, 0x1f83d9abfb41bd6b, 0x5be0cd19137e2179
51 };
52 
53 /* The first 64-bits of the fractional parts of the cube roots of the first 80 primes [ 2, 409 ]
54  */
55 uint64_t libhmac_sha512_prime_cube_roots[ 80 ] = {
56 	0x428a2f98d728ae22,  0x7137449123ef65cd, 0xb5c0fbcfec4d3b2f,  0xe9b5dba58189dbbc,
57 	0x3956c25bf348b538,  0x59f111f1b605d019, 0x923f82a4af194f9b,  0xab1c5ed5da6d8118,
58 	0xd807aa98a3030242,  0x12835b0145706fbe, 0x243185be4ee4b28c,  0x550c7dc3d5ffb4e2,
59 	0x72be5d74f27b896f,  0x80deb1fe3b1696b1, 0x9bdc06a725c71235,  0xc19bf174cf692694,
60 	0xe49b69c19ef14ad2,  0xefbe4786384f25e3, 0x0fc19dc68b8cd5b5,  0x240ca1cc77ac9c65,
61 	0x2de92c6f592b0275,  0x4a7484aa6ea6e483, 0x5cb0a9dcbd41fbd4,  0x76f988da831153b5,
62 	0x983e5152ee66dfab,  0xa831c66d2db43210, 0xb00327c898fb213f,  0xbf597fc7beef0ee4,
63 	0xc6e00bf33da88fc2,  0xd5a79147930aa725, 0x06ca6351e003826f,  0x142929670a0e6e70,
64 	0x27b70a8546d22ffc,  0x2e1b21385c26c926, 0x4d2c6dfc5ac42aed,  0x53380d139d95b3df,
65 	0x650a73548baf63de,  0x766a0abb3c77b2a8, 0x81c2c92e47edaee6,  0x92722c851482353b,
66 	0xa2bfe8a14cf10364,  0xa81a664bbc423001, 0xc24b8b70d0f89791,  0xc76c51a30654be30,
67 	0xd192e819d6ef5218,  0xd69906245565a910, 0xf40e35855771202a,  0x106aa07032bbd1b8,
68 	0x19a4c116b8d2d0c8,  0x1e376c085141ab53, 0x2748774cdf8eeb99,  0x34b0bcb5e19b48a8,
69 	0x391c0cb3c5c95a63,  0x4ed8aa4ae3418acb, 0x5b9cca4f7763e373,  0x682e6ff3d6b2b8a3,
70 	0x748f82ee5defb2fc,  0x78a5636f43172f60, 0x84c87814a1f0ab72,  0x8cc702081a6439ec,
71 	0x90befffa23631e28,  0xa4506cebde82bde9, 0xbef9a3f7b2c67915,  0xc67178f2e372532b,
72 	0xca273eceea26619c,  0xd186b8c721c0c207, 0xeada7dd6cde0eb1e,  0xf57d4f7fee6ed178,
73 	0x06f067aa72176fba,  0x0a637dc5a2c898a6, 0x113f9804bef90dae,  0x1b710b35131c471b,
74 	0x28db77f523047d84,  0x32caab7b40c72493, 0x3c9ebe0a15c9bebc,  0x431d67c49c100d4c,
75 	0x4cc5d4becb3e42b6,  0x597f299cfc657e2a, 0x5fcb6fab3ad6faec,  0x6c44198c4a475817
76 };
77 
78 #define libhmac_sha512_transform_extend_64bit_value( values_64bit, value_64bit_index, s0, s1 ) \
79 	s0 = byte_stream_bit_rotate_right_64bit( values_64bit[ value_64bit_index - 15 ], 1 ) \
80 	   ^ byte_stream_bit_rotate_right_64bit( values_64bit[ value_64bit_index - 15 ], 8 ) \
81 	   ^ ( values_64bit[ value_64bit_index - 15 ] >> 7 ); \
82 	s1 = byte_stream_bit_rotate_right_64bit( values_64bit[ value_64bit_index - 2 ], 19 ) \
83 	   ^ byte_stream_bit_rotate_right_64bit( values_64bit[ value_64bit_index - 2 ], 61 ) \
84 	   ^ ( values_64bit[ value_64bit_index - 2 ] >> 6 ); \
85 \
86 	values_64bit[ value_64bit_index ] = values_64bit[ value_64bit_index - 16 ] \
87 	                                  + s0 \
88 	                                  + values_64bit[ value_64bit_index - 7 ] \
89 	                                  + s1
90 
91 #define libhmac_sha512_transform_unfolded_extend_64bit_values( values_64bit, s0, s1 ) \
92 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 16, s0, s1 ); \
93 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 17, s0, s1 ); \
94 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 18, s0, s1 ); \
95 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 19, s0, s1 ); \
96 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 20, s0, s1 ); \
97 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 21, s0, s1 ); \
98 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 22, s0, s1 ); \
99 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 23, s0, s1 ); \
100 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 24, s0, s1 ); \
101 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 25, s0, s1 ); \
102 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 26, s0, s1 ); \
103 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 27, s0, s1 ); \
104 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 28, s0, s1 ); \
105 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 29, s0, s1 ); \
106 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 30, s0, s1 ); \
107 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 31, s0, s1 ); \
108 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 32, s0, s1 ); \
109 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 33, s0, s1 ); \
110 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 34, s0, s1 ); \
111 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 35, s0, s1 ); \
112 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 36, s0, s1 ); \
113 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 37, s0, s1 ); \
114 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 38, s0, s1 ); \
115 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 39, s0, s1 ); \
116 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 40, s0, s1 ); \
117 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 41, s0, s1 ); \
118 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 42, s0, s1 ); \
119 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 43, s0, s1 ); \
120 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 44, s0, s1 ); \
121 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 45, s0, s1 ); \
122 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 46, s0, s1 ); \
123 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 47, s0, s1 ); \
124 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 48, s0, s1 ); \
125 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 49, s0, s1 ); \
126 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 50, s0, s1 ); \
127 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 51, s0, s1 ); \
128 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 52, s0, s1 ); \
129 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 53, s0, s1 ); \
130 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 54, s0, s1 ); \
131 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 55, s0, s1 ); \
132 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 56, s0, s1 ); \
133 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 57, s0, s1 ); \
134 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 58, s0, s1 ); \
135 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 59, s0, s1 ); \
136 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 60, s0, s1 ); \
137 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 61, s0, s1 ); \
138 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 62, s0, s1 ); \
139 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 63, s0, s1 ); \
140 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 64, s0, s1 ); \
141 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 65, s0, s1 ); \
142 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 66, s0, s1 ); \
143 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 67, s0, s1 ); \
144 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 68, s0, s1 ); \
145 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 69, s0, s1 ); \
146 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 70, s0, s1 ); \
147 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 71, s0, s1 ); \
148 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 72, s0, s1 ); \
149 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 73, s0, s1 ); \
150 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 74, s0, s1 ); \
151 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 75, s0, s1 ); \
152 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 76, s0, s1 ); \
153 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 77, s0, s1 ); \
154 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 78, s0, s1 ); \
155 	libhmac_sha512_transform_extend_64bit_value( values_64bit, 79, s0, s1 );
156 
157 #define libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, value_64bit_index, hash_values, hash_value_index0, hash_value_index1, hash_value_index2, hash_value_index3, hash_value_index4, hash_value_index5, hash_value_index6, hash_value_index7, s0, s1, t1, t2 ) \
158 	s0 = byte_stream_bit_rotate_right_64bit( hash_values[ hash_value_index0 ], 28 ) \
159 	   ^ byte_stream_bit_rotate_right_64bit( hash_values[ hash_value_index0 ], 34 ) \
160 	   ^ byte_stream_bit_rotate_right_64bit( hash_values[ hash_value_index0 ], 39 ); \
161 	s1 = byte_stream_bit_rotate_right_64bit( hash_values[ hash_value_index4 ], 14 ) \
162 	   ^ byte_stream_bit_rotate_right_64bit( hash_values[ hash_value_index4 ], 18 ) \
163 	   ^ byte_stream_bit_rotate_right_64bit( hash_values[ hash_value_index4 ], 41 ); \
164 \
165 	t1  = hash_values[ hash_value_index7 ]; \
166 	t1 += s1; \
167 	t1 += ( hash_values[ hash_value_index4 ] & hash_values[ hash_value_index5 ] ) \
168 	    ^ ( ~( hash_values[ hash_value_index4 ] ) & hash_values[ hash_value_index6 ] ); \
169 	t1 += libhmac_sha512_prime_cube_roots[ value_64bit_index ]; \
170 	t1 += values_64bit[ value_64bit_index ]; \
171 	t2  = s0; \
172 	t2 += ( hash_values[ hash_value_index0 ] & hash_values[ hash_value_index1 ] ) \
173 	    ^ ( hash_values[ hash_value_index0 ] & hash_values[ hash_value_index2 ] ) \
174 	    ^ ( hash_values[ hash_value_index1 ] & hash_values[ hash_value_index2 ] ); \
175 \
176 	hash_values[ hash_value_index3 ] += t1; \
177 	hash_values[ hash_value_index7 ]  = t1 + t2;
178 
179 #define libhmac_sha512_transform_unfolded_calculate_hash_values( values_64bit, hash_values, s0, s1, t1, t2 ) \
180 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 0, hash_values, 0, 1, 2, 3, 4, 5, 6, 7, s0, s1, t1, t2 ) \
181 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 1, hash_values, 7, 0, 1, 2, 3, 4, 5, 6, s0, s1, t1, t2 ) \
182 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 2, hash_values, 6, 7, 0, 1, 2, 3, 4, 5, s0, s1, t1, t2 ) \
183 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 3, hash_values, 5, 6, 7, 0, 1, 2, 3, 4, s0, s1, t1, t2 ) \
184 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 4, hash_values, 4, 5, 6, 7, 0, 1, 2, 3, s0, s1, t1, t2 ) \
185 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 5, hash_values, 3, 4, 5, 6, 7, 0, 1, 2, s0, s1, t1, t2 ) \
186 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 6, hash_values, 2, 3, 4, 5, 6, 7, 0, 1, s0, s1, t1, t2 ) \
187 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 7, hash_values, 1, 2, 3, 4, 5, 6, 7, 0, s0, s1, t1, t2 ) \
188 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 8, hash_values, 0, 1, 2, 3, 4, 5, 6, 7, s0, s1, t1, t2 ) \
189 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 9, hash_values, 7, 0, 1, 2, 3, 4, 5, 6, s0, s1, t1, t2 ) \
190 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 10, hash_values, 6, 7, 0, 1, 2, 3, 4, 5, s0, s1, t1, t2 ) \
191 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 11, hash_values, 5, 6, 7, 0, 1, 2, 3, 4, s0, s1, t1, t2 ) \
192 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 12, hash_values, 4, 5, 6, 7, 0, 1, 2, 3, s0, s1, t1, t2 ) \
193 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 13, hash_values, 3, 4, 5, 6, 7, 0, 1, 2, s0, s1, t1, t2 ) \
194 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 14, hash_values, 2, 3, 4, 5, 6, 7, 0, 1, s0, s1, t1, t2 ) \
195 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 15, hash_values, 1, 2, 3, 4, 5, 6, 7, 0, s0, s1, t1, t2 ) \
196 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 16, hash_values, 0, 1, 2, 3, 4, 5, 6, 7, s0, s1, t1, t2 ) \
197 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 17, hash_values, 7, 0, 1, 2, 3, 4, 5, 6, s0, s1, t1, t2 ) \
198 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 18, hash_values, 6, 7, 0, 1, 2, 3, 4, 5, s0, s1, t1, t2 ) \
199 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 19, hash_values, 5, 6, 7, 0, 1, 2, 3, 4, s0, s1, t1, t2 ) \
200 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 20, hash_values, 4, 5, 6, 7, 0, 1, 2, 3, s0, s1, t1, t2 ) \
201 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 21, hash_values, 3, 4, 5, 6, 7, 0, 1, 2, s0, s1, t1, t2 ) \
202 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 22, hash_values, 2, 3, 4, 5, 6, 7, 0, 1, s0, s1, t1, t2 ) \
203 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 23, hash_values, 1, 2, 3, 4, 5, 6, 7, 0, s0, s1, t1, t2 ) \
204 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 24, hash_values, 0, 1, 2, 3, 4, 5, 6, 7, s0, s1, t1, t2 ) \
205 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 25, hash_values, 7, 0, 1, 2, 3, 4, 5, 6, s0, s1, t1, t2 ) \
206 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 26, hash_values, 6, 7, 0, 1, 2, 3, 4, 5, s0, s1, t1, t2 ) \
207 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 27, hash_values, 5, 6, 7, 0, 1, 2, 3, 4, s0, s1, t1, t2 ) \
208 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 28, hash_values, 4, 5, 6, 7, 0, 1, 2, 3, s0, s1, t1, t2 ) \
209 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 29, hash_values, 3, 4, 5, 6, 7, 0, 1, 2, s0, s1, t1, t2 ) \
210 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 30, hash_values, 2, 3, 4, 5, 6, 7, 0, 1, s0, s1, t1, t2 ) \
211 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 31, hash_values, 1, 2, 3, 4, 5, 6, 7, 0, s0, s1, t1, t2 ) \
212 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 32, hash_values, 0, 1, 2, 3, 4, 5, 6, 7, s0, s1, t1, t2 ) \
213 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 33, hash_values, 7, 0, 1, 2, 3, 4, 5, 6, s0, s1, t1, t2 ) \
214 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 34, hash_values, 6, 7, 0, 1, 2, 3, 4, 5, s0, s1, t1, t2 ) \
215 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 35, hash_values, 5, 6, 7, 0, 1, 2, 3, 4, s0, s1, t1, t2 ) \
216 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 36, hash_values, 4, 5, 6, 7, 0, 1, 2, 3, s0, s1, t1, t2 ) \
217 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 37, hash_values, 3, 4, 5, 6, 7, 0, 1, 2, s0, s1, t1, t2 ) \
218 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 38, hash_values, 2, 3, 4, 5, 6, 7, 0, 1, s0, s1, t1, t2 ) \
219 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 39, hash_values, 1, 2, 3, 4, 5, 6, 7, 0, s0, s1, t1, t2 ) \
220 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 40, hash_values, 0, 1, 2, 3, 4, 5, 6, 7, s0, s1, t1, t2 ) \
221 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 41, hash_values, 7, 0, 1, 2, 3, 4, 5, 6, s0, s1, t1, t2 ) \
222 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 42, hash_values, 6, 7, 0, 1, 2, 3, 4, 5, s0, s1, t1, t2 ) \
223 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 43, hash_values, 5, 6, 7, 0, 1, 2, 3, 4, s0, s1, t1, t2 ) \
224 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 44, hash_values, 4, 5, 6, 7, 0, 1, 2, 3, s0, s1, t1, t2 ) \
225 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 45, hash_values, 3, 4, 5, 6, 7, 0, 1, 2, s0, s1, t1, t2 ) \
226 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 46, hash_values, 2, 3, 4, 5, 6, 7, 0, 1, s0, s1, t1, t2 ) \
227 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 47, hash_values, 1, 2, 3, 4, 5, 6, 7, 0, s0, s1, t1, t2 ) \
228 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 48, hash_values, 0, 1, 2, 3, 4, 5, 6, 7, s0, s1, t1, t2 ) \
229 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 49, hash_values, 7, 0, 1, 2, 3, 4, 5, 6, s0, s1, t1, t2 ) \
230 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 50, hash_values, 6, 7, 0, 1, 2, 3, 4, 5, s0, s1, t1, t2 ) \
231 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 51, hash_values, 5, 6, 7, 0, 1, 2, 3, 4, s0, s1, t1, t2 ) \
232 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 52, hash_values, 4, 5, 6, 7, 0, 1, 2, 3, s0, s1, t1, t2 ) \
233 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 53, hash_values, 3, 4, 5, 6, 7, 0, 1, 2, s0, s1, t1, t2 ) \
234 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 54, hash_values, 2, 3, 4, 5, 6, 7, 0, 1, s0, s1, t1, t2 ) \
235 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 55, hash_values, 1, 2, 3, 4, 5, 6, 7, 0, s0, s1, t1, t2 ) \
236 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 56, hash_values, 0, 1, 2, 3, 4, 5, 6, 7, s0, s1, t1, t2 ) \
237 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 57, hash_values, 7, 0, 1, 2, 3, 4, 5, 6, s0, s1, t1, t2 ) \
238 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 58, hash_values, 6, 7, 0, 1, 2, 3, 4, 5, s0, s1, t1, t2 ) \
239 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 59, hash_values, 5, 6, 7, 0, 1, 2, 3, 4, s0, s1, t1, t2 ) \
240 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 60, hash_values, 4, 5, 6, 7, 0, 1, 2, 3, s0, s1, t1, t2 ) \
241 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 61, hash_values, 3, 4, 5, 6, 7, 0, 1, 2, s0, s1, t1, t2 ) \
242 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 62, hash_values, 2, 3, 4, 5, 6, 7, 0, 1, s0, s1, t1, t2 ) \
243 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 63, hash_values, 1, 2, 3, 4, 5, 6, 7, 0, s0, s1, t1, t2 ) \
244 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 64, hash_values, 0, 1, 2, 3, 4, 5, 6, 7, s0, s1, t1, t2 ) \
245 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 65, hash_values, 7, 0, 1, 2, 3, 4, 5, 6, s0, s1, t1, t2 ) \
246 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 66, hash_values, 6, 7, 0, 1, 2, 3, 4, 5, s0, s1, t1, t2 ) \
247 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 67, hash_values, 5, 6, 7, 0, 1, 2, 3, 4, s0, s1, t1, t2 ) \
248 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 68, hash_values, 4, 5, 6, 7, 0, 1, 2, 3, s0, s1, t1, t2 ) \
249 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 69, hash_values, 3, 4, 5, 6, 7, 0, 1, 2, s0, s1, t1, t2 ) \
250 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 70, hash_values, 2, 3, 4, 5, 6, 7, 0, 1, s0, s1, t1, t2 ) \
251 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 71, hash_values, 1, 2, 3, 4, 5, 6, 7, 0, s0, s1, t1, t2 ) \
252 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 72, hash_values, 0, 1, 2, 3, 4, 5, 6, 7, s0, s1, t1, t2 ) \
253 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 73, hash_values, 7, 0, 1, 2, 3, 4, 5, 6, s0, s1, t1, t2 ) \
254 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 74, hash_values, 6, 7, 0, 1, 2, 3, 4, 5, s0, s1, t1, t2 ) \
255 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 75, hash_values, 5, 6, 7, 0, 1, 2, 3, 4, s0, s1, t1, t2 ) \
256 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 76, hash_values, 4, 5, 6, 7, 0, 1, 2, 3, s0, s1, t1, t2 ) \
257 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 77, hash_values, 3, 4, 5, 6, 7, 0, 1, 2, s0, s1, t1, t2 ) \
258 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 78, hash_values, 2, 3, 4, 5, 6, 7, 0, 1, s0, s1, t1, t2 ) \
259 	libhmac_sha512_transform_unfolded_calculate_hash_value( values_64bit, 79, hash_values, 1, 2, 3, 4, 5, 6, 7, 0, s0, s1, t1, t2 )
260 
261 /* Calculates the SHA-512 of 128 byte sized blocks of data in a buffer
262  * Returns the number of bytes used if successful or -1 on error
263  */
libhmac_sha512_transform(libhmac_internal_sha512_context_t * internal_context,const uint8_t * buffer,size_t size,libcerror_error_t ** error)264 ssize_t libhmac_sha512_transform(
265          libhmac_internal_sha512_context_t *internal_context,
266          const uint8_t *buffer,
267          size_t size,
268          libcerror_error_t **error )
269 {
270 	uint64_t hash_values[ 8 ];
271 	uint64_t values_64bit[ 80 ];
272 
273 	static char *function     = "libhmac_sha512_transform";
274 	uint64_t s0               = 0;
275 	uint64_t s1               = 0;
276 	uint64_t t1               = 0;
277 	uint64_t t2               = 0;
278 	size_t buffer_offset      = 0;
279 
280 #if !defined( LIBHMAC_UNFOLLED_LOOPS )
281 	uint8_t hash_values_index = 0;
282 	uint8_t value_64bit_index = 0;
283 #endif
284 
285 	if( internal_context == NULL )
286 	{
287 		libcerror_error_set(
288 		 error,
289 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
290 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
291 		 "%s: invalid internal context.",
292 		 function );
293 
294 		return( -1 );
295 	}
296 	if( buffer == NULL )
297 	{
298 		libcerror_error_set(
299 		 error,
300 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
301 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
302 		 "%s: invalid buffer.",
303 		 function );
304 
305 		return( -1 );
306 	}
307 	if( size > (size_t) SSIZE_MAX )
308 	{
309 		libcerror_error_set(
310 		 error,
311 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
312 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
313 		 "%s: invalid size value exceeds maximum.",
314 		 function );
315 
316 		return( -1 );
317 	}
318 	while( size >= LIBHMAC_SHA512_BLOCK_SIZE )
319 	{
320 		if( memory_copy(
321 		     hash_values,
322 		     internal_context->hash_values,
323 		     sizeof( uint64_t ) * 8 ) == NULL )
324 		{
325 			libcerror_error_set(
326 			 error,
327 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
328 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
329 			 "%s: unable to copy hash values.",
330 			 function );
331 
332 			goto on_error;
333 		}
334 #if defined( LIBHMAC_UNFOLLED_LOOPS )
335 		/* Break the block into 16 x 64-bit values
336 		 */
337 		libhmac_byte_stream_copy_to_16x_uint64_big_endian(
338 		 &( buffer[ buffer_offset ] ),
339 		 values_64bit );
340 
341 		buffer_offset += LIBHMAC_SHA512_BLOCK_SIZE;
342 
343 		/* Extend to 80 x 64-bit values
344 		 */
345 		libhmac_sha512_transform_unfolded_extend_64bit_values(
346 		 values_64bit,
347 		 s0,
348 		 s1 );
349 
350 		/* Calculate the hash values for the 64-bit values
351 		 */
352 		libhmac_sha512_transform_unfolded_calculate_hash_values(
353 		 values_64bit,
354 		 hash_values,
355 		 s0,
356 		 s1,
357 		 t1,
358 		 t2 );
359 
360 		/* Update the hash values in the context
361 		 */
362 		internal_context->hash_values[ 0 ] += hash_values[ 0 ];
363 		internal_context->hash_values[ 1 ] += hash_values[ 1 ];
364 		internal_context->hash_values[ 2 ] += hash_values[ 2 ];
365 		internal_context->hash_values[ 3 ] += hash_values[ 3 ];
366 		internal_context->hash_values[ 4 ] += hash_values[ 4 ];
367 		internal_context->hash_values[ 5 ] += hash_values[ 5 ];
368 		internal_context->hash_values[ 6 ] += hash_values[ 6 ];
369 		internal_context->hash_values[ 7 ] += hash_values[ 7 ];
370 
371 #else
372 		/* Break the block into 16 x 64-bit values
373 		 */
374 		for( value_64bit_index = 0;
375 		     value_64bit_index < 16;
376 		     value_64bit_index++ )
377 		{
378 			byte_stream_copy_to_uint64_big_endian(
379 			 &( buffer[ buffer_offset ] ),
380 			 values_64bit[ value_64bit_index ] );
381 
382 			buffer_offset += sizeof( uint64_t );
383 		}
384 		/* Extend to 80 x 64-bit values
385 		 */
386 		for( value_64bit_index = 16;
387 		     value_64bit_index < 80;
388 		     value_64bit_index++ )
389 		{
390 			libhmac_sha512_transform_extend_64bit_value(
391 			 values_64bit,
392 			 value_64bit_index,
393 			 s0,
394 			 s1 );
395 		}
396 		/* Calculate the hash values for the 64-bit values
397 		 */
398 		for( value_64bit_index = 0;
399 		     value_64bit_index < 80;
400 		     value_64bit_index++ )
401 		{
402 			s0 = byte_stream_bit_rotate_right_64bit( hash_values[ 0 ], 28 )
403 			   ^ byte_stream_bit_rotate_right_64bit( hash_values[ 0 ], 34 )
404 			   ^ byte_stream_bit_rotate_right_64bit( hash_values[ 0 ], 39 );
405 			s1 = byte_stream_bit_rotate_right_64bit( hash_values[ 4 ], 14 )
406 			   ^ byte_stream_bit_rotate_right_64bit( hash_values[ 4 ], 18 )
407 			   ^ byte_stream_bit_rotate_right_64bit( hash_values[ 4 ], 41 );
408 
409 			t1  = hash_values[ 7 ];
410 			t1 += s1;
411 			t1 += ( hash_values[ 4 ] & hash_values[ 5 ] )
412 			    ^ ( ~( hash_values[ 4 ] ) & hash_values[ 6 ] );
413 			t1 += libhmac_sha512_prime_cube_roots[ value_64bit_index ];
414 			t1 += values_64bit[ value_64bit_index ];
415 			t2  = s0;
416 			t2 += ( hash_values[ 0 ] & hash_values[ 1 ] )
417 			    ^ ( hash_values[ 0 ] & hash_values[ 2 ] )
418 			    ^ ( hash_values[ 1 ] & hash_values[ 2 ] );
419 
420 			hash_values[ 7 ] = hash_values[ 6 ];
421 			hash_values[ 6 ] = hash_values[ 5 ];
422 			hash_values[ 5 ] = hash_values[ 4 ];
423 			hash_values[ 4 ] = hash_values[ 3 ] + t1;
424 			hash_values[ 3 ] = hash_values[ 2 ];
425 			hash_values[ 2 ] = hash_values[ 1 ];
426 			hash_values[ 1 ] = hash_values[ 0 ];
427 			hash_values[ 0 ] = t1 + t2;
428 		}
429 		/* Update the hash values in the context
430 		 */
431 		for( hash_values_index = 0;
432 		     hash_values_index < 8;
433 		     hash_values_index++ )
434 		{
435 			internal_context->hash_values[ hash_values_index ] += hash_values[ hash_values_index ];
436 		}
437 #endif /* defined( LIBHMAC_UNFOLLED_LOOPS ) */
438 
439 		size -= LIBHMAC_SHA512_BLOCK_SIZE;
440 	}
441 	/* Prevent sensitive data from leaking
442 	 */
443 	if( memory_set(
444 	     hash_values,
445 	     0,
446 	     sizeof( uint64_t ) * 8 ) == NULL )
447 	{
448 		libcerror_error_set(
449 		 error,
450 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
451 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
452 		 "%s: unable to clear hash values.",
453 		 function );
454 
455 		goto on_error;
456 	}
457 	if( memory_set(
458 	     values_64bit,
459 	     0,
460 	     sizeof( uint64_t ) * 80 ) == NULL )
461 	{
462 		libcerror_error_set(
463 		 error,
464 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
465 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
466 		 "%s: unable to clear 64-bit values.",
467 		 function );
468 
469 		goto on_error;
470 	}
471 	return( (ssize_t) buffer_offset );
472 
473 on_error:
474 	memory_set(
475 	 values_64bit,
476 	 0,
477 	 sizeof( uint64_t ) * 80 );
478 
479 	memory_set(
480 	 hash_values,
481 	 0,
482 	 sizeof( uint64_t ) * 8 );
483 
484 	return( -1 );
485 }
486 
487 #endif /* !defined( LIBHMAC_HAVE_SHA512_SUPPORT ) */
488 
489 /* Creates a SHA-512 context
490  * Make sure the value context is referencing, is set to NULL
491  * Returns 1 if successful or -1 on error
492  */
libhmac_sha512_initialize(libhmac_sha512_context_t ** context,libcerror_error_t ** error)493 int libhmac_sha512_initialize(
494      libhmac_sha512_context_t **context,
495      libcerror_error_t **error )
496 {
497 	libhmac_internal_sha512_context_t *internal_context = NULL;
498 	static char *function                               = "libhmac_sha512_initialize";
499 
500 	if( context == NULL )
501 	{
502 		libcerror_error_set(
503 		 error,
504 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
505 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
506 		 "%s: invalid context.",
507 		 function );
508 
509 		return( -1 );
510 	}
511 	if( *context != NULL )
512 	{
513 		libcerror_error_set(
514 		 error,
515 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
516 		 LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
517 		 "%s: invalid context value already set.",
518 		 function );
519 
520 		return( -1 );
521 	}
522 	internal_context = memory_allocate_structure(
523 	                    libhmac_internal_sha512_context_t );
524 
525 	if( internal_context == NULL )
526 	{
527 		libcerror_error_set(
528 		 error,
529 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
530 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
531 		 "%s: unable to create context.",
532 		 function );
533 
534 		goto on_error;
535 	}
536 	if( memory_set(
537 	     internal_context,
538 	     0,
539 	     sizeof( libhmac_internal_sha512_context_t ) ) == NULL )
540 	{
541 		libcerror_error_set(
542 		 error,
543 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
544 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
545 		 "%s: unable to clear context.",
546 		 function );
547 
548 		memory_free(
549 		 internal_context );
550 
551 		return( -1 );
552 	}
553 #if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_SHA_H ) && defined( SHA512_DIGEST_LENGTH )
554 	if( SHA512_Init(
555 	     &( internal_context->sha512_context ) ) != 1 )
556 	{
557 		libcerror_error_set(
558 		 error,
559 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
560 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
561 		 "%s: unable to initialize context.",
562 		 function );
563 
564 		goto on_error;
565 	}
566 
567 #elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_SHA512 )
568 #if defined( HAVE_EVP_MD_CTX_INIT )
569 	EVP_MD_CTX_init(
570 	 &( internal_context->internal_evp_md_context ) );
571 
572 	internal_context->evp_md_context = &( internal_context->internal_evp_md_context );
573 #else
574 	internal_context->evp_md_context = EVP_MD_CTX_new();
575 
576 	if( internal_context->evp_md_context == NULL )
577 	{
578 		libcerror_error_set(
579 		 error,
580 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
581 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
582 		 "%s: unable to create EVP message digest context.",
583 		 function );
584 
585 		goto on_error;
586 	}
587 #endif /* defined( HAVE_EVP_MD_CTX_INIT ) */
588 
589 	if( EVP_DigestInit_ex(
590 	     internal_context->evp_md_context,
591 	     EVP_sha512(),
592 	     NULL ) != 1 )
593 	{
594 		libcerror_error_set(
595 		 error,
596 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
597 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
598 		 "%s: unable to initialize context.",
599 		 function );
600 
601 #if defined( HAVE_EVP_MD_CTX_CLEANUP )
602 		EVP_MD_CTX_cleanup(
603 		 &( internal_context->internal_evp_md_context ) );
604 		ERR_remove_thread_state(
605 		 NULL );
606 #else
607 		EVP_MD_CTX_free(
608 		 internal_context->evp_md_context );
609 #endif
610 		internal_context->evp_md_context = NULL;
611 
612 		goto on_error;
613 	}
614 #else
615 	if( memory_copy(
616 	     internal_context->hash_values,
617 	     libhmac_sha512_prime_square_roots,
618 	     sizeof( uint64_t ) * 8 ) == NULL )
619 	{
620 		libcerror_error_set(
621 		 error,
622 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
623 		 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
624 		 "%s: unable to copy initial hash values.",
625 		 function );
626 
627 		return( -1 );
628 	}
629 #endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_SHA_H ) && defined( SHA512_DIGEST_LENGTH ) */
630 
631 	*context = (libhmac_sha512_context_t *) internal_context;
632 
633 	return( 1 );
634 
635 on_error:
636 	if( internal_context != NULL )
637 	{
638 		memory_free(
639 		 internal_context );
640 	}
641 	return( -1 );
642 }
643 
644 /* Frees a SHA-512 context
645  * Returns 1 if successful or -1 on error
646  */
libhmac_sha512_free(libhmac_sha512_context_t ** context,libcerror_error_t ** error)647 int libhmac_sha512_free(
648      libhmac_sha512_context_t **context,
649      libcerror_error_t **error )
650 {
651 	libhmac_internal_sha512_context_t *internal_context = NULL;
652 	static char *function                               = "libhmac_sha512_free";
653 
654 	if( context == NULL )
655 	{
656 		libcerror_error_set(
657 		 error,
658 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
659 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
660 		 "%s: invalid context.",
661 		 function );
662 
663 		return( -1 );
664 	}
665 	if( *context != NULL )
666 	{
667 		internal_context = (libhmac_internal_sha512_context_t *) *context;
668 		*context         = NULL;
669 
670 #if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_SHA_H ) && defined( SHA512_DIGEST_LENGTH )
671 		/* No additional clean up necessary
672 		 */
673 
674 #elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_SHA512 )
675 #if defined( HAVE_EVP_MD_CTX_CLEANUP )
676 		if( EVP_MD_CTX_cleanup(
677 		     &( internal_context->internal_evp_md_context ) ) != 1 )
678 		{
679 			libcerror_error_set(
680 			 error,
681 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
682 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
683 			 "%s: unable to clean up EVP message digest context.",
684 			 function );
685 		}
686 		/* Make sure the error state is removed otherwise OpenSSL will leak memory
687 		 */
688 		ERR_remove_thread_state(
689 		 NULL );
690 #else
691 		EVP_MD_CTX_free(
692 		 internal_context->evp_md_context );
693 
694 #endif /* defined( HAVE_EVP_MD_CTX_CLEANUP ) */
695 
696 		internal_context->evp_md_context = NULL;
697 #else
698 		/* No additional clean up necessary
699 		 */
700 #endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_SHA_H ) && defined( SHA512_DIGEST_LENGTH ) */
701 
702 		memory_free(
703 		 internal_context );
704 	}
705 	return( 1 );
706 }
707 
708 #if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_SHA_H ) && defined( SHA512_DIGEST_LENGTH )
709 
710 /* Updates the SHA-512 context using OpenSSL
711  * Returns 1 if successful or -1 on error
712  */
libhmac_sha512_update(libhmac_sha512_context_t * context,const uint8_t * buffer,size_t size,libcerror_error_t ** error)713 int libhmac_sha512_update(
714      libhmac_sha512_context_t *context,
715      const uint8_t *buffer,
716      size_t size,
717      libcerror_error_t **error )
718 {
719 	libhmac_internal_sha512_context_t *internal_context = NULL;
720 	static char *function                               = "libhmac_sha512_update";
721 	unsigned long safe_hash_size                        = 0;
722 
723 	if( context == NULL )
724 	{
725 		libcerror_error_set(
726 		 error,
727 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
728 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
729 		 "%s: invalid context.",
730 		 function );
731 
732 		return( -1 );
733 	}
734 	internal_context = (libhmac_internal_sha512_context_t *) context;
735 
736 	if( buffer == NULL )
737 	{
738 		libcerror_error_set(
739 		 error,
740 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
741 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
742 		 "%s: invalid buffer.",
743 		 function );
744 
745 		return( -1 );
746 	}
747 #if ( SIZEOF_LONG < SIZEOF_SIZE_T )
748 	if( size > (size_t) ULONG_MAX )
749 #else
750 	if( size > (size_t) SSIZE_MAX )
751 #endif
752 	{
753 		libcerror_error_set(
754 		 error,
755 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
756 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
757 		 "%s: invalid size value exceeds maximum.",
758 		 function );
759 
760 		return( -1 );
761 	}
762 	if( size == 0 )
763 	{
764 		return( 1 );
765 	}
766 	safe_hash_size = (unsigned long) size;
767 
768 	if( SHA512_Update(
769 	     &( internal_context->sha512_context ),
770 	     (const void *) buffer,
771 	     size ) != 1 )
772 	{
773 		libcerror_error_set(
774 		 error,
775 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
776 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
777 		 "%s: unable to update context.",
778 		 function );
779 
780 		return( -1 );
781 	}
782 	return( 1 );
783 }
784 
785 #elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_SHA512 )
786 
787 /* Updates the SHA-512 context using OpenSSL EVP
788  * Returns 1 if successful or -1 on error
789  */
libhmac_sha512_update(libhmac_sha512_context_t * context,const uint8_t * buffer,size_t size,libcerror_error_t ** error)790 int libhmac_sha512_update(
791      libhmac_sha512_context_t *context,
792      const uint8_t *buffer,
793      size_t size,
794      libcerror_error_t **error )
795 {
796 	libhmac_internal_sha512_context_t *internal_context = NULL;
797 	static char *function                               = "libhmac_sha512_update";
798 
799 	if( context == NULL )
800 	{
801 		libcerror_error_set(
802 		 error,
803 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
804 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
805 		 "%s: invalid context.",
806 		 function );
807 
808 		return( -1 );
809 	}
810 	internal_context = (libhmac_internal_sha512_context_t *) context;
811 
812 	if( buffer == NULL )
813 	{
814 		libcerror_error_set(
815 		 error,
816 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
817 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
818 		 "%s: invalid buffer.",
819 		 function );
820 
821 		return( -1 );
822 	}
823 	if( size > (size_t) SSIZE_MAX )
824 	{
825 		libcerror_error_set(
826 		 error,
827 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
828 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
829 		 "%s: invalid size value exceeds maximum.",
830 		 function );
831 
832 		return( -1 );
833 	}
834 	if( size == 0 )
835 	{
836 		return( 1 );
837 	}
838 	if( EVP_DigestUpdate(
839 	     internal_context->evp_md_context,
840 	     (const void *) buffer,
841 	     size ) != 1 )
842 	{
843 		libcerror_error_set(
844 		 error,
845 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
846 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
847 		 "%s: unable to update context.",
848 		 function );
849 
850 		return( -1 );
851 	}
852 	return( 1 );
853 }
854 
855 #else
856 
857 /* Updates the SHA-512 context using fallback implementation
858  * Returns 1 if successful or -1 on error
859  */
libhmac_sha512_update(libhmac_sha512_context_t * context,const uint8_t * buffer,size_t size,libcerror_error_t ** error)860 int libhmac_sha512_update(
861      libhmac_sha512_context_t *context,
862      const uint8_t *buffer,
863      size_t size,
864      libcerror_error_t **error )
865 {
866 	libhmac_internal_sha512_context_t *internal_context = NULL;
867 	static char *function                               = "libhmac_sha512_update";
868 	size_t buffer_offset                                = 0;
869 	size_t remaining_block_size                         = 0;
870 	ssize_t process_count                               = 0;
871 
872 	if( context == NULL )
873 	{
874 		libcerror_error_set(
875 		 error,
876 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
877 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
878 		 "%s: invalid context.",
879 		 function );
880 
881 		return( -1 );
882 	}
883 	internal_context = (libhmac_internal_sha512_context_t *) context;
884 
885 	if( buffer == NULL )
886 	{
887 		libcerror_error_set(
888 		 error,
889 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
890 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
891 		 "%s: invalid buffer.",
892 		 function );
893 
894 		return( -1 );
895 	}
896 	if( size > (size_t) SSIZE_MAX )
897 	{
898 		libcerror_error_set(
899 		 error,
900 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
901 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
902 		 "%s: invalid size value exceeds maximum.",
903 		 function );
904 
905 		return( -1 );
906 	}
907 	if( size == 0 )
908 	{
909 		return( 1 );
910 	}
911 	if( internal_context->block_offset > 0 )
912 	{
913 		remaining_block_size = LIBHMAC_SHA512_BLOCK_SIZE - internal_context->block_offset;
914 
915 		if( remaining_block_size > size )
916 		{
917 			remaining_block_size = size;
918 		}
919 		if( memory_copy(
920 		     &( internal_context->block[ internal_context->block_offset ] ),
921 		     buffer,
922 		     remaining_block_size ) == NULL )
923 		{
924 			libcerror_error_set(
925 			 error,
926 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
927 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
928 			 "%s: unable to copy data to context block.",
929 			 function );
930 
931 			return( -1 );
932 		}
933 		internal_context->block_offset += remaining_block_size;
934 
935 		if( internal_context->block_offset < LIBHMAC_SHA512_BLOCK_SIZE )
936 		{
937 			return( 1 );
938 		}
939 		buffer_offset += remaining_block_size;
940 		size          -= remaining_block_size;
941 
942 		process_count = libhmac_sha512_transform(
943 		                 internal_context,
944 		                 internal_context->block,
945 		                 LIBHMAC_SHA512_BLOCK_SIZE,
946 		                 error );
947 
948 		if( process_count == -1 )
949 		{
950 			libcerror_error_set(
951 			 error,
952 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
953 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
954 			 "%s: unable to transform context block.",
955 			 function );
956 
957 			return( -1 );
958 		}
959 		internal_context->hash_count  += process_count;
960 		internal_context->block_offset = 0;
961 	}
962 	if( size > 0 )
963 	{
964 		process_count = libhmac_sha512_transform(
965 		                 internal_context,
966 		                 &( buffer[ buffer_offset ] ),
967 		                 size,
968 		                 error );
969 
970 		if( process_count == -1 )
971 		{
972 			libcerror_error_set(
973 			 error,
974 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
975 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
976 			 "%s: unable to transform buffer.",
977 			 function );
978 
979 			return( -1 );
980 		}
981 		internal_context->hash_count += process_count;
982 
983 		buffer_offset += process_count;
984 		size          -= process_count;
985 	}
986 	if( size > 0 )
987 	{
988 		if( size >= LIBHMAC_SHA512_BLOCK_SIZE )
989 		{
990 			libcerror_error_set(
991 			 error,
992 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
993 			 LIBCERROR_RUNTIME_ERROR_VALUE_OUT_OF_BOUNDS,
994 			 "%s: invalid size value out of bounds.",
995 			 function );
996 
997 			return( -1 );
998 		}
999 		if( memory_copy(
1000 		     internal_context->block,
1001 		     &( buffer[ buffer_offset ] ),
1002 		     size ) == NULL )
1003 		{
1004 			libcerror_error_set(
1005 			 error,
1006 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
1007 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1008 			 "%s: unable to copy remaining data to context block.",
1009 			 function );
1010 
1011 			return( -1 );
1012 		}
1013 		internal_context->block_offset = size;
1014 	}
1015 	return( 1 );
1016 }
1017 
1018 #endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_SHA_H ) && defined( SHA512_DIGEST_LENGTH ) */
1019 
1020 #if defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_SHA_H ) && defined( SHA512_DIGEST_LENGTH )
1021 
1022 /* Finalizes the SHA-512 context using OpenSSL
1023  * Returns 1 if successful or -1 on error
1024  */
libhmac_sha512_finalize(libhmac_sha512_context_t * context,uint8_t * hash,size_t hash_size,libcerror_error_t ** error)1025 int libhmac_sha512_finalize(
1026      libhmac_sha512_context_t *context,
1027      uint8_t *hash,
1028      size_t hash_size,
1029      libcerror_error_t **error )
1030 {
1031 	libhmac_internal_sha512_context_t *internal_context = NULL;
1032 	static char *function                               = "libhmac_sha512_finalize";
1033 
1034 	if( context == NULL )
1035 	{
1036 		libcerror_error_set(
1037 		 error,
1038 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1039 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1040 		 "%s: invalid context.",
1041 		 function );
1042 
1043 		return( -1 );
1044 	}
1045 	internal_context = (libhmac_internal_sha512_context_t *) context;
1046 
1047 	if( hash == NULL )
1048 	{
1049 		libcerror_error_set(
1050 		 error,
1051 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1052 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1053 		 "%s: invalid hash.",
1054 		 function );
1055 
1056 		return( -1 );
1057 	}
1058 	if( hash_size > (size_t) SSIZE_MAX )
1059 	{
1060 		libcerror_error_set(
1061 		 error,
1062 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1063 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1064 		 "%s: invalid hash size value exceeds maximum.",
1065 		 function );
1066 
1067 		return( -1 );
1068 	}
1069 	if( hash_size < (size_t) LIBHMAC_SHA512_HASH_SIZE )
1070 	{
1071 		libcerror_error_set(
1072 		 error,
1073 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1074 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1075 		 "%s: invalid hash size value too small.",
1076 		 function );
1077 
1078 		return( -1 );
1079 	}
1080 	if( SHA512_Final(
1081 	     hash,
1082 	     &( internal_context->sha512_context ) ) != 1 )
1083 	{
1084 		libcerror_error_set(
1085 		 error,
1086 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1087 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1088 		 "%s: unable to finalize context.",
1089 		 function );
1090 
1091 		return( -1 );
1092 	}
1093 	return( 1 );
1094 }
1095 
1096 #elif defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_EVP_H ) && defined( HAVE_EVP_SHA512 )
1097 
1098 /* Finalizes the SHA-512 context using OpenSSL EVP
1099  * Returns 1 if successful or -1 on error
1100  */
libhmac_sha512_finalize(libhmac_sha512_context_t * context,uint8_t * hash,size_t hash_size,libcerror_error_t ** error)1101 int libhmac_sha512_finalize(
1102      libhmac_sha512_context_t *context,
1103      uint8_t *hash,
1104      size_t hash_size,
1105      libcerror_error_t **error )
1106 {
1107 	libhmac_internal_sha512_context_t *internal_context = NULL;
1108 	static char *function                               = "libhmac_sha512_finalize";
1109 	unsigned int safe_hash_size                         = 0;
1110 
1111 	if( context == NULL )
1112 	{
1113 		libcerror_error_set(
1114 		 error,
1115 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1116 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1117 		 "%s: invalid context.",
1118 		 function );
1119 
1120 		return( -1 );
1121 	}
1122 	internal_context = (libhmac_internal_sha512_context_t *) context;
1123 
1124 	if( hash == NULL )
1125 	{
1126 		libcerror_error_set(
1127 		 error,
1128 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1129 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1130 		 "%s: invalid hash.",
1131 		 function );
1132 
1133 		return( -1 );
1134 	}
1135 	if( hash_size > (size_t) UINT_MAX )
1136 	{
1137 		libcerror_error_set(
1138 		 error,
1139 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1140 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1141 		 "%s: invalid hash size value exceeds maximum.",
1142 		 function );
1143 
1144 		return( -1 );
1145 	}
1146 	if( hash_size < (size_t) LIBHMAC_SHA512_HASH_SIZE )
1147 	{
1148 		libcerror_error_set(
1149 		 error,
1150 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1151 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1152 		 "%s: invalid hash size value too small.",
1153 		 function );
1154 
1155 		return( -1 );
1156 	}
1157 	safe_hash_size = (unsigned int) hash_size;
1158 
1159 	if( EVP_DigestFinal_ex(
1160 	     internal_context->evp_md_context,
1161 	     (unsigned char *) hash,
1162 	     &safe_hash_size ) != 1 )
1163 	{
1164 		libcerror_error_set(
1165 		 error,
1166 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1167 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1168 		 "%s: unable to finalize context.",
1169 		 function );
1170 
1171 		return( -1 );
1172 	}
1173 	return( 1 );
1174 }
1175 
1176 #else
1177 
1178 /* Finalizes the SHA-512 context using fallback implementation
1179  * Returns 1 if successful or -1 on error
1180  */
libhmac_sha512_finalize(libhmac_sha512_context_t * context,uint8_t * hash,size_t hash_size,libcerror_error_t ** error)1181 int libhmac_sha512_finalize(
1182      libhmac_sha512_context_t *context,
1183      uint8_t *hash,
1184      size_t hash_size,
1185      libcerror_error_t **error )
1186 {
1187 	libhmac_internal_sha512_context_t *internal_context = NULL;
1188 	static char *function                               = "libhmac_sha512_finalize";
1189 	size_t block_size                                   = 0;
1190 	size_t number_of_blocks                             = 0;
1191 	ssize_t process_count                               = 0;
1192 	uint64_t bit_size                                   = 0;
1193 
1194 #if !defined( LIBHMAC_UNFOLLED_LOOPS )
1195 	size_t hash_index                                   = 0;
1196 	int hash_values_index                               = 0;
1197 #endif
1198 
1199 	if( context == NULL )
1200 	{
1201 		libcerror_error_set(
1202 		 error,
1203 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1204 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1205 		 "%s: invalid context.",
1206 		 function );
1207 
1208 		return( -1 );
1209 	}
1210 	internal_context = (libhmac_internal_sha512_context_t *) context;
1211 
1212 	if( hash == NULL )
1213 	{
1214 		libcerror_error_set(
1215 		 error,
1216 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1217 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1218 		 "%s: invalid hash.",
1219 		 function );
1220 
1221 		return( -1 );
1222 	}
1223 	if( hash_size < (size_t) LIBHMAC_SHA512_HASH_SIZE )
1224 	{
1225 		libcerror_error_set(
1226 		 error,
1227 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1228 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1229 		 "%s: invalid hash value too small.",
1230 		 function );
1231 
1232 		return( -1 );
1233 	}
1234 	if( hash_size > (size_t) SSIZE_MAX )
1235 	{
1236 		libcerror_error_set(
1237 		 error,
1238 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1239 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1240 		 "%s: invalid hash size value exceeds maximum.",
1241 		 function );
1242 
1243 		return( -1 );
1244 	}
1245 	if( hash_size < (size_t) LIBHMAC_SHA512_HASH_SIZE )
1246 	{
1247 		libcerror_error_set(
1248 		 error,
1249 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1250 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1251 		 "%s: invalid hash size value too small.",
1252 		 function );
1253 
1254 		return( -1 );
1255 	}
1256 	/* Add padding with a size of 120 mod 128
1257 	 */
1258 	number_of_blocks = 1;
1259 
1260 	if( internal_context->block_offset > 119 )
1261 	{
1262 		number_of_blocks += 1;
1263 	}
1264 	block_size = number_of_blocks * LIBHMAC_SHA512_BLOCK_SIZE;
1265 
1266 	if( memory_set(
1267 	     &( internal_context->block[ internal_context->block_offset ] ),
1268 	     0,
1269 	     block_size - internal_context->block_offset ) == NULL )
1270 	{
1271 		libcerror_error_set(
1272 		 error,
1273 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1274 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1275 		 "%s: unable to clear context block.",
1276 		 function );
1277 
1278 		return( -1 );
1279 	}
1280 	/* The first byte of the padding contains 0x80
1281 	 */
1282 	internal_context->block[ internal_context->block_offset ] = 0x80;
1283 
1284 	bit_size = ( internal_context->hash_count + internal_context->block_offset ) * 8;
1285 
1286 	byte_stream_copy_from_uint64_big_endian(
1287 	 &( internal_context->block[ block_size - 8 ] ),
1288 	 bit_size );
1289 
1290 	process_count = libhmac_sha512_transform(
1291 	                 internal_context,
1292 	                 internal_context->block,
1293 	                 block_size,
1294 	                 error );
1295 
1296 	if( process_count == -1 )
1297 	{
1298 		libcerror_error_set(
1299 		 error,
1300 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1301 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1302 		 "%s: unable to transform context block.",
1303 		 function );
1304 
1305 		return( -1 );
1306 	}
1307 #if !defined( LIBHMAC_UNFOLLED_LOOPS )
1308 	for( hash_values_index = 0;
1309 	     hash_values_index < 8;
1310 	     hash_values_index++ )
1311 	{
1312 		byte_stream_copy_from_uint64_big_endian(
1313 		 &( hash[ hash_index ] ),
1314 		 internal_context->hash_values[ hash_values_index ] );
1315 
1316 		hash_index += sizeof( uint64_t );
1317 	}
1318 #else
1319 	byte_stream_copy_from_uint64_big_endian(
1320 	 &( hash[ 0 ] ),
1321 	 internal_context->hash_values[ 0 ] );
1322 
1323 	byte_stream_copy_from_uint64_big_endian(
1324 	 &( hash[ 8 ] ),
1325 	 internal_context->hash_values[ 1 ] );
1326 
1327 	byte_stream_copy_from_uint64_big_endian(
1328 	 &( hash[ 16 ] ),
1329 	 internal_context->hash_values[ 2 ] );
1330 
1331 	byte_stream_copy_from_uint64_big_endian(
1332 	 &( hash[ 24 ] ),
1333 	 internal_context->hash_values[ 3 ] );
1334 
1335 	byte_stream_copy_from_uint64_big_endian(
1336 	 &( hash[ 32 ] ),
1337 	 internal_context->hash_values[ 4 ] );
1338 
1339 	byte_stream_copy_from_uint64_big_endian(
1340 	 &( hash[ 40 ] ),
1341 	 internal_context->hash_values[ 5 ] );
1342 
1343 	byte_stream_copy_from_uint64_big_endian(
1344 	 &( hash[ 48 ] ),
1345 	 internal_context->hash_values[ 6 ] );
1346 
1347 	byte_stream_copy_from_uint64_big_endian(
1348 	 &( hash[ 56 ] ),
1349 	 internal_context->hash_values[ 7 ] );
1350 
1351 #endif /* !defined( LIBHMAC_UNFOLLED_LOOPS ) */
1352 
1353 	/* Prevent sensitive data from leaking
1354 	 */
1355 	if( memory_set(
1356 	     internal_context,
1357 	     0,
1358 	     sizeof( libhmac_internal_sha512_context_t ) ) == NULL )
1359 	{
1360 		libcerror_error_set(
1361 		 error,
1362 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1363 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1364 		 "%s: unable to clear context.",
1365 		 function );
1366 
1367 		return( -1 );
1368 	}
1369 	return( 1 );
1370 }
1371 
1372 #endif /* defined( HAVE_LIBCRYPTO ) && defined( HAVE_OPENSSL_SHA_H ) && defined( SHA512_DIGEST_LENGTH ) */
1373 
1374 /* Calculates the SHA-512 of the buffer
1375  * Returns 1 if successful or -1 on error
1376  */
libhmac_sha512_calculate(const uint8_t * buffer,size_t size,uint8_t * hash,size_t hash_size,libcerror_error_t ** error)1377 int libhmac_sha512_calculate(
1378      const uint8_t *buffer,
1379      size_t size,
1380      uint8_t *hash,
1381      size_t hash_size,
1382      libcerror_error_t **error )
1383 {
1384 	libhmac_sha512_context_t *context = NULL;
1385 	static char *function             = "libhmac_sha512_calculate";
1386 
1387 	if( libhmac_sha512_initialize(
1388 	     &context,
1389 	     error ) != 1 )
1390 	{
1391 		libcerror_error_set(
1392 		 error,
1393 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1394 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1395 		 "%s: unable to initialize context.",
1396 		 function );
1397 
1398 		goto on_error;
1399 	}
1400 	if( libhmac_sha512_update(
1401 	     context,
1402 	     buffer,
1403 	     size,
1404 	     error ) != 1 )
1405 	{
1406 		libcerror_error_set(
1407 		 error,
1408 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1409 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1410 		 "%s: unable to update context.",
1411 		 function );
1412 
1413 		goto on_error;
1414 	}
1415 	if( libhmac_sha512_finalize(
1416 	     context,
1417 	     hash,
1418 	     hash_size,
1419 	     error ) != 1 )
1420 	{
1421 		libcerror_error_set(
1422 		 error,
1423 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1424 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1425 		 "%s: unable to finalize context.",
1426 		 function );
1427 
1428 		goto on_error;
1429 	}
1430 	if( libhmac_sha512_free(
1431 	     &context,
1432 	     error ) != 1 )
1433 	{
1434 		libcerror_error_set(
1435 		 error,
1436 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1437 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1438 		 "%s: unable to free context.",
1439 		 function );
1440 
1441 		goto on_error;
1442 	}
1443 	return( 1 );
1444 
1445 on_error:
1446 	if( context != NULL )
1447 	{
1448 		libhmac_sha512_free(
1449 		 &context,
1450 		 NULL );
1451 	}
1452 	return( -1 );
1453 }
1454 
1455 /* Calculates the SHA-512 HMAC of the buffer
1456  * HMAC is defined in RFC 2104
1457  * Returns 1 if successful or -1 on error
1458  */
libhmac_sha512_calculate_hmac(const uint8_t * key,size_t key_size,const uint8_t * buffer,size_t size,uint8_t * hmac,size_t hmac_size,libcerror_error_t ** error)1459 int libhmac_sha512_calculate_hmac(
1460      const uint8_t *key,
1461      size_t key_size,
1462      const uint8_t *buffer,
1463      size_t size,
1464      uint8_t *hmac,
1465      size_t hmac_size,
1466      libcerror_error_t **error )
1467 {
1468 	uint8_t key_hash[ LIBHMAC_SHA512_HASH_SIZE ];
1469 
1470 	libhmac_sha512_context_t *context = NULL;
1471 	uint8_t *key_data                 = NULL;
1472 	uint8_t *inner_padding            = NULL;
1473 	uint8_t *outer_padding            = NULL;
1474 	static char *function             = "libhmac_sha512_calculate_hmac";
1475 	size_t block_index                = 0;
1476 	size_t block_size                 = 128;
1477 
1478 	if( key == NULL )
1479 	{
1480 		libcerror_error_set(
1481 		 error,
1482 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1483 		 LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
1484 		 "%s: invalid key.",
1485 		 function );
1486 
1487 		return( -1 );
1488 	}
1489 	if( key_size > (size_t) SSIZE_MAX )
1490 	{
1491 		libcerror_error_set(
1492 		 error,
1493 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1494 		 LIBCERROR_ARGUMENT_ERROR_VALUE_EXCEEDS_MAXIMUM,
1495 		 "%s: invalid key size value exceeds maximum.",
1496 		 function );
1497 
1498 		return( -1 );
1499 	}
1500 	if( hmac_size < (size_t) LIBHMAC_SHA512_HASH_SIZE )
1501 	{
1502 		libcerror_error_set(
1503 		 error,
1504 		 LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
1505 		 LIBCERROR_ARGUMENT_ERROR_VALUE_TOO_SMALL,
1506 		 "%s: invalid HMAC size value too small.",
1507 		 function );
1508 
1509 		return( -1 );
1510 	}
1511 	key_data = (uint8_t *) memory_allocate(
1512 	                        sizeof( uint8_t ) * block_size );
1513 
1514 	if( key_data == NULL )
1515 	{
1516 		libcerror_error_set(
1517 		 error,
1518 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1519 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1520 		 "%s: unable to create key data.",
1521 		 function );
1522 
1523 		goto on_error;
1524 	}
1525 	if( key_size <= block_size )
1526 	{
1527 		if( memory_copy(
1528 		     key_data,
1529 		     key,
1530 		     key_size ) == NULL )
1531 		{
1532 			libcerror_error_set(
1533 			 error,
1534 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
1535 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1536 			 "%s: unable to copy key data.",
1537 			 function );
1538 
1539 			goto on_error;
1540 		}
1541 		if( memory_set(
1542 		     &( key_data[ key_size ] ),
1543 		     0,
1544 		     block_size - key_size ) == NULL )
1545 		{
1546 			libcerror_error_set(
1547 			 error,
1548 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
1549 			 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1550 			 "%s: unable to clear key remaining data.",
1551 			 function );
1552 
1553 			goto on_error;
1554 		}
1555 	}
1556 	else
1557 	{
1558 		if( libhmac_sha512_initialize(
1559 		     &context,
1560 		     error ) != 1 )
1561 		{
1562 			libcerror_error_set(
1563 			 error,
1564 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1565 			 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1566 			 "%s: unable to initialize context.",
1567 			 function );
1568 
1569 			goto on_error;
1570 		}
1571 		if( libhmac_sha512_update(
1572 		     context,
1573 		     key,
1574 		     key_size,
1575 		     error ) != 1 )
1576 		{
1577 			libcerror_error_set(
1578 			 error,
1579 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1580 			 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1581 			 "%s: unable to update context.",
1582 			 function );
1583 
1584 			goto on_error;
1585 		}
1586 		if( libhmac_sha512_finalize(
1587 		     context,
1588 		     key_hash,
1589 		     LIBHMAC_SHA512_HASH_SIZE,
1590 		     error ) != 1 )
1591 		{
1592 			libcerror_error_set(
1593 			 error,
1594 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1595 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1596 			 "%s: unable to finalize context.",
1597 			 function );
1598 
1599 			goto on_error;
1600 		}
1601 		if( libhmac_sha512_free(
1602 		     &context,
1603 		     error ) != 1 )
1604 		{
1605 			libcerror_error_set(
1606 			 error,
1607 			 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1608 			 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1609 			 "%s: unable to free context.",
1610 			 function );
1611 
1612 			goto on_error;
1613 		}
1614 		if( block_size > LIBHMAC_SHA512_HASH_SIZE )
1615 		{
1616 			if( memory_set(
1617 			     &( key_data[ LIBHMAC_SHA512_HASH_SIZE ] ),
1618 			     0,
1619 			     block_size - LIBHMAC_SHA512_HASH_SIZE ) == NULL )
1620 			{
1621 				libcerror_error_set(
1622 				 error,
1623 				 LIBCERROR_ERROR_DOMAIN_MEMORY,
1624 				 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1625 				 "%s: unable to clear remaining key data.",
1626 				 function );
1627 
1628 				goto on_error;
1629 			}
1630 		}
1631 		if( memory_copy(
1632 		     key_data,
1633 		     key_hash,
1634 		     LIBHMAC_SHA512_HASH_SIZE ) == NULL )
1635 		{
1636 			libcerror_error_set(
1637 			 error,
1638 			 LIBCERROR_ERROR_DOMAIN_MEMORY,
1639 			 LIBCERROR_MEMORY_ERROR_COPY_FAILED,
1640 			 "%s: unable to copy key hash data.",
1641 			 function );
1642 
1643 			goto on_error;
1644 		}
1645 	}
1646 	inner_padding = (uint8_t *) memory_allocate(
1647 	                             sizeof( uint8_t ) * block_size );
1648 
1649 	if( inner_padding == NULL )
1650 	{
1651 		libcerror_error_set(
1652 		 error,
1653 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1654 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1655 		 "%s: unable to create inner padding.",
1656 		 function );
1657 
1658 		goto on_error;
1659 	}
1660 	if( memory_set(
1661 	     inner_padding,
1662 	     0x36,
1663 	     block_size ) == NULL )
1664 	{
1665 		libcerror_error_set(
1666 		 error,
1667 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1668 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1669 		 "%s: unable to set inner padding.",
1670 		 function );
1671 
1672 		goto on_error;
1673 	}
1674 	outer_padding = (uint8_t *) memory_allocate(
1675 	                             sizeof( uint8_t ) * block_size );
1676 
1677 	if( outer_padding == NULL )
1678 	{
1679 		libcerror_error_set(
1680 		 error,
1681 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1682 		 LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
1683 		 "%s: unable to create outer padding.",
1684 		 function );
1685 
1686 		goto on_error;
1687 	}
1688 	if( memory_set(
1689 	     outer_padding,
1690 	     0x5c,
1691 	     block_size ) == NULL )
1692 	{
1693 		libcerror_error_set(
1694 		 error,
1695 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1696 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1697 		 "%s: unable to set outer padding.",
1698 		 function );
1699 
1700 		goto on_error;
1701 	}
1702 	for( block_index = 0;
1703 	     block_index < block_size;
1704 	     block_index++ )
1705 	{
1706 		inner_padding[ block_index ] ^= key_data[ block_index ];
1707 		outer_padding[ block_index ] ^= key_data[ block_index ];
1708 	}
1709 	if( libhmac_sha512_initialize(
1710 	     &context,
1711 	     error ) != 1 )
1712 	{
1713 		libcerror_error_set(
1714 		 error,
1715 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1716 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1717 		 "%s: unable to initialize context.",
1718 		 function );
1719 
1720 		goto on_error;
1721 	}
1722 	if( libhmac_sha512_update(
1723 	     context,
1724 	     inner_padding,
1725 	     block_size,
1726 	     error ) != 1 )
1727 	{
1728 		libcerror_error_set(
1729 		 error,
1730 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1731 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1732 		 "%s: unable to update context.",
1733 		 function );
1734 
1735 		goto on_error;
1736 	}
1737 	if( libhmac_sha512_update(
1738 	     context,
1739 	     buffer,
1740 	     size,
1741 	     error ) != 1 )
1742 	{
1743 		libcerror_error_set(
1744 		 error,
1745 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1746 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1747 		 "%s: unable to update context.",
1748 		 function );
1749 
1750 		goto on_error;
1751 	}
1752 	if( libhmac_sha512_finalize(
1753 	     context,
1754 	     hmac,
1755 	     hmac_size,
1756 	     error ) != 1 )
1757 	{
1758 		libcerror_error_set(
1759 		 error,
1760 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1761 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1762 		 "%s: unable to finalize context.",
1763 		 function );
1764 
1765 		goto on_error;
1766 	}
1767 	if( libhmac_sha512_free(
1768 	     &context,
1769 	     error ) != 1 )
1770 	{
1771 		libcerror_error_set(
1772 		 error,
1773 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1774 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1775 		 "%s: unable to free context.",
1776 		 function );
1777 
1778 		goto on_error;
1779 	}
1780 	if( libhmac_sha512_initialize(
1781 	     &context,
1782 	     error ) != 1 )
1783 	{
1784 		libcerror_error_set(
1785 		 error,
1786 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1787 		 LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
1788 		 "%s: unable to initialize context.",
1789 		 function );
1790 
1791 		goto on_error;
1792 	}
1793 	if( libhmac_sha512_update(
1794 	     context,
1795 	     outer_padding,
1796 	     block_size,
1797 	     error ) != 1 )
1798 	{
1799 		libcerror_error_set(
1800 		 error,
1801 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1802 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1803 		 "%s: unable to update context.",
1804 		 function );
1805 
1806 		goto on_error;
1807 	}
1808 	if( libhmac_sha512_update(
1809 	     context,
1810 	     hmac,
1811 	     LIBHMAC_SHA512_HASH_SIZE,
1812 	     error ) != 1 )
1813 	{
1814 		libcerror_error_set(
1815 		 error,
1816 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1817 		 LIBCERROR_RUNTIME_ERROR_SET_FAILED,
1818 		 "%s: unable to update context.",
1819 		 function );
1820 
1821 		goto on_error;
1822 	}
1823 	if( libhmac_sha512_finalize(
1824 	     context,
1825 	     hmac,
1826 	     hmac_size,
1827 	     error ) != 1 )
1828 	{
1829 		libcerror_error_set(
1830 		 error,
1831 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1832 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1833 		 "%s: unable to finalize context.",
1834 		 function );
1835 
1836 		goto on_error;
1837 	}
1838 	if( libhmac_sha512_free(
1839 	     &context,
1840 	     error ) != 1 )
1841 	{
1842 		libcerror_error_set(
1843 		 error,
1844 		 LIBCERROR_ERROR_DOMAIN_RUNTIME,
1845 		 LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
1846 		 "%s: unable to free context.",
1847 		 function );
1848 
1849 		goto on_error;
1850 	}
1851 	if( memory_set(
1852 	     outer_padding,
1853 	     0,
1854 	     block_size ) == NULL )
1855 	{
1856 		libcerror_error_set(
1857 		 error,
1858 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1859 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1860 		 "%s: unable to clear outer padding.",
1861 		 function );
1862 
1863 		goto on_error;
1864 	}
1865 	memory_free(
1866 	 outer_padding );
1867 
1868 	outer_padding = NULL;
1869 
1870 	if( memory_set(
1871 	     inner_padding,
1872 	     0,
1873 	     block_size ) == NULL )
1874 	{
1875 		libcerror_error_set(
1876 		 error,
1877 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1878 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1879 		 "%s: unable to clear inner padding.",
1880 		 function );
1881 
1882 		goto on_error;
1883 	}
1884 	memory_free(
1885 	 inner_padding );
1886 
1887 	inner_padding = NULL;
1888 
1889 	if( memory_set(
1890 	     key_data,
1891 	     0,
1892 	     block_size ) == NULL )
1893 	{
1894 		libcerror_error_set(
1895 		 error,
1896 		 LIBCERROR_ERROR_DOMAIN_MEMORY,
1897 		 LIBCERROR_MEMORY_ERROR_SET_FAILED,
1898 		 "%s: unable to clear key data.",
1899 		 function );
1900 
1901 		goto on_error;
1902 	}
1903 	memory_free(
1904 	 key_data );
1905 
1906 	key_data = NULL;
1907 
1908 	return( 1 );
1909 
1910 on_error:
1911 	if( context != NULL )
1912 	{
1913 		libhmac_sha512_free(
1914 		 &context,
1915 		 NULL );
1916 	}
1917 	if( outer_padding != NULL )
1918 	{
1919 		memory_set(
1920         	 outer_padding,
1921 	         0,
1922         	 block_size );
1923 
1924 		memory_free(
1925 		 outer_padding );
1926 	}
1927 	if( inner_padding != NULL )
1928 	{
1929 		memory_set(
1930         	 inner_padding,
1931 	         0,
1932         	 block_size );
1933 
1934 		memory_free(
1935 		 inner_padding );
1936 	}
1937 	if( key_data != NULL )
1938 	{
1939 		memory_set(
1940         	 key_data,
1941 	         0,
1942         	 block_size );
1943 
1944 		memory_free(
1945 		 key_data );
1946 	}
1947 	return( -1 );
1948 }
1949 
1950