/* * Copyright (c) 2012-2020 MIRACL UK Ltd. * * This file is part of MIRACL Core * (see https://github.com/miracl/core). * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /** * @file big.h * @author Mike Scott * @date 23rd February 2016 * @brief Big number Header File * * */ #ifndef BIG_B168_29_H #define BIG_B168_29_H #include #include #include #include "arch.h" #include "core.h" #include "config_big_B168_29.h" using namespace core; /* could comment this out if code size is a major issue */ #define UNWOUND /* Normally recommended, but may not be optimal for some architectures, for example 32-bit ARM M4 */ #define USE_KARATSUBA #define BIGBITS_B168_29 (8*MODBYTES_B168_29) #define NLEN_B168_29 (1+((8*MODBYTES_B168_29-1)/BASEBITS_B168_29)) #define DNLEN_B168_29 2*NLEN_B168_29 #define BMASK_B168_29 (((chunk)1<y */ extern int BIG_comp(BIG x, BIG y); /** @brief Compares two DBIG numbers. Inputs must be normalised externally (Constant Time) * @param x first DBIG number to be compared @param y second DBIG number to be compared @return -1 is xy */ extern int BIG_dcomp(DBIG x, DBIG y); /** @brief Calculate number of bits in a BIG - output normalised (Variable Time) * @param x BIG number @return Number of bits in x */ extern int BIG_nbits(BIG x); /** @brief Calculate number of bits in a DBIG - output normalised (Variable Time) * @param x DBIG number @return Number of bits in x */ extern int BIG_dnbits(DBIG x); /** @brief Reduce x mod n - constant time for fixed bd * Slow but rarely used @param x BIG number to be reduced mod n @param n The modulus @param bd non-negative bit difference between maximum x and n */ extern void BIG_ctmod(BIG x, BIG n, int bd); /** @brief x=y mod n - constant time for fixed bd * Slow but rarely used. y is destroyed. @param x BIG number, on exit = y mod n @param y DBIG number @param n Modulus @param bd non-negative bit difference between maximum y and n */ extern void BIG_ctdmod(BIG x, DBIG y, BIG n, int bd); /** @brief Divide x by n - constant time for fixed bd * Slow but rarely used @param x BIG number to be divided by n @param n The Divisor @param bd non-negative bit difference between maximum x and n */ extern void BIG_ctsdiv(BIG x,BIG n,int bd); /** @brief x=y/n - constant time for fixed bd * Slow but rarely used. y is destroyed. @param x BIG number, on exit = y/n @param y DBIG number @param n Modulus @param bd non-negative bit difference between maximum y and n */ extern void BIG_ctddiv(BIG x, DBIG y, BIG n,int bd); /** @brief Reduce x mod n - input and output normalised (Variable Time) * Slow but rarely used @param x BIG number to be reduced mod n @param n The modulus */ extern void BIG_mod(BIG x, BIG n); /** @brief Divide x by n - output normalised (Variable Time) * Slow but rarely used @param x BIG number to be divided by n @param n The Divisor */ extern void BIG_sdiv(BIG x, BIG n); /** @brief x=y mod n - output normalised (Variable Time) * Slow but rarely used. y is destroyed. @param x BIG number, on exit = y mod n @param y DBIG number @param n Modulus */ extern void BIG_dmod(BIG x, DBIG y, BIG n); /** @brief x=y/n - output normalised (Variable Time) * Slow but rarely used. y is destroyed. @param x BIG number, on exit = y/n @param y DBIG number @param n Modulus */ extern void BIG_ddiv(BIG x, DBIG y, BIG n); /** @brief return parity of BIG, that is the least significant bit (Constant Time) * @param x BIG number @return 0 or 1 */ extern int BIG_parity(BIG x); /** @brief return i-th of BIG (Constant Time) * @param x BIG number @param i the bit of x to be returned @return 0 or 1 */ extern int BIG_bit(BIG x, int i); /** @brief return least significant bits of a BIG (Constant Time) * @param x BIG number @param n number of bits to return. Assumed to be less than BASEBITS. @return least significant n bits as an integer */ extern int BIG_lastbits(BIG x, int n); /** @brief Create a random BIG from a random number generator (Constant Time) * Assumes that the random number generator has been suitably initialised @param x BIG number, on exit a random number @param r A pointer to a Cryptographically Secure Random Number Generator */ extern void BIG_random(BIG x, csprng *r); /** @brief Create an unbiased random BIG from a random number generator, reduced with respect to a modulus (Constant Time as used) * Assumes that the random number generator has been suitably initialised @param x BIG number, on exit a random number @param n The modulus @param r A pointer to a Cryptographically Secure Random Number Generator */ extern void BIG_randomnum(BIG x, BIG n, csprng *r); /** @brief Create an unbiased random BIG from a random number generator, reduced with respect to a modulus and truncated to max bit length (Constant Time as used) * Assumes that the random number generator has been suitably initialised @param x BIG number, on exit a random number @param n The modulus @param t Maximum bit length @param r A pointer to a Cryptographically Secure Random Number Generator */ extern void BIG_randtrunc(BIG x, BIG n, int t, csprng *r); /** brief return NAF (Non-Adjacent-Form) value as +/- 1, 3 or 5, inputs must be normalised * Given x and 3*x extracts NAF value from given bit position, and returns number of bits processed, and number of trailing zeros detected if any param x BIG number param x3 BIG number, three times x param i bit position param nbs pointer to integer returning number of bits processed param nzs pointer to integer returning number of trailing 0s return + or - 1, 3 or 5 */ /** @brief Calculate x=y*z mod n (Variable Time) * Slow method for modular multiplication @param x BIG number, on exit = y*z mod n @param y BIG number @param z BIG number @param n The BIG Modulus */ extern void BIG_modmul(BIG x, BIG y, BIG z, BIG n); /** @brief Calculate x=y/z mod n (Variable Time) * Slow method for modular division @param x BIG number, on exit = y/z mod n @param y BIG number @param z BIG number @param n The BIG Modulus */ extern void BIG_moddiv(BIG x, BIG y, BIG z, BIG n); /** @brief Calculate x=y^2 mod n (Variable Time) * Slow method for modular squaring @param x BIG number, on exit = y^2 mod n @param y BIG number @param n The BIG Modulus */ extern void BIG_modsqr(BIG x, BIG y, BIG n); /** @brief Calculate x=-y mod n (Variable Time) * Modular negation @param x BIG number, on exit = -y mod n @param y BIG number @param n The BIG Modulus */ extern void BIG_modneg(BIG x, BIG y, BIG n); /** @brief Calculate x=y+z mod n (Variable Time) * Slow method for modular addition @param x BIG number, on exit = y+z mod n @param y BIG number @param z BIG number @param n The BIG Modulus */ extern void BIG_modadd(BIG x, BIG y, BIG z, BIG n); /** @brief Calculate jacobi Symbol (x/y) (Variable Time) * @param x BIG number @param y BIG number @return Jacobi symbol, -1,0 or 1 */ extern int BIG_jacobi(BIG x, BIG y); /** @brief Calculate x=1/y mod n (Variable Time) * Modular Inversion - This is slow. Uses binary method. @param x BIG number, on exit = 1/y mod n @param y BIG number @param n The BIG Modulus */ extern void BIG_invmodp(BIG x, BIG y, BIG n); /** @brief Calculate x=x mod 2^m (Variable Time) * Truncation @param x BIG number, on reduced mod 2^m @param m new truncated size */ extern void BIG_mod2m(BIG x, int m); /** @brief Calculates a*b+c+*d * Calculate partial product of a.b, add in carry c, and add total to d (Constant Time) @param a multiplier @param b multiplicand @param c carry @param d pointer to accumulated bottom half of result @return top half of result */ extern int step1(BIG,BIG,BIG); extern void step2(BIG,BIG,BIG); #ifdef dchunk /* Method required to calculate x*y+c+r, bottom half in r, top half returned */ inline chunk muladd(chunk x, chunk y, chunk c, chunk *r) { dchunk prod = (dchunk)x * y + c + *r; *r = (chunk)prod & BMASK_B168_29; return (chunk)(prod >> BASEBITS_B168_29); } #else /* No integer type available that can store double the wordlength */ /* accumulate partial products */ inline chunk muladd(chunk x, chunk y, chunk c, chunk *r) { chunk x0, x1, y0, y1; chunk bot, top, mid, carry; x0 = x & HMASK_B168_29; x1 = (x >> HBITS_B168_29); y0 = y & HMASK_B168_29; y1 = (y >> HBITS_B168_29); bot = x0 * y0; top = x1 * y1; mid = x0 * y1 + x1 * y0; x0 = mid & HMASK_B168_29; x1 = (mid >> HBITS_B168_29); bot += x0 << HBITS_B168_29; bot += *r; bot += c; top += x1; carry = bot >> BASEBITS_B168_29; bot &= BMASK_B168_29; top += carry; *r = bot; return top; } #endif } #endif