Coverage Report

Created: 2026-09-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl41/fuzz/bndiv.c
Line
Count
Source
1
/*
2
 * Copyright 2016-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
 * Confirm that if (d, r) = a / b, then b * d + r == a, and that sign(d) ==
13
 * sign(a), and 0 <= r <= b
14
 */
15
16
#include <stdio.h>
17
#include <openssl/bn.h>
18
#include <openssl/err.h>
19
#include "fuzzer.h"
20
21
/* 256 kB */
22
2.55k
#define MAX_LEN (256 * 1000)
23
24
static BN_CTX *ctx;
25
static BIGNUM *b1;
26
static BIGNUM *b2;
27
static BIGNUM *b3;
28
static BIGNUM *b4;
29
static BIGNUM *b5;
30
31
int FuzzerInitialize(int *argc, char ***argv)
32
3
{
33
3
    b1 = BN_new();
34
3
    b2 = BN_new();
35
3
    b3 = BN_new();
36
3
    b4 = BN_new();
37
3
    b5 = BN_new();
38
3
    ctx = BN_CTX_new();
39
40
3
    if (b1 == NULL || b2 == NULL || b3 == NULL || b4 == NULL || b5 == NULL
41
3
        || ctx == NULL) {
42
0
        BN_free(b1);
43
0
        BN_free(b2);
44
0
        BN_free(b3);
45
0
        BN_free(b4);
46
0
        BN_free(b5);
47
0
        BN_CTX_free(ctx);
48
0
        b1 = b2 = b3 = b4 = b5 = NULL;
49
0
        ctx = NULL;
50
0
        return 0;
51
0
    }
52
53
3
    OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
54
3
    ERR_clear_error();
55
56
3
    return 1;
57
3
}
58
59
int FuzzerTestOneInput(const uint8_t *buf, size_t len)
60
2.55k
{
61
2.55k
    int success = 0;
62
2.55k
    size_t l1 = 0, l2 = 0;
63
    /* s1 and s2 will be the signs for b1 and b2. */
64
2.55k
    int s1 = 0, s2 = 0;
65
66
    /* limit the size of the input to avoid timeout */
67
2.55k
    if (len > MAX_LEN)
68
3
        len = MAX_LEN;
69
70
    /* We are going to split the buffer in two, sizes l1 and l2, giving b1 and
71
     * b2.
72
     */
73
2.55k
    if (len > 0) {
74
2.55k
        --len;
75
        /* Use first byte to divide the remaining buffer into 3Fths. I admit
76
         * this disallows some number sizes. If it matters, better ideas are
77
         * welcome (Ben).
78
         */
79
2.55k
        l1 = ((buf[0] & 0x3f) * len) / 0x3f;
80
2.55k
        s1 = buf[0] & 0x40;
81
2.55k
        s2 = buf[0] & 0x80;
82
2.55k
        ++buf;
83
2.55k
        l2 = len - l1;
84
2.55k
    }
85
2.55k
    if (BN_bin2bn(buf, (int)l1, b1) != b1)
86
0
        goto done;
87
2.55k
    BN_set_negative(b1, s1);
88
2.55k
    if (BN_bin2bn(buf + l1, (int)l2, b2) != b2)
89
0
        goto done;
90
2.55k
    BN_set_negative(b2, s2);
91
92
    /* divide by 0 is an error */
93
2.55k
    if (BN_is_zero(b2))
94
13
        goto done;
95
96
2.54k
    if (!BN_div(b3, b4, b1, b2, ctx))
97
0
        goto done;
98
2.54k
    if (BN_is_zero(b1))
99
316
        success = BN_is_zero(b3) && BN_is_zero(b4);
100
2.22k
    else if (BN_is_negative(b1))
101
1.52k
        success = (BN_is_negative(b3) != BN_is_negative(b2) || BN_is_zero(b3))
102
1.52k
            && (BN_is_negative(b4) || BN_is_zero(b4));
103
704
    else
104
704
        success = (BN_is_negative(b3) == BN_is_negative(b2) || BN_is_zero(b3))
105
704
            && (!BN_is_negative(b4) || BN_is_zero(b4));
106
2.54k
    if (!BN_mul(b5, b3, b2, ctx))
107
0
        goto done;
108
2.54k
    if (!BN_add(b5, b5, b4))
109
0
        goto done;
110
111
2.54k
    success = success && BN_cmp(b5, b1) == 0;
112
2.54k
    if (!success) {
113
0
        BN_print_fp(stdout, b1);
114
0
        putchar('\n');
115
0
        BN_print_fp(stdout, b2);
116
0
        putchar('\n');
117
0
        BN_print_fp(stdout, b3);
118
0
        putchar('\n');
119
0
        BN_print_fp(stdout, b4);
120
0
        putchar('\n');
121
0
        BN_print_fp(stdout, b5);
122
0
        putchar('\n');
123
0
        printf("%d %d %d %d %d %d %d\n", BN_is_negative(b1),
124
0
            BN_is_negative(b2),
125
0
            BN_is_negative(b3), BN_is_negative(b4), BN_is_zero(b4),
126
0
            BN_is_negative(b3) != BN_is_negative(b2)
127
0
                && (BN_is_negative(b4) || BN_is_zero(b4)),
128
0
            BN_cmp(b5, b1));
129
0
        puts("----\n");
130
0
    }
131
132
2.55k
done:
133
2.55k
    ERR_clear_error();
134
135
2.55k
    return 0;
136
2.54k
}
137
138
void FuzzerCleanup(void)
139
0
{
140
0
    BN_free(b1);
141
0
    BN_free(b2);
142
0
    BN_free(b3);
143
0
    BN_free(b4);
144
0
    BN_free(b5);
145
0
    BN_CTX_free(ctx);
146
0
}