Home | History | Annotate | Line # | Download | only in fuzz
      1  1.1  christos /*
      2  1.1  christos  * Copyright 2016 The OpenSSL Project Authors. All Rights Reserved.
      3  1.1  christos  *
      4  1.1  christos  * Licensed under the OpenSSL licenses, (the "License");
      5  1.1  christos  * you may not use this file except in compliance with the License.
      6  1.1  christos  * You may obtain a copy of the License at
      7  1.1  christos  * https://www.openssl.org/source/license.html
      8  1.1  christos  * or in the file LICENSE in the source distribution.
      9  1.1  christos  */
     10  1.1  christos 
     11  1.1  christos /*
     12  1.1  christos  * Confirm that if (d, r) = a / b, then b * d + r == a, and that sign(d) ==
     13  1.1  christos  * sign(a), and 0 <= r <= b
     14  1.1  christos  */
     15  1.1  christos 
     16  1.1  christos #include <stdio.h>
     17  1.1  christos #include <openssl/bn.h>
     18  1.1  christos #include <openssl/err.h>
     19  1.1  christos #include "fuzzer.h"
     20  1.1  christos 
     21  1.1  christos /* 256 kB */
     22  1.1  christos #define MAX_LEN (256 * 1000)
     23  1.1  christos 
     24  1.1  christos static BN_CTX *ctx;
     25  1.1  christos static BIGNUM *b1;
     26  1.1  christos static BIGNUM *b2;
     27  1.1  christos static BIGNUM *b3;
     28  1.1  christos static BIGNUM *b4;
     29  1.1  christos static BIGNUM *b5;
     30  1.1  christos 
     31  1.1  christos int FuzzerInitialize(int *argc, char ***argv)
     32  1.1  christos {
     33  1.1  christos     b1 = BN_new();
     34  1.1  christos     b2 = BN_new();
     35  1.1  christos     b3 = BN_new();
     36  1.1  christos     b4 = BN_new();
     37  1.1  christos     b5 = BN_new();
     38  1.1  christos     ctx = BN_CTX_new();
     39  1.1  christos 
     40  1.1  christos     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
     41  1.1  christos     ERR_get_state();
     42  1.1  christos 
     43  1.1  christos     return 1;
     44  1.1  christos }
     45  1.1  christos 
     46  1.1  christos int FuzzerTestOneInput(const uint8_t *buf, size_t len)
     47  1.1  christos {
     48  1.1  christos     int success = 0;
     49  1.1  christos     size_t l1 = 0, l2 = 0;
     50  1.1  christos     /* s1 and s2 will be the signs for b1 and b2. */
     51  1.1  christos     int s1 = 0, s2 = 0;
     52  1.1  christos 
     53  1.1  christos     /* limit the size of the input to avoid timeout */
     54  1.1  christos     if (len > MAX_LEN)
     55  1.1  christos         len = MAX_LEN;
     56  1.1  christos 
     57  1.1  christos     /* We are going to split the buffer in two, sizes l1 and l2, giving b1 and
     58  1.1  christos      * b2.
     59  1.1  christos      */
     60  1.1  christos     if (len > 0) {
     61  1.1  christos         --len;
     62  1.1  christos         /* Use first byte to divide the remaining buffer into 3Fths. I admit
     63  1.1  christos          * this disallows some number sizes. If it matters, better ideas are
     64  1.1  christos          * welcome (Ben).
     65  1.1  christos          */
     66  1.1  christos         l1 = ((buf[0] & 0x3f) * len) / 0x3f;
     67  1.1  christos         s1 = buf[0] & 0x40;
     68  1.1  christos         s2 = buf[0] & 0x80;
     69  1.1  christos         ++buf;
     70  1.1  christos         l2 = len - l1;
     71  1.1  christos     }
     72  1.1  christos     OPENSSL_assert(BN_bin2bn(buf, l1, b1) == b1);
     73  1.1  christos     BN_set_negative(b1, s1);
     74  1.1  christos     OPENSSL_assert(BN_bin2bn(buf + l1, l2, b2) == b2);
     75  1.1  christos     BN_set_negative(b2, s2);
     76  1.1  christos 
     77  1.1  christos     /* divide by 0 is an error */
     78  1.1  christos     if (BN_is_zero(b2)) {
     79  1.1  christos         success = 1;
     80  1.1  christos         goto done;
     81  1.1  christos     }
     82  1.1  christos 
     83  1.1  christos     OPENSSL_assert(BN_div(b3, b4, b1, b2, ctx));
     84  1.1  christos     if (BN_is_zero(b1))
     85  1.1  christos         success = BN_is_zero(b3) && BN_is_zero(b4);
     86  1.1  christos     else if (BN_is_negative(b1))
     87  1.1  christos         success = (BN_is_negative(b3) != BN_is_negative(b2) || BN_is_zero(b3))
     88  1.1  christos             && (BN_is_negative(b4) || BN_is_zero(b4));
     89  1.1  christos     else
     90  1.1  christos         success = (BN_is_negative(b3) == BN_is_negative(b2)  || BN_is_zero(b3))
     91  1.1  christos             && (!BN_is_negative(b4) || BN_is_zero(b4));
     92  1.1  christos     OPENSSL_assert(BN_mul(b5, b3, b2, ctx));
     93  1.1  christos     OPENSSL_assert(BN_add(b5, b5, b4));
     94  1.1  christos 
     95  1.1  christos     success = success && BN_cmp(b5, b1) == 0;
     96  1.1  christos     if (!success) {
     97  1.1  christos         BN_print_fp(stdout, b1);
     98  1.1  christos         putchar('\n');
     99  1.1  christos         BN_print_fp(stdout, b2);
    100  1.1  christos         putchar('\n');
    101  1.1  christos         BN_print_fp(stdout, b3);
    102  1.1  christos         putchar('\n');
    103  1.1  christos         BN_print_fp(stdout, b4);
    104  1.1  christos         putchar('\n');
    105  1.1  christos         BN_print_fp(stdout, b5);
    106  1.1  christos         putchar('\n');
    107  1.1  christos         printf("%d %d %d %d %d %d %d\n", BN_is_negative(b1),
    108  1.1  christos                BN_is_negative(b2),
    109  1.1  christos                BN_is_negative(b3), BN_is_negative(b4), BN_is_zero(b4),
    110  1.1  christos                BN_is_negative(b3) != BN_is_negative(b2)
    111  1.1  christos                && (BN_is_negative(b4) || BN_is_zero(b4)),
    112  1.1  christos                BN_cmp(b5, b1));
    113  1.1  christos         puts("----\n");
    114  1.1  christos     }
    115  1.1  christos 
    116  1.1  christos  done:
    117  1.1  christos     OPENSSL_assert(success);
    118  1.1  christos     ERR_clear_error();
    119  1.1  christos 
    120  1.1  christos     return 0;
    121  1.1  christos }
    122  1.1  christos 
    123  1.1  christos void FuzzerCleanup(void)
    124  1.1  christos {
    125  1.1  christos     BN_free(b1);
    126  1.1  christos     BN_free(b2);
    127  1.1  christos     BN_free(b3);
    128  1.1  christos     BN_free(b4);
    129  1.1  christos     BN_free(b5);
    130  1.1  christos     BN_CTX_free(ctx);
    131  1.1  christos }
    132