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 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 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 108e0c4386eSCy Schubert void FuzzerCleanup(void) 109e0c4386eSCy Schubert { 110e0c4386eSCy Schubert } 111