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