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