lh | 9ed821d | 2023-04-07 01:36:19 -0700 | [diff] [blame^] | 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 | /* 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_get_state(); |
| 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 | } |