Compare commits

...
18 changed files with 151 additions and 128 deletions
+11
View File
@@ -448,6 +448,17 @@ static int uniCharNcasecmp(const Tcl_UniChar *ucs, const Tcl_UniChar *uct, unsig
# define TclpLocaltime_unix TclpLocaltime
# define TclpGmtime_unix TclpGmtime
# define TclOldFreeObj TclFreeObj
# define TclBN_reverse bn_reverse
# define TclBN_fast_s_mp_mul_digs fast_s_mp_mul_digs
# define TclBN_fast_s_mp_sqr fast_s_mp_sqr
# define TclBN_mp_karatsuba_mul mp_karatsuba_mul
# define TclBN_mp_karatsuba_sqr mp_karatsuba_sqr
# define TclBN_mp_toom_mul mp_toom_mul
# define TclBN_mp_toom_sqr mp_toom_sqr
# define TclBN_s_mp_add s_mp_add
# define TclBN_s_mp_mul_digs s_mp_mul_digs
# define TclBN_s_mp_sqr s_mp_sqr
# define TclBN_s_mp_sub s_mp_sub
static int
seekOld(
+2 -2
View File
@@ -239,10 +239,10 @@ declare 67 {
}
# Added in libtommath 1.0.1
declare 68 {
int TclBN_mp_set_long_long(mp_int *a, Tcl_WideUInt i)
int TclBN_mp_set_long_long(mp_int *a, unsigned TCL_WIDE_INT_TYPE i)
}
declare 69 {
Tcl_WideUInt TclBN_mp_get_long_long(const mp_int *a)
unsigned TCL_WIDE_INT_TYPE TclBN_mp_get_long_long(const mp_int *a)
}
declare 70 {
int TclBN_mp_set_long(mp_int *a, unsigned long i)
+57 -17
View File
@@ -7,8 +7,7 @@
* Michael Fromberger but has been written from scratch with
* additional optimizations in place.
*
* The library is free for all purposes without any express
* guarantee it works.
* SPDX-License-Identifier: Unlicense
*/
#ifndef BN_H_
#define BN_H_
@@ -25,7 +24,7 @@ extern "C" {
#endif
/* MS Visual C++ doesn't have a 128bit type for words, so fall back to 32bit MPI's (where words are 64bit) */
#if defined(_MSC_VER) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__)
#if defined(_WIN32) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__)
# define MP_32BIT
#endif
@@ -110,9 +109,6 @@ typedef unsigned long long mp_word;
/* otherwise the bits per digit is calculated automatically from the size of a mp_digit */
#ifndef DIGIT_BIT
# define DIGIT_BIT (((CHAR_BIT * MP_SIZEOF_MP_DIGIT) - 1)) /* bits per digit */
typedef unsigned long mp_min_u32;
#else
typedef mp_digit mp_min_u32;
#endif
#define MP_DIGIT_BIT DIGIT_BIT
@@ -131,6 +127,7 @@ typedef mp_digit mp_min_u32;
#define MP_MEM -2 /* out of mem */
#define MP_VAL -3 /* invalid input */
#define MP_RANGE MP_VAL
#define MP_ITER -4 /* Max. iterations reached */
#define MP_YES 1 /* yes response */
#define MP_NO 0 /* no response */
@@ -178,11 +175,6 @@ struct mp_int {
/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
#define USED(m) ((m)->used)
#define DIGIT(m, k) ((m)->dp[(k)])
#define SIGN(m) ((m)->sign)
/* error code to char* string */
const char *mp_error_to_string(int code);
@@ -243,6 +235,11 @@ void mp_zero(mp_int *a);
void mp_set(mp_int *a, mp_digit b);
*/
/* set a double */
/*
int mp_set_double(mp_int *a, double b);
*/
/* set a 32-bit const */
/*
int mp_set_int(mp_int *a, unsigned long b);
@@ -258,6 +255,11 @@ int mp_set_long(mp_int *a, unsigned long b);
int mp_set_long_long(mp_int *a, unsigned long long b);
*/
/* get a double */
/*
double mp_get_double(const mp_int *a);
*/
/* get a 32-bit value */
/*
unsigned long mp_get_int(const mp_int *a);
@@ -357,15 +359,20 @@ int mp_cnt_lsb(const mp_int *a);
/* I Love Earth! */
/* makes a pseudo-random int of a given size */
/* makes a pseudo-random mp_int of a given size */
/*
int mp_rand(mp_int *a, int digits);
*/
/* makes a pseudo-random small int of a given size */
/*
int mp_rand_digit(mp_digit *r);
*/
#ifdef MP_PRNG_ENABLE_LTM_RNG
/* as last resort we will fall back to libtomcrypt's rng_get_bytes()
* in case you don't use libtomcrypt or use it w/o rng_get_bytes()
* you have to implement it somewhere else, as it's required */
/* A last resort to provide random data on systems without any of the other
* implemented ways to gather entropy.
* It is compatible with `rng_get_bytes()` from libtomcrypt so you could
* provide that one and then set `ltm_rng = rng_get_bytes;` */
extern unsigned long (*ltm_rng)(unsigned char *out, unsigned long outlen, void (*callback)(void));
extern void (*ltm_rng_callback)(void);
#endif
@@ -386,6 +393,13 @@ int mp_or(const mp_int *a, const mp_int *b, mp_int *c);
int mp_and(const mp_int *a, const mp_int *b, mp_int *c);
*/
/* Checks the bit at position b and returns MP_YES
if the bit is 1, MP_NO if it is 0 and MP_VAL
in case of error */
/*
int mp_get_bit(const mp_int *a, int b);
*/
/* c = a XOR b (two complement) */
/*
int mp_tc_xor(const mp_int *a, const mp_int *b, mp_int *c);
@@ -581,6 +595,11 @@ int mp_is_square(const mp_int *arg, int *ret);
int mp_jacobi(const mp_int *a, const mp_int *n, int *c);
*/
/* computes the Kronecker symbol c = (a | p) (like jacobi() but with {a,p} in Z */
/*
int mp_kronecker(const mp_int *a, const mp_int *p, int *c);
*/
/* used to setup the Barrett reduction for a given modulus b */
/*
int mp_reduce_setup(mp_int *a, const mp_int *b);
@@ -702,10 +721,31 @@ int mp_prime_miller_rabin(const mp_int *a, const mp_int *b, int *result);
int mp_prime_rabin_miller_trials(int size);
*/
/* performs t rounds of Miller-Rabin on "a" using the first
* t prime bases. Also performs an initial sieve of trial
/* performs one strong Lucas-Selfridge test of "a".
* Sets result to 0 if composite or 1 if probable prime
*/
/*
int mp_prime_strong_lucas_selfridge(const mp_int *a, int *result);
*/
/* performs one Frobenius test of "a" as described by Paul Underwood.
* Sets result to 0 if composite or 1 if probable prime
*/
/*
int mp_prime_frobenius_underwood(const mp_int *N, int *result);
*/
/* performs t random rounds of Miller-Rabin on "a" additional to
* bases 2 and 3. Also performs an initial sieve of trial
* division. Determines if "a" is prime with probability
* of error no more than (1/4)**t.
* Both a strong Lucas-Selfridge to complete the BPSW test
* and a separate Frobenius test are available at compile time.
* With t<0 a deterministic test is run for primes up to
* 318665857834031151167461. With t<13 (abs(t)-13) additional
* tests with sequential small primes are run starting at 43.
* Is Fips 186.4 compliant if called with t as computed by
* mp_prime_rabin_miller_trials();
*
* Sets result to 1 if probably prime, 0 otherwise
*/
+23 -11
View File
@@ -44,9 +44,6 @@
#define TOOM_MUL_CUTOFF TclBNToomMulCutoff
#define TOOM_SQR_CUTOFF TclBNToomSqrCutoff
#define bn_reverse TclBN_reverse
#define fast_s_mp_mul_digs TclBN_fast_s_mp_mul_digs
#define fast_s_mp_sqr TclBN_fast_s_mp_sqr
#define mp_add TclBN_mp_add
#define mp_add_d TclBN_mp_add_d
#define mp_and TclBN_mp_and
@@ -78,8 +75,6 @@
#define mp_init_set TclBN_mp_init_set
#define mp_init_set_int TclBN_mp_init_set_int
#define mp_init_size TclBN_mp_init_size
#define mp_karatsuba_mul TclBN_mp_karatsuba_mul
#define mp_karatsuba_sqr TclBN_mp_karatsuba_sqr
#define mp_lshd TclBN_mp_lshd
#define mp_mod TclBN_mp_mod
#define mp_mod_2d TclBN_mp_mod_2d
@@ -107,16 +102,22 @@
#define mp_tc_xor TclBN_mp_tc_xor
#define mp_to_unsigned_bin TclBN_mp_to_unsigned_bin
#define mp_to_unsigned_bin_n TclBN_mp_to_unsigned_bin_n
#define mp_toom_mul TclBN_mp_toom_mul
#define mp_toom_sqr TclBN_mp_toom_sqr
#define mp_toradix_n TclBN_mp_toradix_n
#define mp_unsigned_bin_size TclBN_mp_unsigned_bin_size
#define mp_xor TclBN_mp_xor
#define mp_zero TclBN_mp_zero
#define s_mp_add TclBN_s_mp_add
#define s_mp_mul_digs TclBN_s_mp_mul_digs
#define s_mp_sqr TclBN_s_mp_sqr
#define s_mp_sub TclBN_s_mp_sub
MODULE_SCOPE void bn_reverse(unsigned char *s, int len);
MODULE_SCOPE int fast_s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs);
MODULE_SCOPE int fast_s_mp_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE int mp_karatsuba_mul(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE int mp_karatsuba_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE int mp_toom_mul(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE int mp_toom_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE int s_mp_add(const mp_int *a, const mp_int *b, mp_int *c);
MODULE_SCOPE int s_mp_mul_digs(const mp_int *a, const mp_int *b, mp_int *c, int digs);
MODULE_SCOPE int s_mp_sqr(const mp_int *a, mp_int *b);
MODULE_SCOPE int s_mp_sub(const mp_int *a, const mp_int *b, mp_int *c);
#undef TCL_STORAGE_CLASS
#ifdef BUILD_tcl
@@ -608,4 +609,15 @@ extern const TclTomMathStubs *tclTomMathStubsPtr;
#undef TCL_STORAGE_CLASS
#define TCL_STORAGE_CLASS DLLIMPORT
#undef TclBNInitBignumFromLong
#define TclBNInitBignumFromLong(value) TclBNInitBignumFromWideInt((long) value)
#ifdef USE_TCL_STUBS
# undef TclBN_mp_set_long
# ifdef TCL_WIDE_INT_IS_LONG
# define TclBN_mp_set_long(a, b) TclBN_mp_set_long_long(a, (unsigned long)b)
# else
# define TclBN_mp_set_long(a, b) TclBN_mp_set_int(a, b)
# endif
#endif
#endif /* _TCLINTDECLS */
+9 -4
View File
@@ -13,7 +13,7 @@
*/
#include "tclInt.h"
#include "tommath.h"
#include "tommath_private.h"
MODULE_SCOPE const TclTomMathStubs tclTomMathStubs;
@@ -106,6 +106,11 @@ TclBN_revision(void)
*----------------------------------------------------------------------
*/
#ifdef TCL_WIDE_INT_IS_LONG
# define TclBN_mp_set_long_long TclBN_mp_set_long
#endif
void
TclInitBignumFromWideInt(
mp_int *a, /* Bignum to initialize */
@@ -115,10 +120,10 @@ TclInitBignumFromWideInt(
Tcl_Panic("initialization failure in TclInitBignumFromWideInt");
}
if (v < 0) {
mp_set_long_long(a, (Tcl_WideUInt)(-v));
TclBN_mp_set_long_long(a, (Tcl_WideUInt)(-v));
mp_neg(a, a);
} else {
mp_set_long_long(a, (Tcl_WideUInt)v);
TclBN_mp_set_long_long(a, (Tcl_WideUInt)v);
}
}
@@ -146,7 +151,7 @@ TclInitBignumFromWideUInt(
if (mp_init_size(a, (CHAR_BIT * sizeof(Tcl_WideUInt) + DIGIT_BIT - 1) / DIGIT_BIT) != MP_OKAY) {
Tcl_Panic("initialization failure in TclInitBignumFromWideUInt");
}
mp_set_long_long(a, v);
TclBN_mp_set_long_long(a, v);
}
/*
+1 -1
View File
@@ -79,7 +79,7 @@ int fast_s_mp_sqr(const mp_int *a, mp_int *b)
}
/* store it */
W[ix] = _W & MP_MASK;
W[ix] = (mp_digit)_W & MP_MASK;
/* make next carry */
W1 = _W >> (mp_word)DIGIT_BIT;
+1 -11
View File
@@ -27,18 +27,8 @@ int mp_get_bit(const mp_int *a, int b)
limb = b / DIGIT_BIT;
/*
* Zero is a special value with the member "used" set to zero.
* Needs to be tested before the check for the upper boundary
* otherwise (limb >= a->used) would be true for a = 0
*/
if (mp_iszero(a) != MP_NO) {
return MP_NO;
}
if (limb >= a->used) {
return MP_VAL;
return MP_NO;
}
bit = (mp_digit)(1) << (b % DIGIT_BIT);
+2 -2
View File
@@ -19,8 +19,8 @@ double mp_get_double(const mp_int *a)
for (i = 0; i < DIGIT_BIT; ++i) {
fac *= 2.0;
}
for (i = USED(a); i --> 0;) {
d = (d * fac) + (double)DIGIT(a, i);
for (i = a->used; i --> 0;) {
d = (d * fac) + (double)a->dp[i];
}
return (mp_isneg(a) != MP_NO) ? -d : d;
}
+1 -18
View File
@@ -15,25 +15,8 @@
/* get the lower 32-bits of an mp_int */
unsigned long mp_get_int(const mp_int *a)
{
int i;
mp_min_u32 res;
if (a->used == 0) {
return 0;
}
/* get number of digits of the lsb we have to read */
i = MIN(a->used, ((((int)sizeof(unsigned long) * CHAR_BIT) + DIGIT_BIT - 1) / DIGIT_BIT)) - 1;
/* get most significant digit of result */
res = DIGIT(a, i);
while (--i >= 0) {
res = (res << DIGIT_BIT) | DIGIT(a, i);
}
/* force result to 32-bits always so it is consistent on non 32-bit platforms */
return res & 0xFFFFFFFFUL;
return mp_get_long(a) & 0xFFFFFFFFUL;
}
#endif
+3 -3
View File
@@ -26,11 +26,11 @@ unsigned long mp_get_long(const mp_int *a)
i = MIN(a->used, ((((int)sizeof(unsigned long) * CHAR_BIT) + DIGIT_BIT - 1) / DIGIT_BIT)) - 1;
/* get most significant digit of result */
res = DIGIT(a, i);
res = (unsigned long)a->dp[i];
#if (ULONG_MAX != 0xffffffffuL) || (DIGIT_BIT < 32)
#if (ULONG_MAX != 0xFFFFFFFFUL) || (DIGIT_BIT < 32)
while (--i >= 0) {
res = (res << DIGIT_BIT) | DIGIT(a, i);
res = (res << DIGIT_BIT) | (unsigned long)a->dp[i];
}
#endif
return res;
+5 -5
View File
@@ -13,24 +13,24 @@
*/
/* get the lower unsigned long long of an mp_int, platform dependent */
Tcl_WideUInt mp_get_long_long(const mp_int *a)
unsigned TCL_WIDE_INT_TYPE mp_get_long_long(const mp_int *a)
{
int i;
Tcl_WideUInt res;
unsigned TCL_WIDE_INT_TYPE res;
if (a->used == 0) {
return 0;
}
/* get number of digits of the lsb we have to read */
i = MIN(a->used, ((((int)sizeof(Tcl_WideUInt) * CHAR_BIT) + DIGIT_BIT - 1) / DIGIT_BIT)) - 1;
i = MIN(a->used, ((((int)sizeof(unsigned TCL_WIDE_INT_TYPE) * CHAR_BIT) + DIGIT_BIT - 1) / DIGIT_BIT)) - 1;
/* get most significant digit of result */
res = DIGIT(a, i);
res = (unsigned TCL_WIDE_INT_TYPE)a->dp[i];
#if DIGIT_BIT < 64
while (--i >= 0) {
res = (res << DIGIT_BIT) | DIGIT(a, i);
res = (res << DIGIT_BIT) | (unsigned TCL_WIDE_INT_TYPE)a->dp[i];
}
#endif
return res;
+1 -1
View File
@@ -55,7 +55,7 @@ int mp_is_square(const mp_int *arg, int *ret)
}
/* First check mod 128 (suppose that DIGIT_BIT is at least 7) */
if (rem_128[127u & DIGIT(arg, 0)] == (char)1) {
if (rem_128[127u & arg->dp[0]] == (char)1) {
return MP_OKAY;
}
+1 -1
View File
@@ -18,7 +18,7 @@
*/
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__)
#define MP_ARC4RANDOM
#define MP_GEN_RANDOM_MAX 0xffffffffu
#define MP_GEN_RANDOM_MAX 0xFFFFFFFFU
#define MP_GEN_RANDOM_SHIFT 32
static int s_read_arc4random(mp_digit *p)
+1 -1
View File
@@ -42,7 +42,7 @@ int mp_set_double(mp_int *a, double b)
}
if (((cast.bits >> 63) != 0ULL) && (mp_iszero(a) == MP_NO)) {
SIGN(a) = MP_NEG;
a->sign = MP_NEG;
}
return MP_OKAY;
+1 -22
View File
@@ -15,28 +15,7 @@
/* set a 32-bit const */
int mp_set_int(mp_int *a, unsigned long b)
{
int x, res;
mp_zero(a);
/* set four bits at a time */
for (x = 0; x < 8; x++) {
/* shift the number up four bits */
if ((res = mp_mul_2d(a, 4, a)) != MP_OKAY) {
return res;
}
/* OR in the top four bits of the source */
a->dp[0] |= (mp_digit)(b >> 28) & 15uL;
/* shift the source up to the next four bits */
b <<= 4;
/* ensure that digits are not clamped off */
a->used += 1;
}
mp_clamp(a);
return MP_OKAY;
return mp_set_long(a, b & 0xFFFFFFFFUL);
}
#endif
+1 -1
View File
@@ -13,7 +13,7 @@
*/
/* set a platform dependent unsigned long long int */
MP_SET_XLONG(mp_set_long_long, Tcl_WideUInt)
MP_SET_XLONG(mp_set_long_long, unsigned TCL_WIDE_INT_TYPE)
#endif
/* ref: $Format:%D$ */
+21 -5
View File
@@ -23,7 +23,7 @@ extern "C" {
#endif
/* MS Visual C++ doesn't have a 128bit type for words, so fall back to 32bit MPI's (where words are 64bit) */
#if defined(_MSC_VER) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__)
#if defined(_WIN32) || defined(__LLP64__) || defined(__e2k__) || defined(__LCC__)
# define MP_32BIT
#endif
@@ -45,8 +45,6 @@ extern "C" {
# endif
#endif
typedef unsigned long long Tcl_WideUInt;
/* some default configurations.
*
* A "mp_digit" must be able to hold DIGIT_BIT + 1 bits
@@ -65,6 +63,7 @@ typedef unsigned short mp_word;
#elif defined(MP_16BIT)
typedef unsigned short mp_digit;
typedef unsigned int mp_word;
#endif
# define MP_SIZEOF_MP_DIGIT 2
# ifdef DIGIT_BIT
# error You must not define DIGIT_BIT when using MP_16BIT
@@ -79,7 +78,12 @@ typedef unsigned long mp_word __attribute__((mode(TI)));
/* this is to make porting into LibTomCrypt easier :-) */
typedef unsigned int mp_digit;
#ifdef _WIN32
typedef unsigned __int64 mp_word;
#else
typedef unsigned long long mp_word;
#endif
#endif
# ifdef MP_31BIT
/* this is an extension that uses 31-bit digits */
@@ -149,10 +153,14 @@ extern int KARATSUBA_MUL_CUTOFF,
#define MP_WARRAY (1u << (((sizeof(mp_word) * CHAR_BIT) - (2 * DIGIT_BIT)) + 1))
/* the infamous mp_int structure */
typedef struct {
#ifndef MP_INT_DECLARED
#define MP_INT_DECLARED
typedef struct mp_int mp_int;
#endif
struct mp_int {
int used, alloc, sign;
mp_digit *dp;
} mp_int;
};
/* callback for mp_prime_random, should fill dst with random bytes and return how many read [upto len] */
typedef int ltm_prime_callback(unsigned char *dst, int len, void *dat);
@@ -212,7 +220,11 @@ int mp_set_int(mp_int *a, unsigned long b);
int mp_set_long(mp_int *a, unsigned long b);
/* set a platform dependent unsigned long long value */
#ifdef _WIN32
int mp_set_long_long(mp_int *a, unsigned __int64 b);
#else
int mp_set_long_long(mp_int *a, unsigned long long b);
#endif
/* get a double */
double mp_get_double(const mp_int *a);
@@ -224,7 +236,11 @@ unsigned long mp_get_int(const mp_int *a);
unsigned long mp_get_long(const mp_int *a);
/* get a platform dependent unsigned long long value */
#ifdef _WIN32
unsigned __int64 mp_get_long_long(const mp_int *a);
#else
unsigned long long mp_get_long_long(const mp_int *a);
#endif
/* initialize and set a digit */
int mp_init_set(mp_int *a, mp_digit b);
+10 -23
View File
@@ -85,29 +85,16 @@ extern const size_t mp_s_rmap_reverse_sz;
#define MP_SET_XLONG(func_name, type) \
int func_name (mp_int * a, type b) \
{ \
unsigned int x; \
int res; \
\
mp_zero (a); \
\
/* set four bits at a time */ \
for (x = 0; x < (sizeof(type) * 2u); x++) { \
/* shift the number up four bits */ \
if ((res = mp_mul_2d (a, 4, a)) != MP_OKAY) { \
return res; \
} \
\
/* OR in the top four bits of the source */ \
a->dp[0] |= (mp_digit)(b >> ((sizeof(type) * 8u) - 4u)) & 15uL;\
\
/* shift the source up to the next four bits */ \
b <<= 4; \
\
/* ensure that digits are not clamped off */ \
a->used += 1; \
} \
mp_clamp (a); \
return MP_OKAY; \
unsigned int x = 0; \
int res = mp_grow(a, (CHAR_BIT * sizeof(type) + DIGIT_BIT - 1) / DIGIT_BIT); \
if (res == MP_OKAY) { \
while (b) { \
a->dp[x++] = ((mp_digit)b & MP_MASK); \
b >>= DIGIT_BIT; \
} \
a->used = x; \
} \
return res; \
}
#ifdef __cplusplus