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