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