xref: /freebsd/crypto/openssl/fuzz/bignum.c (revision a7148ab39c03abd4d1a84997c70bf96f15dd2a09)
1e0c4386eSCy Schubert /*
2*a7148ab3SEnji Cooper  * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved.
3e0c4386eSCy Schubert  *
4e0c4386eSCy Schubert  * Licensed under the Apache License 2.0 (the "License");
5e0c4386eSCy Schubert  * you may not use this file except in compliance with the License.
6e0c4386eSCy Schubert  * You may obtain a copy of the License at
7e0c4386eSCy Schubert  * https://www.openssl.org/source/license.html
8e0c4386eSCy Schubert  * or in the file LICENSE in the source distribution.
9e0c4386eSCy Schubert  */
10e0c4386eSCy Schubert 
11e0c4386eSCy Schubert /*
12e0c4386eSCy Schubert  * Confirm that a^b mod c agrees when calculated cleverly vs naively, for
13e0c4386eSCy Schubert  * random a, b and c.
14e0c4386eSCy Schubert  */
15e0c4386eSCy Schubert 
16e0c4386eSCy Schubert #include <stdio.h>
17e0c4386eSCy Schubert #include <openssl/bn.h>
18e0c4386eSCy Schubert #include <openssl/err.h>
19e0c4386eSCy Schubert #include "fuzzer.h"
20e0c4386eSCy Schubert 
21e0c4386eSCy Schubert 
FuzzerInitialize(int * argc,char *** argv)22e0c4386eSCy Schubert int FuzzerInitialize(int *argc, char ***argv)
23e0c4386eSCy Schubert {
24e0c4386eSCy Schubert     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
25e0c4386eSCy Schubert     ERR_clear_error();
26e0c4386eSCy Schubert 
27e0c4386eSCy Schubert     return 1;
28e0c4386eSCy Schubert }
29e0c4386eSCy Schubert 
FuzzerTestOneInput(const uint8_t * buf,size_t len)30e0c4386eSCy Schubert int FuzzerTestOneInput(const uint8_t *buf, size_t len)
31e0c4386eSCy Schubert {
32e0c4386eSCy Schubert     int success = 0;
33e0c4386eSCy Schubert     size_t l1 = 0, l2 = 0, l3 = 0;
34e0c4386eSCy Schubert     int s1 = 0, s3 = 0;
35e0c4386eSCy Schubert     BN_CTX *ctx;
36e0c4386eSCy Schubert     BIGNUM *b1;
37e0c4386eSCy Schubert     BIGNUM *b2;
38e0c4386eSCy Schubert     BIGNUM *b3;
39e0c4386eSCy Schubert     BIGNUM *b4;
40e0c4386eSCy Schubert     BIGNUM *b5;
41e0c4386eSCy Schubert 
42e0c4386eSCy Schubert     b1 = BN_new();
43e0c4386eSCy Schubert     b2 = BN_new();
44e0c4386eSCy Schubert     b3 = BN_new();
45e0c4386eSCy Schubert     b4 = BN_new();
46e0c4386eSCy Schubert     b5 = BN_new();
47e0c4386eSCy Schubert     ctx = BN_CTX_new();
48e0c4386eSCy Schubert 
49e0c4386eSCy Schubert     /* Divide the input into three parts, using the values of the first two
50e0c4386eSCy Schubert      * bytes to choose lengths, which generate b1, b2 and b3. Use three bits
51e0c4386eSCy Schubert      * of the third byte to choose signs for the three numbers.
52e0c4386eSCy Schubert      */
53e0c4386eSCy Schubert     if (len > 2) {
54e0c4386eSCy Schubert         len -= 3;
55*a7148ab3SEnji Cooper         /* limit l1, l2, and l3 to be no more than 512 bytes */
56*a7148ab3SEnji Cooper         l1 = ((buf[0] * len) / 255) % 512;
57e0c4386eSCy Schubert         ++buf;
58*a7148ab3SEnji Cooper         l2 = ((buf[0] * (len - l1)) / 255) % 512;
59e0c4386eSCy Schubert         ++buf;
60*a7148ab3SEnji Cooper         l3 = (len - l1 - l2) % 512;
61e0c4386eSCy Schubert 
62e0c4386eSCy Schubert         s1 = buf[0] & 1;
63e0c4386eSCy Schubert         s3 = buf[0] & 4;
64e0c4386eSCy Schubert         ++buf;
65e0c4386eSCy Schubert     }
66e0c4386eSCy Schubert     OPENSSL_assert(BN_bin2bn(buf, l1, b1) == b1);
67e0c4386eSCy Schubert     BN_set_negative(b1, s1);
68e0c4386eSCy Schubert     OPENSSL_assert(BN_bin2bn(buf + l1, l2, b2) == b2);
69e0c4386eSCy Schubert     OPENSSL_assert(BN_bin2bn(buf + l1 + l2, l3, b3) == b3);
70e0c4386eSCy Schubert     BN_set_negative(b3, s3);
71e0c4386eSCy Schubert 
72e0c4386eSCy Schubert     /* mod 0 is undefined */
73e0c4386eSCy Schubert     if (BN_is_zero(b3)) {
74e0c4386eSCy Schubert         success = 1;
75e0c4386eSCy Schubert         goto done;
76e0c4386eSCy Schubert     }
77e0c4386eSCy Schubert 
78e0c4386eSCy Schubert     OPENSSL_assert(BN_mod_exp(b4, b1, b2, b3, ctx));
79e0c4386eSCy Schubert     OPENSSL_assert(BN_mod_exp_simple(b5, b1, b2, b3, ctx));
80e0c4386eSCy Schubert 
81e0c4386eSCy Schubert     success = BN_cmp(b4, b5) == 0;
82e0c4386eSCy Schubert     if (!success) {
83e0c4386eSCy Schubert         BN_print_fp(stdout, b1);
84e0c4386eSCy Schubert         putchar('\n');
85e0c4386eSCy Schubert         BN_print_fp(stdout, b2);
86e0c4386eSCy Schubert         putchar('\n');
87e0c4386eSCy Schubert         BN_print_fp(stdout, b3);
88e0c4386eSCy Schubert         putchar('\n');
89e0c4386eSCy Schubert         BN_print_fp(stdout, b4);
90e0c4386eSCy Schubert         putchar('\n');
91e0c4386eSCy Schubert         BN_print_fp(stdout, b5);
92e0c4386eSCy Schubert         putchar('\n');
93e0c4386eSCy Schubert     }
94e0c4386eSCy Schubert 
95e0c4386eSCy Schubert  done:
96e0c4386eSCy Schubert     OPENSSL_assert(success);
97e0c4386eSCy Schubert     BN_free(b1);
98e0c4386eSCy Schubert     BN_free(b2);
99e0c4386eSCy Schubert     BN_free(b3);
100e0c4386eSCy Schubert     BN_free(b4);
101e0c4386eSCy Schubert     BN_free(b5);
102e0c4386eSCy Schubert     BN_CTX_free(ctx);
103e0c4386eSCy Schubert     ERR_clear_error();
104e0c4386eSCy Schubert 
105e0c4386eSCy Schubert     return 0;
106e0c4386eSCy Schubert }
107e0c4386eSCy Schubert 
FuzzerCleanup(void)108e0c4386eSCy Schubert void FuzzerCleanup(void)
109e0c4386eSCy Schubert {
110e0c4386eSCy Schubert }
111