/src/fluent-bit/src/flb_hmac.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* Fluent Bit |
2 | | * ========== |
3 | | * Copyright (C) 2019-2020 The Fluent Bit Authors |
4 | | * |
5 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
6 | | * you may not use this file except in compliance with the License. |
7 | | * You may obtain a copy of the License at |
8 | | * |
9 | | * http://www.apache.org/licenses/LICENSE-2.0 |
10 | | * |
11 | | * Unless required by applicable law or agreed to in writing, software |
12 | | * distributed under the License is distributed on an "AS IS" BASIS, |
13 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
14 | | * See the License for the specific language governing permissions and |
15 | | * limitations under the License. |
16 | | */ |
17 | | |
18 | | #include <fluent-bit/flb_hmac.h> |
19 | | #include <fluent-bit/flb_mem.h> |
20 | | |
21 | | #if FLB_CRYPTO_OPENSSL_COMPAT_MODE >= 3 |
22 | | #include <openssl/params.h> |
23 | | #endif |
24 | | |
25 | | #include <openssl/evp.h> |
26 | | #include <openssl/bio.h> |
27 | | #include <string.h> |
28 | | |
29 | | #if FLB_CRYPTO_OPENSSL_COMPAT_MODE >= 3 |
30 | | static const char *flb_crypto_get_algorithm_name_by_id(int algorithm_id) |
31 | | { |
32 | | const char *algorithm_name; |
33 | | |
34 | | if (algorithm_id == FLB_HASH_SHA256) { |
35 | | algorithm_name = "SHA-256"; |
36 | | } |
37 | | else if (algorithm_id == FLB_HASH_SHA512) { |
38 | | algorithm_name = "SHA-512"; |
39 | | } |
40 | | else if (algorithm_id == FLB_HASH_MD5) { |
41 | | algorithm_name = "MD5"; |
42 | | } |
43 | | else { |
44 | | algorithm_name = NULL; |
45 | | } |
46 | | |
47 | | return algorithm_name; |
48 | | } |
49 | | |
50 | | int flb_hmac_init(struct flb_hmac *context, |
51 | | int algorithm_id, |
52 | | unsigned char *key, |
53 | | size_t key_length) |
54 | | { |
55 | | const char *digest_algorithm_name; |
56 | | OSSL_PARAM hmac_parameters[2]; |
57 | | int result; |
58 | | |
59 | | |
60 | | if (context == NULL) { |
61 | | return FLB_CRYPTO_INVALID_ARGUMENT; |
62 | | } |
63 | | |
64 | | if (key == NULL) { |
65 | | return FLB_CRYPTO_INVALID_ARGUMENT; |
66 | | } |
67 | | |
68 | | if (key_length == 0) { |
69 | | return FLB_CRYPTO_INVALID_ARGUMENT; |
70 | | } |
71 | | |
72 | | memset(context, 0, sizeof(struct flb_hmac)); |
73 | | |
74 | | digest_algorithm_name = flb_crypto_get_algorithm_name_by_id(algorithm_id); |
75 | | |
76 | | if (digest_algorithm_name == NULL) { |
77 | | return FLB_CRYPTO_INVALID_ARGUMENT; |
78 | | } |
79 | | |
80 | | context->mac_algorithm = EVP_MAC_fetch(NULL, "HMAC", NULL); |
81 | | |
82 | | if (context->mac_algorithm == NULL) { |
83 | | context->last_error = ERR_get_error(); |
84 | | |
85 | | flb_hmac_cleanup(context); |
86 | | |
87 | | return FLB_CRYPTO_INVALID_ARGUMENT; |
88 | | } |
89 | | |
90 | | context->backend_context = EVP_MAC_CTX_new(context->mac_algorithm); |
91 | | |
92 | | if (context->backend_context == NULL) { |
93 | | context->last_error = ERR_get_error(); |
94 | | |
95 | | flb_hmac_cleanup(context); |
96 | | |
97 | | return FLB_CRYPTO_BACKEND_ERROR; |
98 | | } |
99 | | |
100 | | hmac_parameters[0] = OSSL_PARAM_construct_utf8_string("digest", |
101 | | (char *) digest_algorithm_name, |
102 | | 0); |
103 | | hmac_parameters[1] = OSSL_PARAM_construct_end(); |
104 | | |
105 | | |
106 | | result = EVP_MAC_init(context->backend_context, |
107 | | key, key_length, |
108 | | hmac_parameters); |
109 | | |
110 | | if (result == 0) { |
111 | | context->last_error = ERR_get_error(); |
112 | | |
113 | | return FLB_CRYPTO_BACKEND_ERROR; |
114 | | } |
115 | | |
116 | | context->digest_size = EVP_MAC_CTX_get_mac_size(context->backend_context); |
117 | | |
118 | | return FLB_CRYPTO_SUCCESS; |
119 | | } |
120 | | |
121 | | #else |
122 | | |
123 | | static const EVP_MD *flb_crypto_get_digest_algorithm_instance_by_id(int algorithm_id) |
124 | 1.46k | { |
125 | 1.46k | const EVP_MD *algorithm; |
126 | | |
127 | 1.46k | if (algorithm_id == FLB_HASH_SHA256) { |
128 | 1.46k | algorithm = EVP_sha256(); |
129 | 1.46k | } |
130 | 0 | else if (algorithm_id == FLB_HASH_SHA512) { |
131 | 0 | algorithm = EVP_sha512(); |
132 | 0 | } |
133 | 0 | else if (algorithm_id == FLB_HASH_MD5) { |
134 | 0 | algorithm = EVP_md5(); |
135 | 0 | } |
136 | 0 | else { |
137 | 0 | algorithm = NULL; |
138 | 0 | } |
139 | | |
140 | 1.46k | return algorithm; |
141 | 1.46k | } |
142 | | |
143 | | int flb_hmac_init(struct flb_hmac *context, |
144 | | int algorithm_id, |
145 | | unsigned char *key, |
146 | | size_t key_length) |
147 | 1.46k | { |
148 | 1.46k | const EVP_MD *digest_algorithm_instance; |
149 | 1.46k | int result; |
150 | | |
151 | | |
152 | 1.46k | if (context == NULL) { |
153 | 0 | return FLB_CRYPTO_INVALID_ARGUMENT; |
154 | 0 | } |
155 | | |
156 | 1.46k | if (key == NULL) { |
157 | 0 | return FLB_CRYPTO_INVALID_ARGUMENT; |
158 | 0 | } |
159 | | |
160 | 1.46k | if (key_length == 0) { |
161 | 0 | return FLB_CRYPTO_INVALID_ARGUMENT; |
162 | 0 | } |
163 | | |
164 | 1.46k | memset(context, 0, sizeof(struct flb_hmac)); |
165 | | |
166 | 1.46k | digest_algorithm_instance = flb_crypto_get_digest_algorithm_instance_by_id(algorithm_id); |
167 | | |
168 | 1.46k | if (digest_algorithm_instance == NULL) { |
169 | 0 | return FLB_CRYPTO_INVALID_ARGUMENT; |
170 | 0 | } |
171 | | |
172 | | #if FLB_CRYPTO_OPENSSL_COMPAT_MODE == 0 |
173 | | context->backend_context = flb_calloc(1, sizeof(HMAC_CTX)); |
174 | | |
175 | | if (context->backend_context == NULL) { |
176 | | return FLB_CRYPTO_ALLOCATION_ERROR; |
177 | | } |
178 | | |
179 | | HMAC_CTX_init(context->backend_context); |
180 | | #else |
181 | 1.46k | context->backend_context = HMAC_CTX_new(); |
182 | | |
183 | 1.46k | if (context->backend_context == NULL) { |
184 | 0 | context->last_error = ERR_get_error(); |
185 | |
|
186 | 0 | return FLB_CRYPTO_BACKEND_ERROR; |
187 | 0 | } |
188 | 1.46k | #endif |
189 | | |
190 | 1.46k | result = HMAC_Init_ex(context->backend_context, |
191 | 1.46k | key, key_length, |
192 | 1.46k | digest_algorithm_instance, |
193 | 1.46k | NULL); |
194 | | |
195 | 1.46k | if (result != 1) { |
196 | 0 | context->last_error = ERR_get_error(); |
197 | |
|
198 | 0 | return FLB_CRYPTO_BACKEND_ERROR; |
199 | 0 | } |
200 | | |
201 | 1.46k | context->digest_size = EVP_MD_size(digest_algorithm_instance); |
202 | | |
203 | 1.46k | return FLB_CRYPTO_SUCCESS; |
204 | 1.46k | } |
205 | | #endif |
206 | | |
207 | | int flb_hmac_finalize(struct flb_hmac *context, |
208 | | unsigned char *signature_buffer, |
209 | | size_t signature_buffer_size) |
210 | 1.46k | { |
211 | 1.46k | size_t signature_length; |
212 | 1.46k | int error_detected; |
213 | 1.46k | int result; |
214 | | |
215 | 1.46k | if (context->backend_context == NULL) { |
216 | 0 | return FLB_CRYPTO_INVALID_ARGUMENT; |
217 | 0 | } |
218 | | |
219 | 1.46k | if (signature_buffer == NULL) { |
220 | 0 | return FLB_CRYPTO_INVALID_ARGUMENT; |
221 | 0 | } |
222 | | |
223 | 1.46k | if (signature_buffer_size < context->digest_size) { |
224 | 0 | return FLB_CRYPTO_INVALID_ARGUMENT; |
225 | 0 | } |
226 | | |
227 | | #if FLB_CRYPTO_OPENSSL_COMPAT_MODE >= 3 |
228 | | result = EVP_MAC_final(context->backend_context, |
229 | | signature_buffer, |
230 | | &signature_length, |
231 | | signature_buffer_size); |
232 | | |
233 | | error_detected = (result == 0); |
234 | | #else |
235 | 1.46k | signature_length = 0; |
236 | | |
237 | 1.46k | result = HMAC_Final(context->backend_context, |
238 | 1.46k | signature_buffer, |
239 | 1.46k | (unsigned int *) &signature_length); |
240 | | |
241 | 1.46k | error_detected = (result != 1); |
242 | 1.46k | #endif |
243 | | |
244 | 1.46k | if (error_detected) { |
245 | 0 | context->last_error = ERR_get_error(); |
246 | |
|
247 | 0 | return FLB_CRYPTO_BACKEND_ERROR; |
248 | 0 | } |
249 | | |
250 | 1.46k | (void) signature_length; |
251 | | |
252 | 1.46k | return FLB_CRYPTO_SUCCESS; |
253 | 1.46k | } |
254 | | |
255 | | int flb_hmac_update(struct flb_hmac *context, |
256 | | unsigned char *data, |
257 | | size_t data_length) |
258 | 1.46k | { |
259 | 1.46k | int error_detected; |
260 | 1.46k | int result; |
261 | | |
262 | 1.46k | if (context->backend_context == NULL) { |
263 | 0 | return FLB_CRYPTO_INVALID_ARGUMENT; |
264 | 0 | } |
265 | | |
266 | 1.46k | if (data == NULL) { |
267 | 0 | return FLB_CRYPTO_INVALID_ARGUMENT; |
268 | 0 | } |
269 | | |
270 | | #if FLB_CRYPTO_OPENSSL_COMPAT_MODE >= 3 |
271 | | result = EVP_MAC_update(context->backend_context, |
272 | | data, |
273 | | data_length); |
274 | | |
275 | | error_detected = (result == 0); |
276 | | #else |
277 | 1.46k | result = HMAC_Update(context->backend_context, |
278 | 1.46k | data, |
279 | 1.46k | data_length); |
280 | | |
281 | 1.46k | error_detected = (result != 1); |
282 | 1.46k | #endif |
283 | | |
284 | 1.46k | if (error_detected) { |
285 | 0 | context->last_error = ERR_get_error(); |
286 | |
|
287 | 0 | return FLB_CRYPTO_BACKEND_ERROR; |
288 | 0 | } |
289 | | |
290 | 1.46k | return FLB_CRYPTO_SUCCESS; |
291 | 1.46k | } |
292 | | |
293 | | int flb_hmac_cleanup(struct flb_hmac *context) |
294 | 1.46k | { |
295 | | #if FLB_CRYPTO_OPENSSL_COMPAT_MODE >= 3 |
296 | | if (context->backend_context != NULL) { |
297 | | EVP_MAC_CTX_free(context->backend_context); |
298 | | |
299 | | context->backend_context = NULL; |
300 | | } |
301 | | |
302 | | if (context->mac_algorithm != NULL) { |
303 | | EVP_MAC_free(context->mac_algorithm); |
304 | | |
305 | | context->mac_algorithm = NULL; |
306 | | } |
307 | | #else |
308 | 1.46k | if (context->backend_context != NULL) { |
309 | | #if FLB_CRYPTO_OPENSSL_COMPAT_MODE == 0 |
310 | | HMAC_CTX_cleanup(context->backend_context); |
311 | | |
312 | | flb_free(context->backend_context); |
313 | | #else |
314 | 1.46k | HMAC_CTX_reset(context->backend_context); |
315 | | |
316 | 1.46k | HMAC_CTX_free(context->backend_context); |
317 | 1.46k | #endif |
318 | | |
319 | 1.46k | context->backend_context = NULL; |
320 | 1.46k | } |
321 | 1.46k | #endif |
322 | | |
323 | 1.46k | return FLB_CRYPTO_SUCCESS; |
324 | 1.46k | } |
325 | | |
326 | | int flb_hmac_simple_batch(int hash_type, |
327 | | unsigned char *key, size_t key_length, |
328 | | size_t entry_count, |
329 | | unsigned char **data_entries, |
330 | | size_t *length_entries, |
331 | | unsigned char *signature_buffer, |
332 | | size_t signature_buffer_size) |
333 | 1.46k | { |
334 | 1.46k | struct flb_hmac digest_context; |
335 | 1.46k | size_t entry_index; |
336 | 1.46k | int result; |
337 | | |
338 | 1.46k | result = flb_hmac_init(&digest_context, |
339 | 1.46k | hash_type, |
340 | 1.46k | key, key_length); |
341 | | |
342 | 1.46k | if (result == FLB_CRYPTO_SUCCESS) { |
343 | 1.46k | for (entry_index = 0 ; |
344 | 2.92k | entry_index < entry_count && result == FLB_CRYPTO_SUCCESS; |
345 | 1.46k | entry_index++) { |
346 | 1.46k | result = flb_hmac_update(&digest_context, |
347 | 1.46k | data_entries[entry_index], |
348 | 1.46k | length_entries[entry_index]); |
349 | 1.46k | } |
350 | | |
351 | 1.46k | if (result == FLB_CRYPTO_SUCCESS) { |
352 | 1.46k | result = flb_hmac_finalize(&digest_context, |
353 | 1.46k | signature_buffer, |
354 | 1.46k | signature_buffer_size); |
355 | 1.46k | } |
356 | | |
357 | 1.46k | flb_hmac_cleanup(&digest_context); |
358 | 1.46k | } |
359 | | |
360 | 1.46k | return result; |
361 | 1.46k | } |
362 | | |
363 | | int flb_hmac_simple(int hash_type, |
364 | | unsigned char *key, size_t key_length, |
365 | | unsigned char *data, size_t data_length, |
366 | | unsigned char *signature_buffer, |
367 | | size_t signature_buffer_size) |
368 | 1.46k | { |
369 | 1.46k | size_t length_entries[1]; |
370 | 1.46k | unsigned char *data_entries[1]; |
371 | | |
372 | 1.46k | length_entries[0] = data_length; |
373 | 1.46k | data_entries[0] = data; |
374 | | |
375 | 1.46k | return flb_hmac_simple_batch(hash_type, |
376 | 1.46k | key, key_length, |
377 | 1.46k | 1, |
378 | 1.46k | data_entries, |
379 | 1.46k | length_entries, |
380 | 1.46k | signature_buffer, |
381 | 1.46k | signature_buffer_size); |
382 | 1.46k | } |