xref: /freebsd/crypto/openssl/fuzz/bndiv.c (revision b59017c5cad90d0f09a59e68c00457b7faf93e7c)
1 /*
2  * Copyright 2016 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 #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 {
33     b1 = BN_new();
34     b2 = BN_new();
35     b3 = BN_new();
36     b4 = BN_new();
37     b5 = BN_new();
38     ctx = BN_CTX_new();
39 
40     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
41     ERR_clear_error();
42 
43     return 1;
44 }
45 
46 int FuzzerTestOneInput(const uint8_t *buf, size_t len)
47 {
48     int success = 0;
49     size_t l1 = 0, l2 = 0;
50     /* s1 and s2 will be the signs for b1 and b2. */
51     int s1 = 0, s2 = 0;
52 
53     /* limit the size of the input to avoid timeout */
54     if (len > MAX_LEN)
55         len = MAX_LEN;
56 
57     /* We are going to split the buffer in two, sizes l1 and l2, giving b1 and
58      * b2.
59      */
60     if (len > 0) {
61         --len;
62         /* Use first byte to divide the remaining buffer into 3Fths. I admit
63          * this disallows some number sizes. If it matters, better ideas are
64          * welcome (Ben).
65          */
66         l1 = ((buf[0] & 0x3f) * len) / 0x3f;
67         s1 = buf[0] & 0x40;
68         s2 = buf[0] & 0x80;
69         ++buf;
70         l2 = len - l1;
71     }
72     OPENSSL_assert(BN_bin2bn(buf, l1, b1) == b1);
73     BN_set_negative(b1, s1);
74     OPENSSL_assert(BN_bin2bn(buf + l1, l2, b2) == b2);
75     BN_set_negative(b2, s2);
76 
77     /* divide by 0 is an error */
78     if (BN_is_zero(b2)) {
79         success = 1;
80         goto done;
81     }
82 
83     OPENSSL_assert(BN_div(b3, b4, b1, b2, ctx));
84     if (BN_is_zero(b1))
85         success = BN_is_zero(b3) && BN_is_zero(b4);
86     else if (BN_is_negative(b1))
87         success = (BN_is_negative(b3) != BN_is_negative(b2) || BN_is_zero(b3))
88             && (BN_is_negative(b4) || BN_is_zero(b4));
89     else
90         success = (BN_is_negative(b3) == BN_is_negative(b2)  || BN_is_zero(b3))
91             && (!BN_is_negative(b4) || BN_is_zero(b4));
92     OPENSSL_assert(BN_mul(b5, b3, b2, ctx));
93     OPENSSL_assert(BN_add(b5, b5, b4));
94 
95     success = success && BN_cmp(b5, b1) == 0;
96     if (!success) {
97         BN_print_fp(stdout, b1);
98         putchar('\n');
99         BN_print_fp(stdout, b2);
100         putchar('\n');
101         BN_print_fp(stdout, b3);
102         putchar('\n');
103         BN_print_fp(stdout, b4);
104         putchar('\n');
105         BN_print_fp(stdout, b5);
106         putchar('\n');
107         printf("%d %d %d %d %d %d %d\n", BN_is_negative(b1),
108                BN_is_negative(b2),
109                BN_is_negative(b3), BN_is_negative(b4), BN_is_zero(b4),
110                BN_is_negative(b3) != BN_is_negative(b2)
111                && (BN_is_negative(b4) || BN_is_zero(b4)),
112                BN_cmp(b5, b1));
113         puts("----\n");
114     }
115 
116  done:
117     OPENSSL_assert(success);
118     ERR_clear_error();
119 
120     return 0;
121 }
122 
123 void FuzzerCleanup(void)
124 {
125     BN_free(b1);
126     BN_free(b2);
127     BN_free(b3);
128     BN_free(b4);
129     BN_free(b5);
130     BN_CTX_free(ctx);
131 }
132