1c7da899bSchristos /* 2*97e3c585Schristos * Copyright 2016-2024 The OpenSSL Project Authors. All Rights Reserved. 3c7da899bSchristos * 4b0d17251Schristos * Licensed under the Apache License 2.0 (the "License"); 5c7da899bSchristos * you may not use this file except in compliance with the License. 6c7da899bSchristos * You may obtain a copy of the License at 7c7da899bSchristos * https://www.openssl.org/source/license.html 8c7da899bSchristos * or in the file LICENSE in the source distribution. 9c7da899bSchristos */ 10c7da899bSchristos 11c7da899bSchristos /* 12c7da899bSchristos * Confirm that a^b mod c agrees when calculated cleverly vs naively, for 13c7da899bSchristos * random a, b and c. 14c7da899bSchristos */ 15c7da899bSchristos 16c7da899bSchristos #include <stdio.h> 17c7da899bSchristos #include <openssl/bn.h> 1813d40330Schristos #include <openssl/err.h> 19c7da899bSchristos #include "fuzzer.h" 20c7da899bSchristos 2113d40330Schristos 2213d40330Schristos int FuzzerInitialize(int *argc, char ***argv) 2313d40330Schristos { 2413d40330Schristos OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL); 25b0d17251Schristos ERR_clear_error(); 2613d40330Schristos 27c7da899bSchristos return 1; 28c7da899bSchristos } 29c7da899bSchristos 3013d40330Schristos int FuzzerTestOneInput(const uint8_t *buf, size_t len) 3113d40330Schristos { 32c7da899bSchristos int success = 0; 33c7da899bSchristos size_t l1 = 0, l2 = 0, l3 = 0; 3413d40330Schristos int s1 = 0, s3 = 0; 3513d40330Schristos BN_CTX *ctx; 3613d40330Schristos BIGNUM *b1; 3713d40330Schristos BIGNUM *b2; 3813d40330Schristos BIGNUM *b3; 3913d40330Schristos BIGNUM *b4; 4013d40330Schristos BIGNUM *b5; 41c7da899bSchristos 42c7da899bSchristos b1 = BN_new(); 43c7da899bSchristos b2 = BN_new(); 44c7da899bSchristos b3 = BN_new(); 45c7da899bSchristos b4 = BN_new(); 46c7da899bSchristos b5 = BN_new(); 47c7da899bSchristos ctx = BN_CTX_new(); 4813d40330Schristos 49c7da899bSchristos /* Divide the input into three parts, using the values of the first two 50c7da899bSchristos * bytes to choose lengths, which generate b1, b2 and b3. Use three bits 51c7da899bSchristos * of the third byte to choose signs for the three numbers. 52c7da899bSchristos */ 53c7da899bSchristos if (len > 2) { 54c7da899bSchristos len -= 3; 55*97e3c585Schristos /* limit l1, l2, and l3 to be no more than 512 bytes */ 56*97e3c585Schristos l1 = ((buf[0] * len) / 255) % 512; 57c7da899bSchristos ++buf; 58*97e3c585Schristos l2 = ((buf[0] * (len - l1)) / 255) % 512; 59c7da899bSchristos ++buf; 60*97e3c585Schristos l3 = (len - l1 - l2) % 512; 61c7da899bSchristos 62c7da899bSchristos s1 = buf[0] & 1; 63c7da899bSchristos s3 = buf[0] & 4; 64c7da899bSchristos ++buf; 65c7da899bSchristos } 66c7da899bSchristos OPENSSL_assert(BN_bin2bn(buf, l1, b1) == b1); 67c7da899bSchristos BN_set_negative(b1, s1); 68c7da899bSchristos OPENSSL_assert(BN_bin2bn(buf + l1, l2, b2) == b2); 69c7da899bSchristos OPENSSL_assert(BN_bin2bn(buf + l1 + l2, l3, b3) == b3); 70c7da899bSchristos BN_set_negative(b3, s3); 71c7da899bSchristos 72c7da899bSchristos /* mod 0 is undefined */ 73c7da899bSchristos if (BN_is_zero(b3)) { 74c7da899bSchristos success = 1; 75c7da899bSchristos goto done; 76c7da899bSchristos } 77c7da899bSchristos 78c7da899bSchristos OPENSSL_assert(BN_mod_exp(b4, b1, b2, b3, ctx)); 79c7da899bSchristos OPENSSL_assert(BN_mod_exp_simple(b5, b1, b2, b3, ctx)); 80c7da899bSchristos 81c7da899bSchristos success = BN_cmp(b4, b5) == 0; 82c7da899bSchristos if (!success) { 83c7da899bSchristos BN_print_fp(stdout, b1); 84c7da899bSchristos putchar('\n'); 85c7da899bSchristos BN_print_fp(stdout, b2); 86c7da899bSchristos putchar('\n'); 87c7da899bSchristos BN_print_fp(stdout, b3); 88c7da899bSchristos putchar('\n'); 89c7da899bSchristos BN_print_fp(stdout, b4); 90c7da899bSchristos putchar('\n'); 91c7da899bSchristos BN_print_fp(stdout, b5); 92c7da899bSchristos putchar('\n'); 93c7da899bSchristos } 94c7da899bSchristos 95c7da899bSchristos done: 96c7da899bSchristos OPENSSL_assert(success); 9713d40330Schristos BN_free(b1); 9813d40330Schristos BN_free(b2); 9913d40330Schristos BN_free(b3); 10013d40330Schristos BN_free(b4); 10113d40330Schristos BN_free(b5); 10213d40330Schristos BN_CTX_free(ctx); 10313d40330Schristos ERR_clear_error(); 104c7da899bSchristos 105c7da899bSchristos return 0; 106c7da899bSchristos } 10713d40330Schristos 10813d40330Schristos void FuzzerCleanup(void) 10913d40330Schristos { 11013d40330Schristos } 111