Hash :
7a68f128
Author :
Date :
2019-10-19T16:24:39
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
/* LibTomMath, multiple-precision integer library -- Tom St Denis */
/* SPDX-License-Identifier: Unlicense */
#ifndef TOMMATH_PRIVATE_H_
#define TOMMATH_PRIVATE_H_
#include "tommath.h"
#include "tommath_class.h"
#include <limits.h>
/*
* Private symbols
* ---------------
*
* On Unix symbols can be marked as hidden if libtommath is compiled
* as a shared object. By default, symbols are visible.
* On Win32 a .def file must be used to specify the exported symbols.
*/
#if defined(__GNUC__) && __GNUC__ >= 4 && !defined(_WIN32)
# define MP_PRIVATE __attribute__ ((visibility ("hidden")))
#else
# define MP_PRIVATE
#endif
/* Hardening libtommath
* --------------------
*
* By default memory is zeroed before calling
* MP_FREE to avoid leaking data. This is good
* practice in cryptographical applications.
*
* Note however that memory allocators used
* in cryptographical applications can often
* be configured by itself to clear memory,
* rendering the clearing in tommath unnecessary.
* See for example https://github.com/GrapheneOS/hardened_malloc
* and the option CONFIG_ZERO_ON_FREE.
*
* Furthermore there are applications which
* value performance more and want this
* feature to be disabled. For such applications
* define MP_NO_ZERO_ON_FREE during compilation.
*/
#ifdef MP_NO_ZERO_ON_FREE
# define MP_FREE_BUFFER(mem, size) MP_FREE((mem), (size))
# define MP_FREE_DIGITS(mem, digits) MP_FREE((mem), sizeof (mp_digit) * (size_t)(digits))
#else
# define MP_FREE_BUFFER(mem, size) \
do { \
size_t fs_ = (size); \
void* fm_ = (mem); \
if (fm_ != NULL) { \
MP_ZERO_BUFFER(fm_, fs_); \
MP_FREE(fm_, fs_); \
} \
} while (0)
# define MP_FREE_DIGITS(mem, digits) \
do { \
int fd_ = (digits); \
void* fm_ = (mem); \
if (fm_ != NULL) { \
size_t fs_ = sizeof (mp_digit) * (size_t)fd_; \
MP_ZERO_BUFFER(fm_, fs_); \
MP_FREE(fm_, fs_); \
} \
} while (0)
#endif
#ifdef MP_USE_MEMSET
# include <string.h>
# define MP_ZERO_BUFFER(mem, size) memset((mem), 0, (size))
# define MP_ZERO_DIGITS(mem, digits) \
do { \
int zd_ = (digits); \
if (zd_ > 0) { \
memset((mem), 0, sizeof(mp_digit) * (size_t)zd_); \
} \
} while (0)
#else
# define MP_ZERO_BUFFER(mem, size) \
do { \
size_t zs_ = (size); \
char* zm_ = (char*)(mem); \
while (zs_-- > 0u) { \
*zm_++ = '\0'; \
} \
} while (0)
# define MP_ZERO_DIGITS(mem, digits) \
do { \
int zd_ = (digits); \
mp_digit* zm_ = (mem); \
while (zd_-- > 0) { \
*zm_++ = 0; \
} \
} while (0)
#endif
/* Tunable cutoffs
* ---------------
*
* - In the default settings, a cutoff X can be modified at runtime
* by adjusting the corresponding X_CUTOFF variable.
*
* - Tunability of the library can be disabled at compile time
* by defining the MP_FIXED_CUTOFFS macro.
*
* - There is an additional file tommath_cutoffs.h, which defines
* the default cutoffs. These can be adjusted manually or by the
* autotuner.
*
*/
#ifdef MP_FIXED_CUTOFFS
# include "tommath_cutoffs.h"
# define MP_KARATSUBA_MUL_CUTOFF MP_DEFAULT_KARATSUBA_MUL_CUTOFF
# define MP_KARATSUBA_SQR_CUTOFF MP_DEFAULT_KARATSUBA_SQR_CUTOFF
# define MP_TOOM_MUL_CUTOFF MP_DEFAULT_TOOM_MUL_CUTOFF
# define MP_TOOM_SQR_CUTOFF MP_DEFAULT_TOOM_SQR_CUTOFF
#else
# define MP_KARATSUBA_MUL_CUTOFF KARATSUBA_MUL_CUTOFF
# define MP_KARATSUBA_SQR_CUTOFF KARATSUBA_SQR_CUTOFF
# define MP_TOOM_MUL_CUTOFF TOOM_MUL_CUTOFF
# define MP_TOOM_SQR_CUTOFF TOOM_SQR_CUTOFF
#endif
/* define heap macros */
#ifndef MP_MALLOC
/* default to libc stuff */
# include <stdlib.h>
# define MP_MALLOC(size) malloc(size)
# define MP_REALLOC(mem, oldsize, newsize) realloc((mem), (newsize))
# define MP_CALLOC(nmemb, size) calloc((nmemb), (size))
# define MP_FREE(mem, size) free(mem)
#else
/* prototypes for our heap functions */
extern void *MP_MALLOC(size_t size);
extern void *MP_REALLOC(void *mem, size_t oldsize, size_t newsize);
extern void *MP_CALLOC(size_t nmemb, size_t size);
extern void MP_FREE(void *mem, size_t size);
#endif
/* feature detection macro */
#define MP_STRINGIZE(x) MP__STRINGIZE(x)
#define MP__STRINGIZE(x) ""#x""
#define MP_HAS(x) (sizeof(MP_STRINGIZE(x##_C)) == 1u)
/* TODO: Remove private_mp_word as soon as deprecated mp_word is removed from tommath. */
typedef private_mp_word mp_word;
#define MP_MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MP_MAX(x, y) (((x) > (y)) ? (x) : (y))
/* Static assertion */
#define MP_STATIC_ASSERT(msg, cond) typedef char mp_static_assert_##msg[(cond) ? 1 : -1];
/* ---> Basic Manipulations <--- */
#define MP_IS_ZERO(a) ((a)->used == 0)
#define MP_IS_EVEN(a) (((a)->used == 0) || (((a)->dp[0] & 1u) == 0u))
#define MP_IS_ODD(a) (((a)->used > 0) && (((a)->dp[0] & 1u) == 1u))
#define MP_SIZEOF_BITS(type) ((size_t)CHAR_BIT * sizeof(type))
#define MP_MAXFAST (int)(1uL << (MP_SIZEOF_BITS(mp_word) - (2u * (size_t)MP_DIGIT_BIT)))
#define MP_WARRAY (1 << ((MP_SIZEOF_BITS(mp_word) - (2 * MP_DIGIT_BIT)) + 1))
/* default precision */
#ifndef MP_PREC
# ifndef MP_LOW_MEM
# define MP_PREC 32 /* default digits of precision */
# elif defined(MP_8BIT)
# define MP_PREC 16 /* default digits of precision */
# else
# define MP_PREC 8 /* default digits of precision */
# endif
#endif
/* Minimum number of available digits in mp_int, MP_PREC >= MP_MIN_PREC */
#define MP_MIN_PREC ((((int)MP_SIZEOF_BITS(long long) + MP_DIGIT_BIT) - 1) / MP_DIGIT_BIT)
MP_STATIC_ASSERT(prec_geq_min_prec, MP_PREC >= MP_MIN_PREC)
/* random number source */
extern MP_PRIVATE mp_err(*s_mp_rand_source)(void *out, size_t size);
/* lowlevel functions, do not call! */
MP_PRIVATE mp_bool s_mp_get_bit(const mp_int *a, unsigned int b);
MP_PRIVATE mp_err s_mp_add(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_mul_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR;
MP_PRIVATE mp_err s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR;
MP_PRIVATE mp_err s_mp_mul_high_digs_fast(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR;
MP_PRIVATE mp_err s_mp_mul_high_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs) MP_WUR;
MP_PRIVATE mp_err s_mp_sqr_fast(const mp_int *a, mp_int *b) MP_WUR;
MP_PRIVATE mp_err s_mp_sqr(const mp_int *a, mp_int *b) MP_WUR;
MP_PRIVATE mp_err s_mp_balance_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_karatsuba_sqr(const mp_int *a, mp_int *b) MP_WUR;
MP_PRIVATE mp_err s_mp_toom_sqr(const mp_int *a, mp_int *b) MP_WUR;
MP_PRIVATE mp_err s_mp_invmod_fast(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_invmod_slow(const mp_int *a, const mp_int *b, mp_int *c) MP_WUR;
MP_PRIVATE mp_err s_mp_montgomery_reduce_fast(mp_int *x, const mp_int *n, mp_digit rho) MP_WUR;
MP_PRIVATE mp_err s_mp_exptmod_fast(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR;
MP_PRIVATE mp_err s_mp_exptmod(const mp_int *G, const mp_int *X, const mp_int *P, mp_int *Y, int redmode) MP_WUR;
MP_PRIVATE mp_err s_mp_rand_platform(void *p, size_t n) MP_WUR;
typedef int mp_prime_callback(unsigned char *dst, int len, void *dat);
MP_PRIVATE mp_err s_mp_prime_random_ex(mp_int *a, int t, int size, int flags, mp_prime_callback cb, void *dat);
MP_PRIVATE void s_mp_reverse(unsigned char *s, size_t len);
MP_PRIVATE mp_err s_mp_prime_is_divisible(const mp_int *a, mp_bool *result);
/* TODO: jenkins prng is not thread safe as of now */
MP_PRIVATE mp_err s_mp_rand_jenkins(void *p, size_t n) MP_WUR;
MP_PRIVATE void s_mp_rand_jenkins_init(uint64_t seed);
#define MP_RMAP_REVERSE_SIZE 88
extern MP_PRIVATE const char s_mp_rmap[];
extern MP_PRIVATE const uint8_t s_mp_rmap_reverse[];
extern MP_PRIVATE const mp_digit s_mp_prime_tab[];
/* number of primes */
#ifdef MP_8BIT
# define MP_PRIME_TAB_SIZE 31
#else
# define MP_PRIME_TAB_SIZE 256
#endif
#define MP_GET_ENDIANNESS(x) \
do{\
int16_t n = 0x1; \
char *p = (char *)&n; \
x = (p[0] == '\x01') ? MP_LITTLE_ENDIAN : MP_BIG_ENDIAN; \
} while (0)
/* code-generating macros */
#define MP_SET_UNSIGNED(name, type) \
void name(mp_int * a, type b) \
{ \
int i = 0; \
while (b != 0u) { \
a->dp[i++] = ((mp_digit)b & MP_MASK); \
if (MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) { break; } \
b >>= ((MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) ? 0 : MP_DIGIT_BIT); \
} \
a->used = i; \
a->sign = MP_ZPOS; \
MP_ZERO_DIGITS(a->dp + a->used, a->alloc - a->used); \
}
#define MP_SET_SIGNED(name, uname, type, utype) \
void name(mp_int * a, type b) \
{ \
uname(a, (b < 0) ? -(utype)b : (utype)b); \
if (b < 0) { a->sign = MP_NEG; } \
}
#define MP_INIT_INT(name , set, type) \
mp_err name(mp_int * a, type b) \
{ \
mp_err err; \
if ((err = mp_init(a)) != MP_OKAY) { \
return err; \
} \
set(a, b); \
return MP_OKAY; \
}
#define MP_GET_MAG(name, type) \
type name(const mp_int* a) \
{ \
unsigned i = MP_MIN((unsigned)a->used, (unsigned)((MP_SIZEOF_BITS(type) + MP_DIGIT_BIT - 1) / MP_DIGIT_BIT)); \
type res = 0u; \
while (i --> 0u) { \
res <<= ((MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) ? 0 : MP_DIGIT_BIT); \
res |= (type)a->dp[i]; \
if (MP_SIZEOF_BITS(type) <= MP_DIGIT_BIT) { break; } \
} \
return res; \
}
#define MP_GET_SIGNED(name, mag, type, utype) \
type name(const mp_int* a) \
{ \
utype res = mag(a); \
return (a->sign == MP_NEG) ? (type)-res : (type)res; \
}
#endif