Coverage Report

Created: 2026-09-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl41/fuzz/slh-dsa.c
Line
Count
Source
1
/*
2
 * Copyright 2025-2026 The OpenSSL Project Authors. All Rights Reserved.
3
 *
4
 * Licensed under the Apache License 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 * https://www.openssl.org/source/license.html
8
 * or in the file LICENSE in the source distribution.
9
 */
10
11
/*
12
 * Test slh-dsa operation.
13
 */
14
#include <string.h>
15
#include <openssl/evp.h>
16
#include <openssl/err.h>
17
#include <openssl/rand.h>
18
#include <openssl/byteorder.h>
19
#include <openssl/core_names.h>
20
#include "crypto/slh_dsa.h"
21
#include "internal/nelem.h"
22
#include "fuzzer.h"
23
24
/**
25
 * @brief Consumes an 8-bit unsigned integer from a buffer.
26
 *
27
 * This function extracts an 8-bit unsigned integer from the provided buffer,
28
 * updates the buffer pointer, and adjusts the remaining length.
29
 *
30
 * @param buf  Pointer to the input buffer.
31
 * @param len  Pointer to the size of the remaining buffer; updated after consumption.
32
 * @param val  Pointer to store the extracted 8-bit value.
33
 *
34
 * @return Pointer to the updated buffer position after reading the value,
35
 *         or NULL if the buffer does not contain enough data.
36
 */
37
static uint8_t *consume_uint8t(const uint8_t *buf, size_t *len, uint8_t *val)
38
4.50k
{
39
4.50k
    if (*len < sizeof(uint8_t))
40
0
        return NULL;
41
4.50k
    *val = *buf;
42
4.50k
    *len -= sizeof(uint8_t);
43
4.50k
    return (uint8_t *)buf + 1;
44
4.50k
}
45
46
/**
47
 * @brief Generates a DSA key pair using OpenSSL EVP API.
48
 *
49
 * This function creates a DSA key pair based on the specified key size and
50
 * parameters. It supports generating keys using explicit parameters if provided.
51
 *
52
 * @param name The name of the key type (e.g., "DSA").
53
 * @param keysize The desired key size in bits.
54
 * @param params Optional OpenSSL parameters for key generation.
55
 * @param param_broken A flag indicating if the parameters are broken.
56
 *                     If true, key generation will fail.
57
 *
58
 * @return A pointer to the generated EVP_PKEY structure on success,
59
 *         or NULL on failure.
60
 */
61
static EVP_PKEY *slh_dsa_gen_key(const char *name, uint32_t keysize,
62
    OSSL_PARAM params[], uint8_t *param_broken)
63
236
{
64
236
    EVP_PKEY_CTX *ctx;
65
236
    EVP_PKEY *new = NULL;
66
67
236
    ctx = EVP_PKEY_CTX_new_from_name(NULL, name, NULL);
68
236
    if (ctx == NULL)
69
0
        return NULL;
70
236
    if (params != NULL) {
71
38
        new = EVP_PKEY_new();
72
38
        if (new == NULL)
73
0
            goto out;
74
38
        if (!EVP_PKEY_fromdata_init(ctx)) {
75
0
            EVP_PKEY_free(new);
76
0
            new = NULL;
77
0
            goto out;
78
0
        }
79
38
        if (EVP_PKEY_fromdata(ctx, &new, EVP_PKEY_KEYPAIR, params) != 1) {
80
24
            EVP_PKEY_free(new);
81
24
            new = NULL;
82
24
        }
83
38
        goto out;
84
38
    }
85
86
198
    if (!EVP_PKEY_keygen_init(ctx))
87
0
        goto out;
88
198
    if (!EVP_PKEY_generate(ctx, &new)) {
89
0
        EVP_PKEY_free(new);
90
0
        new = NULL;
91
0
    }
92
93
236
out:
94
236
    EVP_PKEY_CTX_free(ctx);
95
236
    return new;
96
198
}
97
98
/**
99
 * @brief Selects a key type and determines the key size.
100
 *
101
 * This function maps a selector value to a specific SLH-DSA algorithm
102
 * using a modulo operation. It then retrieves the corresponding
103
 * algorithm name and assigns an appropriate key size based on the
104
 * selected algorithm.
105
 *
106
 * @param selector A random selector value used to determine the key type.
107
 * @param keysize Pointer to a variable where the determined key size
108
 *                (in bytes) will be stored.
109
 *
110
 * @return A pointer to a string containing the long name of the
111
 *         selected key type, or NULL if invalid.
112
 */
113
static const char *select_keytype(uint8_t selector, uint32_t *keysize)
114
1.87k
{
115
1.87k
    unsigned int choice;
116
1.87k
    const char *name = NULL;
117
118
1.87k
    *keysize = 0;
119
    /*
120
     * There are 12 SLH-DSA algs with registered NIDS at the moment
121
     * So use our random selector value to get one of them by computing
122
     * its modulo 12 value and adding the offset of the first NID, 1460
123
     * Then convert that to a long name
124
     */
125
1.87k
    choice = (selector % 12) + 1460;
126
127
1.87k
    name = OBJ_nid2ln(choice);
128
129
    /*
130
     * Select a keysize, values taken from
131
     * man7/EVP_PKEY-SLH-DSA.pod
132
     */
133
1.87k
    switch (choice) {
134
276
    case NID_SLH_DSA_SHA2_128s:
135
534
    case NID_SLH_DSA_SHA2_128f:
136
612
    case NID_SLH_DSA_SHAKE_128s:
137
665
    case NID_SLH_DSA_SHAKE_128f:
138
665
        *keysize = 16;
139
665
        break;
140
93
    case NID_SLH_DSA_SHA2_192s:
141
467
    case NID_SLH_DSA_SHA2_192f:
142
569
    case NID_SLH_DSA_SHAKE_192s:
143
753
    case NID_SLH_DSA_SHAKE_192f:
144
753
        *keysize = 24;
145
753
        break;
146
99
    case NID_SLH_DSA_SHA2_256s:
147
232
    case NID_SLH_DSA_SHA2_256f:
148
348
    case NID_SLH_DSA_SHAKE_256s:
149
455
    case NID_SLH_DSA_SHAKE_256f:
150
455
        *keysize = 32;
151
455
        break;
152
0
    default:
153
0
        fprintf(stderr, "Selecting invalid key size\n");
154
0
        *keysize = 0;
155
0
        break;
156
1.87k
    }
157
1.87k
    return name;
158
1.87k
}
159
160
/**
161
 * @brief Generates two SLH-DSA key pairs based on consumed selector values.
162
 *
163
 * This function extracts two selector values from the provided buffer,
164
 * determines the corresponding key types and sizes, and generates two
165
 * SLH-DSA key pairs.
166
 *
167
 * @param buf Pointer to a buffer containing selector values. The buffer
168
 *            pointer is updated as values are consumed.
169
 * @param len Pointer to the remaining buffer length, updated as values
170
 *            are consumed.
171
 * @param out1 Pointer to store the first generated key.
172
 * @param out2 Pointer to store the second generated key.
173
 */
174
static void slh_dsa_gen_keys(uint8_t **buf, size_t *len,
175
    void **out1, void **out2)
176
326
{
177
326
    uint8_t selector = 0;
178
326
    const char *keytype = NULL;
179
326
    uint32_t keysize;
180
181
326
    *buf = consume_uint8t(*buf, len, &selector);
182
326
    keytype = select_keytype(selector, &keysize);
183
326
    *out1 = (void *)slh_dsa_gen_key(keytype, keysize, NULL, 0);
184
185
326
    *buf = consume_uint8t(*buf, len, &selector);
186
326
    keytype = select_keytype(selector, &keysize);
187
326
    *out2 = (void *)slh_dsa_gen_key(keytype, keysize, NULL, 0);
188
326
    return;
189
326
}
190
191
114
#define PARAM_BUF_SZ 256
192
193
/**
194
 * @brief Generates an SLH-DSA key pair with custom parameters.
195
 *
196
 * This function extracts a selector value from the provided buffer,
197
 * determines the corresponding key type and size, and generates an
198
 * SLH-DSA key pair using randomly generated public and private key
199
 * buffers. It also introduces intentional modifications to test
200
 * invalid parameter handling.
201
 *
202
 * @param buf Pointer to a buffer containing the selector value. The
203
 *            buffer pointer is updated as values are consumed.
204
 * @param len Pointer to the remaining buffer length, updated as values
205
 *            are consumed.
206
 * @param out1 Pointer to store the generated key. Will be NULL if key
207
 *             generation fails due to invalid parameters.
208
 * @param out2 Unused output parameter (placeholder for symmetry with
209
 *             other key generation functions).
210
 */
211
static void slh_dsa_gen_key_with_params(uint8_t **buf, size_t *len,
212
    void **out1, void **out2)
213
38
{
214
38
    uint8_t selector = 0;
215
38
    const char *keytype = NULL;
216
38
    uint32_t keysize;
217
38
    uint8_t pubbuf[PARAM_BUF_SZ]; /* expressly bigger than max key size * 3 */
218
38
    uint8_t prvbuf[PARAM_BUF_SZ]; /* expressly bigger than max key size * 3 */
219
38
    uint8_t sdbuf[PARAM_BUF_SZ]; /* expressly bigger than max key size * 3 */
220
38
    uint8_t *bufptr;
221
38
    OSSL_PARAM params[3];
222
38
    size_t buflen;
223
38
    uint8_t broken = 0;
224
225
38
    *out1 = NULL;
226
227
38
    *buf = consume_uint8t(*buf, len, &selector);
228
38
    keytype = select_keytype(selector, &keysize);
229
230
38
    if (!RAND_bytes(pubbuf, PARAM_BUF_SZ)
231
38
        || !RAND_bytes(prvbuf, PARAM_BUF_SZ)
232
38
        || !RAND_bytes(sdbuf, PARAM_BUF_SZ))
233
0
        return;
234
235
    /*
236
     * select an invalid length if the buffer 0th bit is one
237
     * make it too big if the 2nd bit is 0, smaller otherwise
238
     */
239
38
    buflen = keysize * 2; /* these params are 2 * the keysize */
240
38
    if ((*buf)[0] & 0x1) {
241
14
        buflen = ((*buf)[0] & 0x2) ? buflen - 1 : buflen + 1;
242
14
        broken = 1;
243
14
    }
244
245
    /* pass a null buffer if the third bit of the buffer is 1 */
246
38
    bufptr = ((*buf)[0] & 0x4) ? NULL : pubbuf;
247
38
    if (!broken)
248
24
        broken = (bufptr == NULL) ? 1 : 0;
249
250
38
    params[0] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PUB_KEY,
251
38
        (char *)bufptr, buflen);
252
253
38
    buflen = keysize * 2;
254
    /* select an invalid length if the 4th bit is true  */
255
38
    if ((*buf)[0] & 0x8) {
256
13
        buflen = (*buf[0] & 0x1) ? buflen - 1 : buflen + 1;
257
13
        broken = 1;
258
13
    }
259
260
    /* pass a null buffer if the 5th bit is true */
261
38
    bufptr = ((*buf)[0] & 0x10) ? NULL : prvbuf;
262
38
    if (!broken)
263
15
        broken = (bufptr == NULL) ? 1 : 0;
264
38
    params[1] = OSSL_PARAM_construct_octet_string(OSSL_PKEY_PARAM_PRIV_KEY,
265
38
        (char *)bufptr, buflen);
266
267
38
    params[2] = OSSL_PARAM_construct_end();
268
269
38
    *out1 = (void *)slh_dsa_gen_key(keytype, keysize, params, &broken);
270
38
    return;
271
38
}
272
273
/**
274
 * @brief Frees allocated SLH-DSA key structures.
275
 *
276
 * This function releases memory allocated for SLH-DSA key pairs
277
 * by freeing the provided EVP_PKEY structures.
278
 *
279
 * @param in1 Pointer to the first input key to be freed.
280
 * @param in2 Pointer to the second input key to be freed.
281
 * @param out1 Pointer to the first output key to be freed.
282
 * @param out2 Pointer to the second output key to be freed.
283
 */
284
static void slh_dsa_clean_keys(void *in1, void *in2, void *out1, void *out2)
285
1.55k
{
286
1.55k
    EVP_PKEY_free((EVP_PKEY *)in1);
287
1.55k
    EVP_PKEY_free((EVP_PKEY *)in2);
288
1.55k
    EVP_PKEY_free((EVP_PKEY *)out1);
289
1.55k
    EVP_PKEY_free((EVP_PKEY *)out2);
290
1.55k
}
291
292
/**
293
 * @brief Performs SLH-DSA signing and verification on a given message.
294
 *
295
 * This function generates an SLH-DSA key, signs a message, and verifies
296
 * the generated signature. It extracts necessary parameters from the buffer
297
 * to determine signing options.
298
 *
299
 * @param buf Pointer to a buffer containing the selector and message data.
300
 *            The buffer pointer is updated as values are consumed.
301
 * @param len Pointer to the remaining buffer length, updated as values
302
 *            are consumed.
303
 * @param key1 Unused key parameter (placeholder for function signature consistency).
304
 * @param key2 Unused key parameter (placeholder for function signature consistency).
305
 * @param out1 Pointer to store the generated key (for cleanup purposes).
306
 * @param out2 Unused output parameter (placeholder for consistency).
307
 */
308
static void slh_dsa_sign_verify(uint8_t **buf, size_t *len, void *key1,
309
    void *key2, void **out1, void **out2)
310
{
311
    EVP_PKEY_CTX *ctx = NULL;
312
    EVP_PKEY *key = NULL;
313
    EVP_SIGNATURE *sig_alg = NULL;
314
    const char *keytype;
315
    uint32_t keylen;
316
    uint8_t selector = 0;
317
    unsigned char *msg = NULL;
318
    size_t msg_len;
319
    size_t sig_len;
320
    unsigned char *sig = NULL;
321
    OSSL_PARAM params[4];
322
    int paramidx = 0;
323
    int intval1, intval2;
324
325
    *buf = consume_uint8t(*buf, len, &selector);
326
    if (*buf == NULL)
327
        return;
328
329
    keytype = select_keytype(selector, &keylen);
330
331
    /*
332
     * Consume another byte to figure out our params
333
     */
334
    *buf = consume_uint8t(*buf, len, &selector);
335
    if (*buf == NULL)
336
        return;
337
338
    /*
339
     * Remainder of the buffer is the msg to sign
340
     */
341
    msg = (unsigned char *)*buf;
342
    msg_len = *len;
343
344
    *len = 0;
345
346
    if (selector & 0x1)
347
        params[paramidx++] = OSSL_PARAM_construct_octet_string(OSSL_SIGNATURE_PARAM_CONTEXT_STRING,
348
            msg, msg_len);
349
350
    if (selector & 0x2) {
351
        intval1 = selector & 0x4;
352
        params[paramidx++] = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_MESSAGE_ENCODING,
353
            &intval1);
354
    }
355
356
    if (selector & 0x8) {
357
        intval2 = selector & 0x10;
358
        params[paramidx++] = OSSL_PARAM_construct_int(OSSL_SIGNATURE_PARAM_DETERMINISTIC,
359
            &intval2);
360
    }
361
362
    params[paramidx] = OSSL_PARAM_construct_end();
363
364
    key = (void *)slh_dsa_gen_key(keytype, keylen, NULL, 0);
365
    if (key == NULL)
366
        return;
367
    *out1 = key; /* for cleanup */
368
369
    ctx = EVP_PKEY_CTX_new_from_pkey(NULL, key, NULL);
370
    if (ctx == NULL)
371
        goto out;
372
373
    sig_alg = EVP_SIGNATURE_fetch(NULL, keytype, NULL);
374
    if (sig_alg == NULL)
375
        goto out;
376
377
    /*
378
     * the context_string parameter can be no more than 255 bytes, so if
379
     * our random input buffer is greater than that, sign_message_init will
380
     * fail, in which case there's nothing more we can do here so bail out
381
     */
382
    if (EVP_PKEY_sign_message_init(ctx, sig_alg, params) != 1)
383
        goto out;
384
385
    if (EVP_PKEY_sign(ctx, NULL, &sig_len, msg, msg_len) != 1)
386
        goto out;
387
    sig = OPENSSL_zalloc(sig_len);
388
    if (sig == NULL)
389
        goto out;
390
391
    if (EVP_PKEY_sign(ctx, sig, &sig_len, msg, msg_len) != 1)
392
        goto out;
393
394
    if (EVP_PKEY_verify_message_init(ctx, sig_alg, params) != 1)
395
        goto out;
396
    if (EVP_PKEY_verify(ctx, sig, sig_len, msg, msg_len) != 1)
397
        fprintf(stderr, "Failed to verify message\n");
398
399
out:
400
    OPENSSL_free(sig);
401
    EVP_SIGNATURE_free(sig_alg);
402
    EVP_PKEY_CTX_free(ctx);
403
}
404
405
/**
406
 * @brief Exports and imports SLH-DSA key pairs, verifying equivalence.
407
 *
408
 * This function extracts key data from two given SLH-DSA keys (`alice` and `bob`),
409
 * reconstructs new keys from the extracted data, and verifies that the imported
410
 * keys are equivalent to the originals. It ensures that key export/import
411
 * functionality is working correctly.
412
 *
413
 * @param buf Unused buffer parameter (placeholder for function signature consistency).
414
 * @param len Unused length parameter (placeholder for function signature consistency).
415
 * @param key1 Pointer to the first key (`alice`) to be exported and imported.
416
 * @param key2 Pointer to the second key (`bob`) to be exported and imported.
417
 * @param out1 Unused output parameter (placeholder for consistency).
418
 * @param out2 Unused output parameter (placeholder for consistency).
419
 */
420
static void slh_dsa_export_import(uint8_t **buf, size_t *len, void *key1,
421
    void *key2, void **out1, void **out2)
422
56
{
423
56
    EVP_PKEY *alice = (EVP_PKEY *)key1;
424
56
    EVP_PKEY *bob = (EVP_PKEY *)key2;
425
56
    EVP_PKEY *new = NULL;
426
56
    EVP_PKEY_CTX *ctx = NULL;
427
56
    OSSL_PARAM *params = NULL;
428
429
56
    if (alice == NULL || bob == NULL)
430
0
        return;
431
432
56
    if (!EVP_PKEY_todata(alice, EVP_PKEY_KEYPAIR, &params))
433
0
        goto alice_done;
434
435
56
    ctx = EVP_PKEY_CTX_new_from_pkey(NULL, alice, NULL);
436
56
    if (ctx == NULL)
437
0
        goto alice_done;
438
439
56
    if (!EVP_PKEY_fromdata_init(ctx))
440
0
        goto alice_done;
441
442
56
    new = EVP_PKEY_new();
443
56
    if (new == NULL)
444
0
        goto alice_done;
445
56
    if (EVP_PKEY_fromdata(ctx, &new, EVP_PKEY_KEYPAIR, params) != 1)
446
0
        goto alice_done;
447
448
56
    (void)EVP_PKEY_eq(alice, new);
449
450
56
alice_done:
451
56
    EVP_PKEY_free(new);
452
56
    EVP_PKEY_CTX_free(ctx);
453
56
    OSSL_PARAM_free(params);
454
56
    params = NULL;
455
56
    ctx = NULL;
456
56
    new = NULL;
457
458
56
    if (!EVP_PKEY_todata(bob, EVP_PKEY_KEYPAIR, &params))
459
0
        goto bob_done;
460
461
56
    ctx = EVP_PKEY_CTX_new_from_pkey(NULL, bob, NULL);
462
56
    if (ctx == NULL)
463
0
        goto bob_done;
464
465
56
    if (!EVP_PKEY_fromdata_init(ctx))
466
0
        goto bob_done;
467
468
56
    new = EVP_PKEY_new();
469
56
    if (new == NULL)
470
0
        goto bob_done;
471
56
    if (EVP_PKEY_fromdata(ctx, &new, EVP_PKEY_KEYPAIR, params) != 1)
472
0
        goto bob_done;
473
474
56
    (void)EVP_PKEY_eq(bob, new);
475
56
    (void)EVP_PKEY_eq(alice, new);
476
477
56
bob_done:
478
56
    EVP_PKEY_CTX_free(ctx);
479
56
    EVP_PKEY_free(new);
480
56
    OSSL_PARAM_free(params);
481
56
}
482
483
/**
484
 * @brief Represents an operation table entry for cryptographic operations.
485
 *
486
 * This structure defines a table entry containing function pointers for
487
 * setting up, executing, and cleaning up cryptographic operations, along
488
 * with associated metadata such as a name and description.
489
 *
490
 * @struct op_table_entry
491
 */
492
struct op_table_entry {
493
    /** Name of the operation. */
494
    char *name;
495
496
    /**
497
     * @brief Function pointer for setting up the operation.
498
     *
499
     * @param buf   Pointer to the buffer pointer; may be updated.
500
     * @param len   Pointer to the remaining buffer size; may be updated.
501
     * @param out1  Pointer to store the first output of the setup function.
502
     * @param out2  Pointer to store the second output of the setup function.
503
     */
504
    void (*setup)(uint8_t **buf, size_t *len, void **out1, void **out2);
505
506
    /**
507
     * @brief Function pointer for executing the operation.
508
     *
509
     * @param buf   Pointer to the buffer pointer; may be updated.
510
     * @param len   Pointer to the remaining buffer size; may be updated.
511
     * @param in1   First input parameter for the operation.
512
     * @param in2   Second input parameter for the operation.
513
     * @param out1  Pointer to store the first output of the operation.
514
     * @param out2  Pointer to store the second output of the operation.
515
     */
516
    void (*doit)(uint8_t **buf, size_t *len, void *in1, void *in2,
517
        void **out1, void **out2);
518
519
    /**
520
     * @brief Function pointer for cleaning up after the operation.
521
     *
522
     * @param in1   First input parameter to be cleaned up.
523
     * @param in2   Second input parameter to be cleaned up.
524
     * @param out1  First output parameter to be cleaned up.
525
     * @param out2  Second output parameter to be cleaned up.
526
     */
527
    void (*cleanup)(void *in1, void *in2, void *out1, void *out2);
528
};
529
530
static struct op_table_entry ops[] = {
531
    { "Generate SLH-DSA keys",
532
        slh_dsa_gen_keys,
533
        NULL,
534
        slh_dsa_clean_keys },
535
    { "Generate SLH-DSA keys with params",
536
        slh_dsa_gen_key_with_params,
537
        NULL,
538
        slh_dsa_clean_keys },
539
    { "SLH-DSA Export/Import",
540
        slh_dsa_gen_keys,
541
        slh_dsa_export_import,
542
        slh_dsa_clean_keys },
543
    { "SLH-DSA sign and verify",
544
        NULL,
545
        slh_dsa_sign_verify,
546
        slh_dsa_clean_keys }
547
};
548
549
int FuzzerInitialize(int *argc, char ***argv)
550
229
{
551
229
    return 0;
552
229
}
553
554
/**
555
 * @brief Processes a fuzzing input by selecting and executing an operation.
556
 *
557
 * This function interprets the first byte of the input buffer to determine
558
 * an operation to execute. It then follows a setup, execution, and cleanup
559
 * sequence based on the selected operation.
560
 *
561
 * @param buf Pointer to the input buffer.
562
 * @param len Length of the input buffer.
563
 *
564
 * @return 0 on successful execution, -1 if the input is too short.
565
 *
566
 * @note The function requires at least 32 bytes in the buffer to proceed.
567
 *       It utilizes the `ops` operation table to dynamically determine and
568
 *       execute the selected operation.
569
 */
570
int FuzzerTestOneInput(const uint8_t *buf, size_t len)
571
663
{
572
663
    uint8_t operation;
573
663
    uint8_t *buffer_cursor;
574
663
    void *in1 = NULL, *in2 = NULL;
575
663
    void *out1 = NULL, *out2 = NULL;
576
577
663
    if (len < 32)
578
24
        return -1;
579
    /*
580
     * Get the first byte of the buffer to tell us what operation
581
     * to perform
582
     */
583
639
    buffer_cursor = consume_uint8t(buf, &len, &operation);
584
639
    if (buffer_cursor == NULL)
585
0
        return -1;
586
587
    /*
588
     * Adjust for operational array size
589
     */
590
639
    operation %= OSSL_NELEM(ops);
591
592
    /*
593
     * And run our setup/doit/cleanup sequence
594
     */
595
639
    if (ops[operation].setup != NULL)
596
634
        ops[operation].setup(&buffer_cursor, &len, &in1, &in2);
597
639
    if (ops[operation].doit != NULL && in1 != NULL)
598
417
        ops[operation].doit(&buffer_cursor, &len, in1, in2, &out1, &out2);
599
639
    if (ops[operation].cleanup != NULL)
600
639
        ops[operation].cleanup(in1, in2, out1, out2);
601
602
639
    return 0;
603
639
}
604
605
void FuzzerCleanup(void)
606
0
{
607
0
    OPENSSL_cleanup();
608
0
}