Coverage Report

Created: 2024-09-19 07:08

/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
}