first and last commit

This commit is contained in:
Chris Nutter committed 2023-07-08 13:03:17 -07:00
commit 1bf4efd552
2612 files changed
+636500

No files matched your search

+63
View File
@@ -0,0 +1,63 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantDebug.c - debugging support
*
* Created Aug. 5 2005 by Doug Mitchell.
*/
#include <libGiants/giantDebug.h>
#include <libGiants/giantTypes.h>
#if GIANTS_DEBUG
void GIRaise(const char *str)
{
printf("Fatal libGiants library error: %s\n", str);
exit(1);
}
#endif /* GIANTS_DEBUG */
#if GI_STACK_DEBUG
void *gInitSp;
void *giLowestSp;
void GI_SET_INIT_SP(void)
{
gInitSp = GI_GET_SP();
giLowestSp = NULL;
}
#ifdef __ppc__
void *GI_GET_SP(void)
{
void *currsp;
asm("mr %0,r1" : "=r"(currsp) : );
return currsp;
}
#else
#ifdef __i386__
void *GI_GET_SP(void)
{
register void *sp __asm__("esp");
return sp;
}
#else
#ifdef __arm__
void *GI_GET_SP(void)
{
register void *sp __asm__("r13");
return sp;
}
#else
#error Need a platform-dependent GI_GET_SP()
#endif
#endif
#endif
#endif /* GI_STACK_DEBUG */
+101
View File
@@ -0,0 +1,101 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantDebug.h - debugging support.
*
* Created Aug. 5 2005 by Doug Mitchell.
*/
#ifndef _GIANT_DEBUG_H_
#define _GIANT_DEBUG_H_
#include <libGiants/giantPlatform.h>
#ifdef __cplusplus
extern "C" {
#endif
#ifndef GIANTS_DEBUG
/* Should be defined in giantPlatform.h */
#error Please defgine GIANTS_DEBUG.
#endif
#if GIANTS_DEBUG
#include <assert.h>
#include <debug.h>
#include <stdlib.h>
#include <stdio.h>
#define dbgLog(str) printf(str)
#define GIASSERT(s) assert(s)
#else /* GIANTS_DEBUG */
#define dbgLog(str)
#define GIASSERT(s)
#endif /* GIANTS_DEBUG */
#undef NULL
#define NULL ((void *)0)
#if GIANTS_DEBUG
void GIRaise(const char *str) __attribute((noreturn));
#else
#define GIRaise(s)
#endif
/* detect overflow og giant->n[] */
#define CHECK_GIANT_OFLOW(g) GIASSERT((g)->sign <= (g)->capacity)
/* stack analysis support */
#if GI_STACK_DEBUG
#include <stdio.h>
extern void *gInitSp;
extern void *giLowestSp;
extern void GI_SET_INIT_SP(void);
extern void *GI_GET_SP(void);
static inline void GI_CHECK_SP(const char *fcn)
{
void *currSp = GI_GET_SP();
if((giLowestSp == NULL) || (currSp < giLowestSp)) {
giLowestSp = currSp;
printf("%s: new min sp %p; stack used %d\n", fcn,
giLowestSp,
gInitSp ? (gInitSp - giLowestSp) : 0);
}
}
/* this does some fine-grain stack logging regardless of giLowestSp */
#if GI_STACK_LOG
static inline void GI_LOG_SP(const char *fcn)
{
void *currSp = GI_GET_SP();
printf("%s: sp %p; stack used %d\n",
fcn, currSp,
gInitSp ? (gInitSp - currSp) : 0);
}
#else
#define GI_LOG_SP(fcn)
#endif /* GI_STACK_LOG */
#else /* GI_STACK_DEBUG */
#define GI_SET_INIT_SP()
#define GI_GET_SP()
#define GI_CHECK_SP(fcn)
#define GI_LOG_SP(fcn)
#endif /* GI_STACK_DEBUG */
#ifdef __cplusplus
}
#endif
#endif /* _GIANT_DEBUG_H_ */
+191
View File
@@ -0,0 +1,191 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantExternal.c - convert between giant integer and external representation
*
* Created Aug. 5 2005 by Doug Mitchell.
*/
#include <libGiants/giantTypes.h>
#include <libGiants/giantExternal.h>
#include <libGiants/giantDebug.h>
#include <stdlib.h>
/*
* Precalculate actual size in bytes needed to serialize a given giant.
*/
gi_uint16 serializeGiantBytes(const giant g)
{
gi_size numDigits, numZeros, digitByte;
giantDigit digit;
gtrimSign(g);
numDigits = g->sign;
if(numDigits == 0) {
return 0;
}
/* Count the number of leading 0 bytes in the m.s. digit. */
numZeros = 0;
digit = g->n[numDigits - 1];
for(digitByte=0; digitByte<GIANT_BYTES_PER_DIGIT; digitByte++) {
/* one loop per byte in the digit */
gi_uint8 byte = (gi_uint8)digit;
digit >>= 8;
if (byte) {
numZeros = 0;
} else {
numZeros++;
}
}
return (numDigits * GIANT_BYTES_PER_DIGIT) - numZeros;
}
/*
* Serialize, deserialize giants's n[] to/from byte stream.
* First byte of byte stream is the m.s. byte of the resulting giant,
* regardless of the size of giantDigit.
*
* No assumption is made about the alignment of cp.
*
* The numBytes argument indicates the space available on input;
* on return it indicates the actual number of bytes written.
*/
GIReturn serializeGiant(
const giant g,
gi_uint8 *cp,
gi_uint16 *numBytes) /* IN/OUT */
{
gi_size digitDex, numDigits, digitByte, totalBytes, bytesLeft;
gi_uint8 *currCp;
giantDigit digit;
GI_CHECK_SP("serializeGiant");
if((g == NULL) || (cp == NULL) || (numBytes == NULL)) {
return GR_IllegalArg;
}
totalBytes = serializeGiantBytes(g);
if(totalBytes == 0) {
*numBytes = 0;
return GR_Success;
}
numDigits = g->sign;
if(totalBytes > *numBytes) {
dbgLog("serializeGiant: Insufficient space\n");
return GR_Overflow;
}
/*
* Emit bytes starting at the far end of the outgoing byte
* stream, which is the l.s. byte of giant data. In order to prevent
* writing out leading zeros, we special case the m.s. digit.
*/
currCp = cp + totalBytes - 1;
for(digitDex=0; digitDex<numDigits - 1; digitDex++) {
/* one loop per giant digit */
digit = g->n[digitDex];
for(digitByte=0; digitByte<GIANT_BYTES_PER_DIGIT; digitByte++) {
/* one loop per byte in the digit */
*currCp-- = (gi_uint8)digit;
digit >>= 8;
}
}
/* Handle the m.s. digit, by writing out only as many bytes as are left.
Since we already wrote out numDigits - 1 digits above the answer is: */
bytesLeft = totalBytes - (numDigits - 1) * GIANT_BYTES_PER_DIGIT;
digit = g->n[digitDex];
for(digitByte=0; digitByte<bytesLeft; digitByte++) {
/* one loop per byte in the digit */
*currCp-- = (gi_uint8)digit;
digit >>= 8;
}
*numBytes = totalBytes;
return GR_Success;
}
/*
* Initialize a giant with specified data. Does not have to be
* aligned to giantDigits (as the output of serializeGiant() always
* is).
*/
GIReturn deserializeGiant(
giant g,
const gi_uint8 *cp,
gi_uint16 numBytes)
{
gi_size numDigits;
giantDigit digit;
giantDigit tempDigit;
gi_size digitDex;
gi_size digitByte;
gi_size dex;
const gi_uint8 *currCp;
GI_CHECK_SP("deserializeGiant");
if(g == NULL) {
return GR_IllegalArg;
}
if(numBytes == 0) {
g->sign = 0;
return GR_Success;
}
if(cp == NULL) {
return GR_IllegalArg;
}
/*
* Trim off leading zeroes, sometimes placed there during DER
* encoding to ensure the number does not appear negative. We
* don't support negative numbers in this module...
*/
while((*cp == 0) && (numBytes != 0)) {
cp++;
numBytes--;
}
if(numBytes == 0) {
g->sign = 0;
return GR_Success;
}
numDigits = BYTES_TO_GIANT_DIGITS(numBytes);
if(numDigits > g->capacity) {
return GR_Overflow;
}
/*
* Start at l.s. byte, at the far end of the byte stream.
*/
digitDex = 0; /* index into g->n[] */
digit = 0; /* accumulator */
digitByte = 0; /* byte index into digit */
currCp = cp + numBytes - 1;
for(dex=0; dex<numBytes; dex++) {
/* add in current byte */
tempDigit = *currCp--;
tempDigit <<= (8 * digitByte);
digit |= tempDigit;
digitByte++;
/* have a complete digit, or reached the last byte? */
if((digitByte == GIANT_BYTES_PER_DIGIT) || /* full digit */
(dex == (numBytes - 1))) { /* no more data */
g->n[digitDex++] = digit;
/* reset for next digit */
digit = 0;
digitByte = 0;
}
}
/*
* Infer sign/size from non-zero n[] elements
*/
g->sign = numDigits;
gtrimSign(g);
return GR_Success;
}
+59
View File
@@ -0,0 +1,59 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantExternal.h - convert between giant integer and external representation
*
* Created Aug. 5 2005 by Doug Mitchell.
*/
#ifndef _GIANT_EXTERNAL_H_
#define _GIANT_EXTERNAL_H_
#include <libGiants/giantIntegers.h>
#include <libGiants/giantTypes.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Max size in bytes needed to serialize a giant of given number of digits.
*/
#define MAX_SERIALIZED_GIANT_SIZE(digits) (GIANT_BYTES_PER_DIGIT * digits)
/*
* Precalculate actual size in bytes needed to serialize a given giant.
*/
gi_uint16 serializeGiantBytes(const giant g);
/*
* serialize, deserialize giants's n[] to/from byte stream.
* First byte of byte stream is the m.s. byte of the resulting giant,
* regardless of the size of giantDigit. The resulting byte stream
* is suitable for use as the content of a DER-encoded integer.
*
* No assumption is made about the alignment of cp.
*
* The numBytes argument indicates the space available on input;
* on return it indicates the actual number of bytes written.
*/
GIReturn serializeGiant(
const giant g,
gi_uint8 *cp,
gi_uint16 *numBytes); /* IN/OUT */
/*
* Initialize a giant with specified data, which may well have come from
* serializeGiant.
*/
GIReturn deserializeGiant(
giant g,
const gi_uint8 *cp,
gi_uint16 numBytes);
#ifdef __cplusplus
}
#endif
#endif /* _GIANT_EXTERNAL_H_ */
File diff suppressed because it is too large. Load diff
+286
View File
@@ -0,0 +1,286 @@
/* Copyright (c) 1998-2007 Apple Inc. All Rights Reserved.
*
* NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
* TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
* SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE
* ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
* INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
* EXPOSE YOU TO LIABILITY.
***************************************************************************
*
* giantIntegers.h - large-integer arithmetic library.
*/
#ifndef _GI_GIANTINTEGERS_H_
#define _GI_GIANTINTEGERS_H_
#include <libGiants/giantTypes.h>
#include <libGiants/giantDebug.h>
#ifdef __cplusplus
extern "C" {
#endif
/* platform-independent digit manipulation macros */
#define GIANT_BYTES_PER_DIGIT (sizeof(giantDigit))
#define GIANT_BITS_PER_DIGIT (8 * GIANT_BYTES_PER_DIGIT)
#define GIANT_DIGIT_MASK ((giantDigit)~0)
#define BYTES_TO_GIANT_DIGITS(x) \
((x + GIANT_BYTES_PER_DIGIT - 1) / GIANT_BYTES_PER_DIGIT)
/*
* Static giant support; giantstruct->n[] no longer dynamically allocated, but
* hard-coded to the max needed for a particular implementation. This max size
* is a function of the prime size (easy to determine) and the max size of
* giant, in digits relative to the size of the prime, actually needed for the
* math implemented in this library (which is going to be tricky to accurately
* determine). We want to minimize the static size of a giant in order to
* minimize RAM usage.
*/
#ifndef GI_MAX_PRIME_SIZE_BITS
#error Please #define GI_MAX_PRIME_SIZE_BITS.
#endif
/* convert that to bytes and digits; these remain fixed */
#define MAX_PRIME_SIZE_BYTES ((GI_MAX_PRIME_SIZE_BITS + 7) / 8)
#define MAX_PRIME_SIZE_DIGITS BYTES_TO_GIANT_DIGITS(MAX_PRIME_SIZE_BYTES)
/*
* The number of digits in a minimal giant, requiring only extra space for
* an add.
*/
#define GIANT_LITTLE_DIGITS (MAX_PRIME_SIZE_DIGITS + 1)
/*
* The number of digits in a max giant, used for mulg and its kin.
*/
#define GIANT_BIG_DIGITS (MAX_PRIME_SIZE_DIGITS * 2)
/*
* The number of digits in a "triple giant", used sparingly in and
* around make_recip and modg_via_recip only.
* The max observed required size seems to be when doing a mulg on
* two numbers, both of whose signs are s+1.
*/
#define GIANT_TRIPLE_DIGITS ((MAX_PRIME_SIZE_DIGITS * 2) + 2)
/* Basic giant type with giantDigit array allocated elsewhere */
typedef struct {
gi_uint16 sign; /* number of giantDigits */
gi_uint16 capacity; /* largest possible number of giantDigits */
giantDigit *n; /* n[0] is l.s. digit */
} giantStruct;
typedef giantStruct *giant;
/*
* Giant capable of being allocated on the stack, with capacity
* no greater than GIANT_LITTLE_DIGITS, i.e., a "little giant" or
* lGiant in the SFEE paper.
*
* Use base giantstruct g in any function call requiring a giant.
*/
typedef struct {
giantStruct g;
giantDigit _n_[GIANT_LITTLE_DIGITS];
} lgiant;
/*
* "Big giant" "subclass" of standard giant. Use base giantstruct g in
* any function call requiring a giant.
*/
typedef struct {
giantStruct g;
giantDigit _n_[GIANT_BIG_DIGITS];
} bigGiantStruct;
typedef bigGiantStruct bgiant; /* for heap allocation */
/*
* "Triple giant" "subclass" of standard giant. Used sparingly in and
* around make_recip only.
*/
typedef struct {
giantStruct g;
giantDigit _n_[GIANT_TRIPLE_DIGITS];
} tripleGiantStruct;
typedef tripleGiantStruct tgiant;
gi_uint16 bitlen(giant n); /* Returns the bit-length n;
* e.g. n=7 returns 3. */
giantDigit bitval(giant n, gi_uint16 pos);
gi_uint16 giantNumBytes(giant n);
void gtog(giant src, giant dest); /* Copies one giant to another */
void int_to_giant(gi_uint32 n, giant g); /* Gives a giant an int value */
GIReturn giant_to_int(giant g, gi_uint32 *i); /* Convent giant to int. */
gi_uint16 numtrailzeros(giant g); /* # of trailing zero bits in g */
int gcompg(giant a, giant b); /* Returns 1, 0, -1 as a>b, a=b, a<b */
void normal_addg(giant a, giant b); /* b += a */
#define addg(a, b) normal_addg(a, b)
void iaddg(giantDigit a, giant b); /* b += a */
void imulg(giantDigit a, giant b); /* b *= a */
void normal_subg(giant a, giant b); /* b -= a. */
void gshiftleft(gi_uint16 bits, giant g); /* Shift g left by bits, introducing
* zeros on the right. */
void gshiftright(gi_uint16 bits, giant g); /* Shift g right by bits, losing bits
* on the right. */
// Right-shift z by s giantDigits
void gshifltwordsright(gi_uint16 digits, giant g);
// shift left by s giantDigits
void gshiftwordsleft(gi_uint16 digits, giant g);
void extractbits(gi_uint16 n, giant src, giant dest);
/* dest becomes lowermost n bits of
* src. Equivalent to
* dest = src % 2^n */
void grammarSquare(giant a); /* g *= g. */
void grammarSquare_common(giant a, giant dest);
/* dest := (a * a)
* dest is typically a bgiant */
#define gsquare(g) grammarSquare(g)
void mulg(giant a, giant b); /* b *= a. */
void mulg_common(giant a, giant b, giant dest);
/* dest := a * b;
* dest is typically a bgiant */
void gtrimSign(giant g); /* Adjust sign for possible leading
* (m.s.) zero digits */
void clearGiant(giant g); /* zero a giant's data */
/* converted from trivial functions */
#if GIANTS_DEBUG
/*
* counter, acccumulates calls to (giantDigit x giantDigit) multiply.
*/
extern unsigned numGiantDigitMuls;
#define INCR_DIGIT_MULS numGiantDigitMuls++
/*
* Accumulate calls to mulg_common()
*/
extern unsigned numMulgCommon;
#define INCR_NUM_MULGS numMulgCommon++;
/*
* Accumulate calls to grammarSquare_common()
*/
extern unsigned numGSquareCommon;
#define INCR_NUM_GSQUARE numGSquareCommon++;
#else /* GIANTS_DEBUG */
#define INCR_DIGIT_MULS
#define INCR_NUM_MULGS
#define INCR_NUM_GSQUARE
#endif /* GIANTS_DEBUG */
/*
* Functions which can be explicit C functions, macros, or static inlines
* depending on the configuration.
*/
#if !defined(GI_INLINE_SMALL_FUNCS) && !defined(GI_MACRO_SMALL_FUNCTIONS)
#error Please define GI_INLINE_SMALL_FUNCS and GI_MACRO_SMALL_FUNCTIONS.
#endif
#if GI_INLINE_SMALL_FUNCS && GI_MACRO_SMALL_FUNCTIONS
#error GI_INLINE_SMALL_FUNCS and GI_MACRO_SMALL_FUNCTIONS are mutually exclusive.
#endif
#if GI_INLINE_SMALL_FUNCS
/* common giant init */
static GI_INLINE void initGiant(
giant g,
gi_uint16 capacity,
giantDigit *digits)
{
g->sign = 0;
g->capacity = capacity;
g->n = digits;
}
/* call this after declaring a local lgiant and before using it */
static GI_INLINE void localGiantAlloc(lgiant *g)
{
initGiant(&g->g, GIANT_LITTLE_DIGITS, g->_n_);
}
/* ditto, for a bgiant */
static GI_INLINE void localBigGiantAlloc(bgiant *g)
{
initGiant(&g->g, GIANT_BIG_DIGITS, g->_n_);
}
/* ditto, for a tgiant */
static GI_INLINE void localTriGiantAlloc(tgiant *g)
{
initGiant(&g->g, GIANT_TRIPLE_DIGITS, g->_n_);
}
/* Returns whether g is 1 */
static GI_INLINE int isone(giant g)
{
return ((g->sign == 1) && (g->n[0] == 1));
}
/* Returns whether g is zero */
static GI_INLINE int isZero(giant g)
{
/* we're skipping the !trimmed check here... */
return (g->sign == 0);
}
#elif GI_MACRO_SMALL_FUNCTIONS
#define initGiant(gnt, cap, digs) \
(gnt)->sign = 0; \
(gnt)->capacity = cap; \
(gnt)->n = digs;
#define localGiantAlloc(lg) initGiant(&((lg)->g), GIANT_LITTLE_DIGITS, (lg)->_n_)
#define localBigGiantAlloc(bg) initGiant(&((bg)->g), GIANT_BIG_DIGITS, (bg)->_n_)
#define localTriGiantAlloc(tg) initGiant(&((tg)->g), GIANT_TRIPLE_DIGITS, (tg)->_n_)
#define isone(g) (((g)->sign == 1) && ((g)->n[0] == 1))
#define isZero(g) ((g)->sign == 0)
#else
/*** regular C functions ***/
/* call this after declaring a local lgiant and before using it */
extern void localGiantAlloc(lgiant *g);
/* ditto, for a bgiant */
extern void localBigGiantAlloc(bgiant *g);
/* ditto, for a tgiant */
extern void localTriGiantAlloc(tgiant *g);
void initGiant(
giant g,
gi_uint16 capacity,
giantDigit *digits);
int isone(giant g); /* Returns whether g is 1 */
int isZero(giant g); /* Returns whether g is zero */
#endif /* INLINE / MACRO */
#ifdef __cplusplus
}
#endif
#endif /* _GI_GIANTINTEGERS_H_ */
+48
View File
@@ -0,0 +1,48 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantMemutils.c - trivial implementation of memcpy and bzero, for platforms
* without libc versions of those functions.
*
* Created Aug. 8 2005 by Doug Mitchell.
*/
#include <libGiants/giantPlatform.h>
#ifndef GI_HAVE_MEMCPY
#error Please define GI_HAVE_MEMCPY.
#endif
#ifndef GI_HAVE_BZERO
#error Please define GI_HAVE_BZERO.
#endif
#if !GI_HAVE_MEMCPY
void *Memcpy(void *dst, const void *src, gi_uint16 len)
{
gi_size dex;
unsigned char *dstp = (unsigned char *)dst;
const unsigned char *srcp = (const unsigned char *)src;
for(dex=0; dex<len; dex++) {
*dstp++ = *srcp++;
}
return dst;
}
#endif
#if !GI_HAVE_BZERO
void Bzero(void *b, gi_uint16 len)
{
gi_size dex;
unsigned char *dstp = (unsigned char *)b;
for(dex=0; dex<len; dex++) {
*dstp++ = 0;
}
}
#endif
+722
View File
@@ -0,0 +1,722 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantMod.c - modular arithmetic function declarations.
*
* Created Nov. 29 2005 by Doug Mitchell.
*/
#include <libGiants/giantMod.h>
#include <libGiants/giantDebug.h>
#ifndef GI_SMALL_CRT_ENABLE
#error Please define GI_SMALL_CRT_ENABLE.
#endif
#if GI_SMALL_CRT_ENABLE
/*
* Custom version of the tgiant for GI_SMALL_CRT_ENABLE use.
* Normally a tgiant has 2n+2 digits. The corresponding "small tgiant"
* has n+2 digits.
*/
#define GIANT_SMALL_TRIPLE_DIGITS (MAX_PRIME_SIZE_DIGITS + 2)
typedef struct {
giantStruct g;
giantDigit _n_[GIANT_SMALL_TRIPLE_DIGITS];
} smallTGiantStruct;
typedef smallTGiantStruct stgiant;
static GI_INLINE void localSmallTGiantAlloc(stgiant *g)
{
initGiant(&g->g, GIANT_SMALL_TRIPLE_DIGITS, g->_n_);
}
static void rsquareSmall(
giant x,
giant n,
giant recip);
static void rmulgSmall(
giant x,
giant y,
giant n,
giant recip);
static void modg_via_recipSmall(
giant d,
giant r,
giant n);
static void powermodgSmall(
giant base,
giant expo,
giant n,
giant recip,
giant result);
#endif
/* for lots of grungy low-level debugging */
#define DEBUG_MODG 0
#if DEBUG_MODG
#include <stdio.h>
#include <libGiantsUtils/printGiant.h>
static void dispGiant(
const char *label,
giant g)
{
printf("--- %s : ", label);
printGiant(g);
}
static void dispInt(
const char *label,
unsigned i)
{
printf("--- %s : %u\n", label, i);
}
static void dispHeader(
const char *label)
{
printf("--- %s ---\n", label);
}
static void dispDelim(void)
{
printf("-------------\n");
}
#else /* DEBUG_MODG */
#define dispGiant(l, g)
#define dispInt(l, i)
#define dispDelim()
#define dispHeader(l)
#endif /* DEBUG_MODG */
#if GI_MODG_ENABLE
/* returns 1 if g has exactly one bit set, else returns zero */
static int isPowerOfTwo(
giant g)
{
int foundBit = 0;
gi_uint16 dex;
giantDigit currDigit;
giantDigit mask;
GI_CHECK_SP("isPowerOfTwo");
if(isZero(g)) {
return 0;
}
/* see if m.s. digit has exactly one bit set */
currDigit = g->n[g->sign - 1];
/* mask shifts out to zero when done */
for(mask=0x01; mask != 0; mask <<= 1) {
if(currDigit & mask) {
if(foundBit) {
/* found second bit set: done */
return 0;
}
else {
/* first '1' bit seen */
foundBit = 1;
}
}
}
GIASSERT(foundBit != 0);
/* now we return true iff all the rest of the digits are zero */
for(dex=0; dex<g->sign-1; dex++) {
if(g->n[dex] != 0) {
return 0;
}
}
return 1;
}
/*
* Calculate the reciprocal of a demonimator.
*/
void make_recip(
giant d,
giant recip)
/* r becomes the steady-state reciprocal
2^(2b)/d, where b = bit-length of d-1. */
{
int b;
tgiant tmp1;
bgiant tmp2;
tgiant tmp3;
GI_CHECK_SP("make_recip (1)");
if (isZero(d)) {
GIASSERT(0);
return;
}
if(isPowerOfTwo(d)) {
gtog(d, recip);
return;
}
localTriGiantAlloc(&tmp1);
localBigGiantAlloc(&tmp2);
localTriGiantAlloc(&tmp3);
//localGiantAlloc(&tmpRecip);
GI_CHECK_SP("make_recip (2)");
b = bitlen(d);
int_to_giant(1, recip);
if((b & (GIANT_BITS_PER_DIGIT - 1)) == 0) {
/* digit-aligned */
gshiftwordsleft(b >> GI_GIANT_LOG2_BITS_PER_DIGIT, recip);
}
else {
gshiftleft(b, recip);
}
gtog(recip, &tmp2.g);
while(1) {
grammarSquare_common(recip, &tmp1.g);
gshiftright(b, &tmp1.g);
mulg_common(d, &tmp1.g, &tmp3.g);
gshiftright(b, &tmp3.g);
addg(recip, recip);
normal_subg(&tmp3.g, recip);
if(gcompg(recip, &tmp2.g) <= 0) {
break;
}
gtog(recip, &tmp2.g);
}
mulg_common(recip, d, &tmp1.g);
int_to_giant(1, &tmp2.g);
while(bitlen(&tmp1.g) > (2 * b)) {
normal_subg(&tmp2.g, recip);
normal_subg(d, &tmp1.g);
}
CHECK_GIANT_OFLOW(recip);
}
#define MODG_CTR_LIMIT 3
/*
* Optimized modg.
* n := n % d, where r is the precalculated steady-state reciprocal of d.
*/
void modg_via_recip(
giant d,
giant r,
giant n)
{
int s = bitlen(r)-1;
bgiant tmp1;
tgiant tmp2;
//dispGiant("d", d);
//dispGiant("r", r);
//dispGiant("n", n);
GI_CHECK_SP("modg_via_recip(1)");
GIASSERT(!isZero(r));
if(s == 0) {
int_to_giant(0, n);
return;
}
if(gcompg(n, d) < 0) {
/* this mod is a nop: done. */
return;
}
localBigGiantAlloc(&tmp1);
localTriGiantAlloc(&tmp2);
do {
unsigned ct = 0;
gtog(n, &tmp1.g);
gshiftright(s-1, &tmp1.g);
mulg_common(r, &tmp1.g, &tmp2.g);
gshiftright(s+1, &tmp2.g);
mulg_common(d, &tmp2.g, &tmp1.g);
normal_subg(&tmp1.g, n);
while(++ct <= MODG_CTR_LIMIT) {
if(gcompg(n,d) >= 0) {
normal_subg(d,n);
}
else {
return;
}
}
} while(1);
}
/* Both n and div are written by this function, with new values:
n := n mod d,
div := floor(n/d).
*/
void divmodg_via_recip(
giant d,
giant r,
giant n,
giant dv)
{
int s = bitlen(r)-1;
tgiant tmp1;
tgiant tmp2;
GI_CHECK_SP("divmodg_via_recip(1)");
GIASSERT(!isZero(r));
if(s == 0) {
int_to_giant(0, n);
gtog(n, dv);
return;
}
int_to_giant(0, dv);
if(gcompg(n, d) < 0) {
/* this mod is a nop: done. */
return;
}
localTriGiantAlloc(&tmp1);
localTriGiantAlloc(&tmp2);
GI_CHECK_SP("divmodg_via_recip(2)");
do {
unsigned ct = 0;
gtog(n, &tmp1.g);
gshiftright(s-1, &tmp1.g);
mulg_common(r, &tmp1.g, &tmp2.g);
gshiftright(s+1, &tmp2.g);
mulg_common(d, &tmp2.g, &tmp1.g);
normal_subg(&tmp1.g, n);
addg(&tmp2.g, dv);
while(++ct <= 3) {
if(gcompg(n,d) >= 0) {
normal_subg(d,n);
iaddg(1, dv);
}
else {
return;
}
}
} while(1);
}
/* x := (x^2) mod n with known reciprocal of n */
void rsquare(
giant x,
giant n,
giant recip)
{
bgiant sq;
GI_CHECK_SP("rsquare(1)");
localBigGiantAlloc(&sq);
GI_CHECK_SP("rsquare(2)");
grammarSquare_common(x, &sq.g);
modg_via_recip(n, recip, &sq.g);
gtog(&sq.g, x);
}
/* y := (x * y) mod n with known reciprocal of n */
void rmulg(
giant x,
giant y,
giant n,
giant recip)
{
bgiant prod;
GI_CHECK_SP("rmulg");
localBigGiantAlloc(&prod);
mulg_common(x, y, &prod.g);
modg_via_recip(n, recip, &prod.g);
gtog(&prod.g, y);
}
/*
* result becomes base^expo (mod n).
* Caller knows and gives us reciprocal of n as recip.
* base and result can share the same giant.
*/
void powermodg(
giant base,
giant expo,
giant n,
giant recip,
giant result)
{
int len, pos;
lgiant bmod; /* saved base mod n */
GI_CHECK_SP("powermodg");
GI_LOG_SP("top of powermodg");
if(isZero(expo)) {
int_to_giant(1, result);
return;
}
localGiantAlloc(&bmod);
if(base != result) {
gtog(base, result);
}
if(gcompg(result, n) >= 0) {
modg_via_recip(n, recip, result);
}
gtog(result, &bmod.g);
len = bitlen(expo);
if(len == 1) {
return;
}
for(pos = len-2; pos >= 0; pos--) {
rsquare(result, n, recip); // New ring-square.
if (bitval(expo, pos)) {
rmulg(&bmod.g, result, n, recip);
}
}
return;
}
void modg(
giant d,
giant n)
/* n becomes n%d. n is arbitrary, but the denominator d must be positive! */
{
lgiant recip;
GI_CHECK_SP("modg");
localGiantAlloc(&recip);
make_recip(d, &recip.g);
modg_via_recip(d, &recip.g, n);
}
/*
* power/mod using Chinese Remainder Theorem.
*
* result becomes base^d (mod n).
*
* ...but we don't know or need d or n. What we have are
*
* p, q such that n = p*q
* reciprocals of p, q
* dp = d mod (p-1)
* dq = d mod (q-1)
* qinv = q^(1) mod p
*/
void powermodCRT(
giant x, /* base (plaintext/ciphertext) */
giant p, /* p*q = n */
giant pRecip, /* reciprocal of p */
giant q,
giant qRecip, /* reciprocal of p */
giant dp, /* d mod (p-1) */
giant dq, /* d mod (q-1) */
giant qinv,
giant sq, /* scratch, provided and init'd by caller */
giant result) /* OUTPUT */
{
bgiant sp;
int m;
GI_CHECK_SP("powermodCRT");
localBigGiantAlloc(&sp);
GIASSERT(sq->capacity >= GIANT_LITTLE_DIGITS);
/*
* sp := x^dp mod p;
* sq := x^dq mod q;
*/
#if GI_SMALL_CRT_ENABLE
powermodgSmall(x, dp, p, pRecip, &sp.g);
powermodgSmall(x, dq, q, qRecip, sq);
#else
powermodg(x, dp, p, pRecip, &sp.g);
powermodg(x, dq, q, qRecip, sq);
#endif
/*
* m = gcompg(sp, sq);
* if(m > = 0)
* result = sp-sq;
* else
* result = sq-sp; // Note unsigned subtract always;
*/
m = gcompg(&sp.g, sq);
if(m >= 0) {
gtog(&sp.g, result);
normal_subg(sq, result);
}
else {
gtog(sq, result);
normal_subg(&sp.g, result);
}
/*
* result = (qinv * result) mod p;
* done with sp, use as scratch now...
*/
mulg_common(result, qinv, &sp.g);
modg_via_recip(p, pRecip, &sp.g);
gtog(&sp.g, result);
/*
* if( ! isZero(result)) if(m < 0) result = p - result;
*/
if(!isZero(result)) {
if(m < 0) {
gtog(p, &sp.g);
normal_subg(result, &sp.g);
gtog(&sp.g, result);
}
}
/*
* result *= q;
* result += sq;
*/
mulg_common(result, q, &sp.g);
addg(sq, &sp.g);
gtog(&sp.g, result);
}
#endif /* GI_MODG_ENABLE */
#if GI_INVERSE_MOD_ENABLE
/*
* Given x, y coprime with x > 0, y > 1, this routine forces
* x := x^(-1) mod modulus.
*/
void ginverseMod(
giant modulus,
giant recip, /* reciprocal of modulus */
giant x) /* IN/OUT */
{
lgiant u, v, a, q, tmp;
unsigned int k = 0;
lgiant uRecip;
GI_CHECK_SP("ginverseMod");
localGiantAlloc(&u);
localGiantAlloc(&v);
localGiantAlloc(&a);
localGiantAlloc(&q);
localGiantAlloc(&tmp);
localGiantAlloc(&uRecip);
dispHeader("ginverseMod top");
dispGiant("x", x);
dispGiant("modulus", modulus);
dispGiant("recip", recip);
/*
* 1) (u, v, a, x, k) = (x mod modulus, modulus, 0, 1, 0);
*/
gtog(x, &u.g);
modg_via_recip(modulus, recip, &u.g);
gtog(modulus, &v.g);
/* a is already zero */
int_to_giant(1, x);
dispHeader("ginverseMod before loop");
dispGiant("x", x);
dispGiant("u", &u.g);
dispGiant("v", &v.g);
dispGiant("a", &a.g);
dispInt("k", k);
/*
* 2) while(u > 1) {
* q = v div u;
* (u, v, a, x, k) = (v mod u, u, x, (a + q*x) mod y, k + 1);
* }
*/
while(!isZero(&u.g) && !isone(&u.g)) {
/* (q,u) := (v div u, v mod u */
make_recip(&u.g, &uRecip.g);
gtog(&u.g, &tmp.g); /* for a const modulus in divmodg_via_recip() */
gtog(&v.g, &u.g); /* divisor, then result of mod */
divmodg_via_recip(&tmp.g, &uRecip.g, &u.g, &q.g);
/* v := old u */
gtog(&tmp.g, &v.g);
/* intermediate: *old* x */
gtog(x, &tmp.g);
/* calc new x := a + q*x mod y */
rmulg(&q.g, x, modulus, recip);
addg(&a.g, x);
modg_via_recip(modulus, recip, x); /* just in case */
/* new a := old x */
gtog(&tmp.g, &a.g);
k++;
dispDelim();
dispGiant("x", x);
dispGiant("q", &q.g);
dispGiant("u", &u.g);
dispGiant("v", &v.g);
dispGiant("a", &a.g);
dispInt("k", k);
}
/*
* 3) if(k odd) x = y - x; // Unsigned (normal_subg) subtract.
*/
if(k & 1) {
gtog(modulus, &u.g);
normal_subg(x, &u.g);
gtog(&u.g, x);
}
}
#endif /* GI_INVERSE_MOD_ENABLE */
#if GI_SMALL_CRT_ENABLE
/*
* Optional "small giant" routines used only by powermodCRT when
* performing its initial powermodg operations with p and q as the
* modulus; p and q are half the size of MAX_PRIME_SIZE_DIGITS, so
* we implement the following functions with corresponding small
* local giants.
* On PPC, this saves 384 bytes of stack space, at the cost of
* 1407 extra bytes of code.
*/
static void rsquareSmall(
giant x,
giant n,
giant recip)
{
stgiant sq;
GI_CHECK_SP("rsquareSmall(1)");
localSmallTGiantAlloc(&sq);
GI_CHECK_SP("rsquareSmall(2)");
grammarSquare_common(x, &sq.g);
modg_via_recipSmall(n, recip, &sq.g);
gtog(&sq.g, x);
}
/* y := (x * y) mod n with known reciprocal of n */
static void rmulgSmall(
giant x,
giant y,
giant n,
giant recip)
{
stgiant prod;
GI_CHECK_SP("rmulgSmall");
localSmallTGiantAlloc(&prod);
mulg_common(x, y, &prod.g);
modg_via_recipSmall(n, recip, &prod.g);
gtog(&prod.g, y);
}
/*
* Optimized modg.
* n := n % d, where r is the precalculated steady-state reciprocal of d.
*/
static void modg_via_recipSmall(
giant d,
giant r,
giant n)
{
int s = bitlen(r)-1;
stgiant tmp1;
stgiant tmp2;
GI_CHECK_SP("modg_via_recipSmall(1)");
GIASSERT(!isZero(r));
if(s == 0) {
int_to_giant(0, n);
return;
}
if(gcompg(n, d) < 0) {
/* this mod is a nop: done. */
return;
}
localSmallTGiantAlloc(&tmp1);
localSmallTGiantAlloc(&tmp2);
do {
unsigned ct = 0;
gtog(n, &tmp1.g);
gshiftright(s-1, &tmp1.g);
mulg_common(r, &tmp1.g, &tmp2.g);
gshiftright(s+1, &tmp2.g);
mulg_common(d, &tmp2.g, &tmp1.g);
normal_subg(&tmp1.g, n);
while(++ct <= MODG_CTR_LIMIT) {
if(gcompg(n,d) >= 0) {
normal_subg(d,n);
}
else {
return;
}
}
} while(1);
}
/*
* result becomes base^expo (mod n).
* Caller knows and gives us reciprocal of n as recip.
* base and result can share the same giant.
*
* This is only used by powermodCRT, which conveniently hands us
* two initialized scratch giants, one bgiant and one stgiant
* so neither we nor any of our callers have to allocate any
* local giants.
*/
static void powermodgSmall(
giant base,
giant expo,
giant n,
giant recip,
giant result)
{
int len, pos;
lgiant bmod; /* saved base mod n */
GI_CHECK_SP("powermodgSmall");
GI_LOG_SP("top of powermodgSmall");
if(isZero(expo)) {
int_to_giant(1, result);
return;
}
localGiantAlloc(&bmod);
if(base != result) {
gtog(base, result);
}
if(gcompg(result, n) >= 0) {
modg_via_recipSmall(n, recip, result);
}
gtog(result, &bmod.g);
len = bitlen(expo);
if(len == 1) {
return;
}
for(pos = len-2; pos >= 0; pos--) {
rsquareSmall(result, n, recip); // New ring-square.
if (bitval(expo, pos)) {
rmulgSmall(&bmod.g, result, n, recip);
}
}
return;
}
#endif /* GI_SMALL_CRT_ENABLE */
+124
View File
@@ -0,0 +1,124 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantMod.h - modular arithmetic function declarations.
*
* Created Nov. 29 2005 by Doug Mitchell.
*/
#ifndef _GIANT_MOD_H_
#define _GIANT_MOD_H_
#include <libGiants/giantIntegers.h>
/* this must be defined in giantPlatform.h */
#ifndef GI_MODG_ENABLE
#error Please define GI_MODG_ENABLE one way or the other.
#endif
#if GI_MODG_ENABLE
#ifdef __cplusplus
extern "C" {
#endif
/*
* Calculate the reciprocal of a demonimator to be used in
* modg_via_recip().
*/
void make_recip(giant d, giant recip);
/*
* n := n % d, where r is the precalculated
* steady-state reciprocal of d.
*/
void modg_via_recip(
giant d,
giant r,
giant n);
/* Both n and div are written by this function, with new values:
n := n mod d,
div := floor(n/d).
*/
void divmodg_via_recip(
giant d,
giant r,
giant n,
giant dv);
/* x := (x^2) mod n with known reciprocal of n */
void rsquare(
giant x,
giant n,
giant recip);
/* y := (x * y) mod n with known reciprocal of n */
void rmulg(
giant x,
giant y,
giant n,
giant recip);
/*
* result becomes base^expo (mod n).
* Caller knows and gives us reciprocal of n as recip.
* base and result can share the same giant.
*/
void powermodg(
giant base,
giant expo,
giant n,
giant recip,
giant result);
/* n becomes n%d. n is arbitrary, but the denominator d must be positive! */
void modg(giant d,giant n);
/*
* power/mod using Chinese Remainder Theorem.
*
* result becomes base^d (mod n).
*
* ...but we don't know or need d or n. What we have are
*
* p, q such that n = p*q
* reciprocals of p, q
* dp = d mod (p-1)
* dq = d mod (q-1)
* qinv = q^(1) mod p
*
* Plus one scratch giant, initialized by caller with the capacity at
* least as big as an lgiant.
*
* The base and result arguments can be identical, i.e., an in/out
* parameter.
*/
void powermodCRT(
giant base, /* base (plaintext/ciphertext) */
giant p, /* p*q = n */
giant pRecip, /* reciprocal of p */
giant q,
giant qRecip, /* reciprocal of q */
giant dp, /* d mod (p-1) */
giant dq, /* d mod (q-1) */
giant qinv,
giant scratchLgiant,
giant result); /* OUTPUT */
/*
* Given x, y coprime with x > 0, y > 1, this routine forces
* x := x^(-1) mod y.
*/
void ginverseMod(
giant modulus,
giant recip, /* reciprocal of modulus */
giant x); /* IN/OUT */
#ifdef __cplusplus
}
#endif
#endif /* GI_MODG_ENABLE */
#endif /* _GIANT_MOD_H_ */
+370
View File
@@ -0,0 +1,370 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantPlatform.h - platform specific type and routines, must be ported to
* each platform on which this library runs.
*/
#ifndef _GIANT_PLATFORM_H_
#define _GIANT_PLATFORM_H_
/*
* This is defined true only for development and testing.
* For production code, leave it zero and define your platform
* in this file.
*/
#define GI_PLATFORM_EMULATE 1
#if GI_PLATFORM_EMULATE
#include <libGiants/giantPlatformEmulation.h>
#else
/* be sure to #define NDEBUG for deployment builds */
#define NDEBUG
#ifdef NDEBUG
#define GIANTS_DEBUG 0
#else
#define GIANTS_DEBUG 1
#endif
/*
* Machine-dependent word-size related integer types.
*
* The following integer types must be defined in this module:
*
* gi_uint8 -- unsigned 8 bit (typically "unsigned char")
* gi_uint16 -- unsigned 16 bit, platform/compiler dependent
* gi_uint32 -- unsigned 32-bit integer, platform/compiler dependent
* gi_size -- unsigned, at *least* 16 bits. Could be larger if that's
* more efficient for the platform. For example on a 32-bit
* processor this should be an unsigned 32 bit integer.
* Generally used inside of functions as counters, indices,
* etc. Function parameters which must be portable to
* small processors are expressed as gi_uint16 or
* gi_uint32.
* giantDigit -- see below
* giantDouble -- two giant digits, the result of a giantDigit multiply
*
* giantDigit is the largest native word size for which
* a (giantDigit x giantDigit) hardware multiply (into a giantDouble,
* somehow) is available. This is a crucial data type; the large integer
* artithmetic package uses data types called 'giants' which are mainly
* comprised of arrays of giantDigits. Most of the CPU cycles spent in this
* library are involved in performing arithmetic on these arrays of
* giantDigits.
*
* Our assumption is that the following all always fit into a gi_uint16:
*
* number of bits per giant digit
* number of giant digits in the max base prime in this module
* number of bits in the max base prime in this module
*
* Note we also assume the existence of a 16-bit integer type; arithmetic
* involving this type doesn't have to be particularly fast but it has to be
* usable as a function argument and in simple assignments. Thus 8-bit
* platforms can run this code as long as there is a C type which compiles
* to 16 bits.
*
* These preprocessor symbols also need to be defined for each platform:
*
* GI_GIANT_LOG2_BITS_PER_DIGIT
* The log to base 2 of the size of giantDigit. There
* is no straightforward way for the C preprocessor to figure this one
* out so you have to specify it. For 16-bit giantDigits the value of
* this symbol is 4; for 32-bit giantDigits the value is 5.
*
* GI_GIANT_PORT_INLINE
* 1 : we don't have a platform-specific giant arithmetic module; use the
* inlines in giantPort_Generic.h
* 0 : we have a platform-specific giant arithmetic module
*
* GI_INLINE_SMALL_FUNCS
* 1 : Use 'static inline' for a select set of small (1-3 line) functions.
* Trade more code for faster runtime and less stack usage. The specific
* effect of this flag wil be nighly dependent on your compiler; in some
* cases you might even see smaller code size when this flag is true.
* 0 : Disable this feature, use actual C functions.
*
* GI_MACRO_SMALL_FUNCTIONS
*
* Like GI_INLINE_SMALL_FUNCS, except causes small functions to be implemented
* as macros. For platforms that don't support the 'inline' keyword. Mutually
* exclusive with GI_INLINE_SMALL_FUNCS.
* 1 : Use #defined macros for the functions in question.
* 0 : Disable; use actual C functions.
*
*
* GI_SMALL_CRT_ENABLE
*
* This flag involves a tradeoff between code size and stack usage in the
* giantMod.c module. Setting this flag true increases code size and
* decreases stack usage.
*
* On a G4, the tradeoff is that setting this flag saves 384 bytes of
* stack space, at the cost of 1407 extra bytes of code.
*
* Note: this flag has no effect if GI_MODG_ENABLE is 0.
*
* 0 : disable the small-CRT functions to save code space.
* 1 : enable to the small-CRT functions to save stack space.
*
* GI_HAVE_MEMCPY
* 1 : This platform has memcpy() and we want to use it as the implementation
* of Memcpy()
* 0 : We've provided our own Memcpy()
*
* GI_HAVE_BZERO
* 1 : This platform has bzero() and we want to use it as the implementation
* of Bzero()
* 0 : We've provided our own Bzero()
*
* GI_INLINE
* Used where the 'inline' keyword would normally be used. #define to 'inline'
* if your compiler provides this functionality, else #define it to nothing or
* some other compiler-specific value.
*
* GI_MODG_ENABLE
*
* When nonzero, enables the modular arithmetic functions found in
* giantMod.[ch]. Some applications such as SFEE do not need these functions.
* Other applications, like RSA and BBS, do in fact need them.
*
* 1 : Enable compilation of giantMod.[ch]
* 0 : Disable compilation of giantMod.[ch]
*
* GI_PRIME_TEST_ENABLE
*
* When nonzero, enables the logic in giantPrime.c used to determine
* whether a given giant is prime. Used in RSA key generation.
*
* 1 : Enable compilation of giantPrime.[ch]
* 0 : Disable compilation of giantPrime.[ch]
*
* GI_INVERSE_MOD_ENABLE
*
* When nonzero, enables the ginverseMod() function in giantMod.[ch]. Used
* for RSA key generation and for BBS.
*
* 1 : Enable compilation of ginverseMod()
* 0 : Disable compilation of ginverseMod()
*
*
* Optimization flags
* ------------------
*
* The following symbols have to be #defined to 0 or 1. See the comments below
* for detailed descritpions of the effects of these flags.
*
* GI_GSQUARE_ENABLE
* GI_OPTIMIZED_MULG
* GI_ADDG_INLINE
*/
/* These define a 16-bit word size emulated on Mac OS X */
#include <stdint.h>
typedef unsigned char gi_uint8;
typedef uint16_t gi_uint16;
typedef uint32_t gi_uint32;
typedef uint16_t gi_size;
typedef uint16_t giantDigit;
typedef uint32_t giantDouble; /* two giant digits */
#define GI_GIANT_LOG2_BITS_PER_DIGIT 4
/*
* Maximum size in bits of base integer in this package. For BBS, this is the
* size of the public 'n' parameter. For asymmetric encryption, it's the
* size of the base prime.
*
* Altering this has no effect on performance, only on memory usage.
* Specifically it affects the amount of stack space used (since all
* giantIntegers in this package are allocated on the stack).
*/
#define GI_MAX_PRIME_SIZE_BITS 4096
/****
**** Optimization flags
****/
/*
* Sample measurements of the effects of these flags were
* taken on an 800 MHz G4, with a 16 bit giantDigit, running
* the bbsProtocol test with 1024 bit 'n' and 10000 iterations.
* Your mileage will certainly vary; the only way to know for
* sure which is the best value for a particular optimizatiaon
* flag is to measure a real-world case on your platform and then
* make the size-vs.-speed tradeoff decision yourself.
*
* However, in the meantime, all of the functionality in this
* library does work correctly for any value of all of these
* flags.
*/
/*
* GI_GSQUARE_ENABLE
*
* Set nonzero to disable optimized grammarSquare().
* Setting nonzero increases code size and increases performance.
*
* Setting this true has the following effects (on 800 MHz G4):
*
* -- adds 384 bytes of code
* -- 7% speedup on private side
* -- 7% speedup on public side
*/
#define GI_GSQUARE_ENABLE 1
/*
* GI_OPTIMIZED_MULG
*
* Use old unoptimized, but smaller, mulg if this is zero.
* Setting nonzero increases code size and increases performance.
*
* Setting this true has the following effects (on 800 MHz G4):
*
* -- adds 168 bytes of code
* -- 20% speedup on private side
* -- 18% speedup on public side
*/
#define GI_OPTIMIZED_MULG 1
/*
* GI_ADDG_INLINE
*
* There are two implementations of some core arithmetic routines.
* Which one is faster depends highly on your implementation of the
* routines declared in giantPortCommon.h and implemented in either
* giantPort_Generic.h (as static inlines) or elsewhere (in C or
* possibly assembly language). Performance also depends on your
* platform's giantDouble performance. If giantDouble arithmetic
* is fast then use GI_ADDG_INLINE. Otherwise try !GI_ADDG_INLINE,
* measure the two, and pick the best one.
*
* Setting this false has the following effects (on 800 MHz G4):
*
* -- increases code size 192 bytes
* -- elliptic operations (SFEE) slow down by 50-100%
*/
#define GI_ADDG_INLINE 1
/*
* GI_GIANT_PORT_INLINE
*
* true : we don't have a platform-specific giant arithmetic module
* false : we do
*
* If GI_ADDG_INLINE is true, setting this true saves a small amount
* of code with no measurable performance impact.
*
* If GI_ADDG_INLINE is false, setting GI_GIANT_PORT_INLINE to
* true has the following effects:
*
* -- adds 168 bytes of code
* -- 2% speedup on private side
* -- 1% speedup on public side
*/
#define GI_GIANT_PORT_INLINE 0
/*
* GI_INLINE_SMALL_FUNCS
*
* When true, uses macros instead of a small number of small functions.
* This is a tradeff of speed and less stack usage vs. code size.
*/
#define GI_INLINE_SMALL_FUNCS 1
/*
* GI_MACRO_SMALL_FUNCTIONS
*
* Like GI_INLINE_SMALL_FUNCS, except causes small functions to be implemented
* as macros. For platforms that don't support the 'inline' keyword.
*/
#define GI_MACRO_SMALL_FUNCTIONS 0
/*
* GI_SMALL_CRT_ENABLE
*
* This flag involves a tradeoff between code size and stack usage in the
* giantMod.c module. Setting this flag true increases code size and
* decreases stack usage.
*
* On a G4, the tradeoff is that setting this flag saves 384 bytes of
* stack space, at the cost of 1407 extra bytes of code.
*
* Note: this flag has no effect if GI_MODG_ENABLE is 0.
*/
#define GI_SMALL_CRT_ENABLE 1
/****
**** Library implementation flags
****/
/* standard library functions available here */
#define GI_HAVE_MEMCPY 1
#define GI_HAVE_BZERO 1
/* enable/disable modular arithmetic */
#define GI_MODG_ENABLE 1
/* enable/disable giantPrime.[ch] - requires GI_MODG_ENABLE! */
#define GI_PRIME_TEST_ENABLE 1
/* enable/disable ginverseMod() */
#define GI_INVERSE_MOD_ENABLE 1
#endif /* GI_PLATFORM_EMULATE */
#pragma mark --- Declarations of functions with platform-specific implementations ---
/*
* You should not have to modify the rest of this file.
*/
#if GI_HAVE_MEMCPY || GI_HAVE_BZERO
#include <string.h>
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* This platform supports inline keywords.
*/
#define GI_INLINE inline
#if GI_HAVE_MEMCPY
#define Memcpy(d, s, l) memcpy(d, s, l)
#else /* !GI_HAVE_MEMCPY */
/*
* memcpy() equivalent
*/
extern void *Memcpy(void *dst, const void *src, gi_uint16 len);
#endif /* GI_HAVE_MEMCPY */
#if GI_HAVE_BZERO
#define Bzero(b, l) bzero(b, l)
#else /* !GI_HAVE_BZERO */
/*
* bzero() equivalent
*/
extern void Bzero(void *b, gi_uint16 len);
#endif /* GI_HAVE_BZERO */
#ifdef __cplusplus
}
#endif
#endif /*_GIANT_PLATFORM_H_*/
+181
View File
@@ -0,0 +1,181 @@
/* Copyright (c) 2004,2006-2007 Apple Inc. All Rights Reserved.
*
* NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
* TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
* SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE
* ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
* INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
* EXPOSE YOU TO LIABILITY.
***************************************************************************
*
* giantPlatformEmulation.h - #defines for platform emulation.
*
* This file is NOT used in production code.
*/
#ifndef _GIANT_PLATFORM_EMULATION_H_
#define _GIANT_PLATFORM_EMULATION_H_
#define NDEBUG
#ifdef NDEBUG
#define GIANTS_DEBUG 0
#else
#define GIANTS_DEBUG 1
#endif
/*
* Emulation targets:
*
* #define _FEE_CUSTOM_XXX_CONFIG_ to 1 and fill in these blanks if
* you want to generate a test configuration which is not strictly related
* to the machine you're building for - e.g., build a 16-bit giant package on PPC.
*/
/* this one for emulating 16-bit CPU on Mac OS X / PPC */
#define _FEE_CUSTOM_16_CONFIG_ 1
/* this one for emulating 8-bit CPU on Mac OS X / PPC */
#define _FEE_CUSTOM_8_CONFIG_ 0
#if _FEE_CUSTOM_16_CONFIG_
/* 16-bit word size emulated on Mac OS X */
#include <stdint.h>
typedef unsigned char gi_uint8;
typedef uint16_t gi_uint16;
typedef uint32_t gi_uint32;
typedef uint16_t gi_size;
typedef uint16_t giantDigit;
typedef uint32_t giantDouble; /* two giant digits */
#define GI_GIANT_LOG2_BITS_PER_DIGIT 4
#elif _FEE_CUSTOM_8_CONFIG_
/* 8-bit word size emulated on Mac OS X */
#include <stdint.h>
typedef unsigned char gi_uint8;
typedef uint16_t gi_uint16;
typedef uint32_t gi_uint32;
typedef uint16_t gi_size;
typedef uint8_t giantDigit;
typedef uint16_t giantDouble; /* two giant digits */
#define GI_GIANT_LOG2_BITS_PER_DIGIT 3
#elif defined(__APPLE__) && defined(__ppc__)
/*
* Mac OS X on 32-bit PPC
*/
#include <stdint.h>
typedef unsigned char gi_uint8;
typedef uint16_t gi_uint16;
typedef uint32_t gi_uint32;
typedef uint32_t gi_size;
typedef uint32_t giantDigit;
typedef uint64_t giantDouble; /* two giant digits */
#define GI_GIANT_LOG2_BITS_PER_DIGIT 5
#elif defined(__APPLE__) && defined(__i386__)
/*
* Mac OS X on 32-bit Pentium
*/
#include <stdint.h>
typedef unsigned char gi_uint8;
typedef uint16_t gi_uint16;
typedef uint32_t gi_uint32;
typedef uint32_t gi_size;
typedef uint32_t giantDigit;
typedef uint64_t giantDouble; /* two giant digits */
#define GI_GIANT_LOG2_BITS_PER_DIGIT 5
#else
/*
* Other target goes here.
*/
#error Platform dependent work needed
#endif
/*
* Maximum size in bits of base integer in this package. For BBS, this is the
* size of the public 'n' parameter.
*/
#define GI_MAX_PRIME_SIZE_BITS 4096
/****
**** Optimization flags
****/
/*
* There are two implementations of some core arithmetic routines.
* Which one is faster depends highly on your implementation of the
* routines declared in giantPortCommon.h and implemented in either
* giantPort_Generic.h (as static inlines) or elsewhere (in C or
* possibly assembly language). Performance also depends on your
* platform's giantDouble performance. If giantDouble arithmetic
* is fast then use GI_ADDG_INLINE. Otherwise try !GI_ADDG_INLINE,
* measure the two, and pick the best one.
*/
#define GI_ADDG_INLINE 1
/*
* true : we don't have a platform-specific giant arithmetic module
* false : we do
*/
#define GI_GIANT_PORT_INLINE 1
/*
* GI_INLINE_SMALL_FUNCS
*
* When true, uses inlines instead of a small number of small functions.
* This is a tradeff of speed and less stack usage vs. code size.
*/
#define GI_INLINE_SMALL_FUNCS 1
/*
* GI_MACRO_SMALL_FUNCTIONS
*
* Like GI_INLINE_SMALL_FUNCS, except causes small functions to be implemented
* as macros. For platforms that don't support the 'inline' keyword.
*/
#define GI_MACRO_SMALL_FUNCTIONS 0
/*
* GI_SMALL_CRT_ENABLE
*
* This flag involves a tradeoff between code size and stack usage in the
* giantMod.c module. Setting this flag true increases code size and
* decreases stack usage.
*
* On a G4, the tradeoff is that setting this flag saves 384 bytes of
* stack space, at the cost of 1407 extra bytes of code.
*
* Note: this flag has no effect if GI_MODG_ENABLE is 0.
*/
#define GI_SMALL_CRT_ENABLE 1
/****
**** Library implementation flags
****/
/* standard library functions available here */
#define GI_HAVE_MEMCPY 1
#define GI_HAVE_BZERO 1
/* enable/disable modular arithmetic */
#define GI_MODG_ENABLE 1
/* enable/disable giantPrime.[ch] */
#define GI_PRIME_TEST_ENABLE 1
/* enable/disable ginverseMod() */
#define GI_INVERSE_MOD_ENABLE 1
#endif /* _GIANT_PLATFORM_EMULATION_H_ */
+98
View File
@@ -0,0 +1,98 @@
/* Copyright (c) 1998,2006-2007 Apple Inc. All Rights Reserved.
*
* NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
* TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
* SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE
* ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
* INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
* EXPOSE YOU TO LIABILITY.
***************************************************************************
giantPortCommon.h - common header used to specify and access
platform-dependent giant digit routines.
Revision History
----------------
1 Sep 98 Doug Mitchell at Apple
Created.
*******************************/
#ifndef _GIANT_PORT_COMMON_H_
#define _GIANT_PORT_COMMON_H_
#include <libGiants/giantTypes.h>
/*
* This is a platform-dependent symbol that must be defined elsewhere,
* typically in giantPlatform.h.
*/
#ifndef GI_GIANT_PORT_INLINE
#error Please define GI_GIANT_PORT_INLINE.
#endif
#if GI_GIANT_PORT_INLINE
/*
* Vanilla C version using static inlines, should work on any platform,
* though may not be the fastest possible implementation.
*/
#include <libGiants/giantPort_Generic.h>
#else /* GI_GIANT_PORT_INLINE */
/*
* A platform-dependent implementation of these functions is required.
*/
/*
* Add two digits, return sum. Carry bit returned as an out parameter.
*/
extern giantDigit giantAddDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *carry); /* RETURNED, 0 or 1 */
/*
* Add a single digit value to a double digit accumulator in place.
* Carry out of the MSD of the accumulator is not handled.
*/
extern void giantAddDouble(
giantDigit *accLow, /* IN/OUT */
giantDigit *accHigh, /* IN/OUT */
giantDigit val);
/*
* Subtract a - b, return difference. Borrow bit returned as an out parameter.
*/
extern giantDigit giantSubDigits(
giantDigit a,
giantDigit b,
giantDigit *borrow); /* RETURNED, 0 or 1 */
/*
* Multiply two digits, return two digits.
*/
extern void giantMulDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *lowProduct, /* RETURNED, low digit */
giantDigit *hiProduct); /* RETURNED, high digit */
#if 0
/* this is not currently used or needed */
/*
* Multiply a vector of giantDigits, candVector, by a single giantDigit,
* plierDigit, adding results into prodVector. Returns m.s. digit from
* final multiply; only candLength digits of *prodVector will be written.
*/
extern giantDigit VectorMultiply(
giantDigit plierDigit,
giantDigit *candVector,
gi_size candLength,
giantDigit *prodVector);
#endif
#endif /* GI_GIANT_PORT_INLINE */
#endif /* _GIANT_PORT_COMMON_H_ */
+143
View File
@@ -0,0 +1,143 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantPort_C.h - Generic giant definitions routines, used when
* no platform-specific version is available.
*
* This module works on any size giantDigit up to and including
* the native unsigned int, as long as the platform does indeed
* supply a (2 x giantDigit) unsigned integer, defined (in
* giantPlatform.h) as a giantDouble.
*
* Created Aug. 8 2005 by Doug Mitchell.
*/
#include <libGiants/giantTypes.h>
#include <libGiants/giantIntegers.h>
#include <libGiants/giantPortCommon.h>
#include <libGiants/giantDebug.h>
#ifndef GI_GIANT_PORT_INLINE
#error Please define GI_GIANT_PORT_INLINE.
#endif
#if !GI_GIANT_PORT_INLINE
/*
* Add two digits, return sum. Carry bit returned as an out parameter.
*/
giantDigit giantAddDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *carry) /* RETURNED, 0 or 1 */
{
giantDigit sum = dig1 + dig2;
GI_CHECK_SP("giantAddDigits");
if((sum < dig1) || (sum < dig2)) {
*carry = 1;
}
else {
*carry = 0;
}
return sum;
}
/*
* Add a single digit value to a double digit accumulator in place.
* Carry out of the MSD of the accumulator is not handled.
*/
void giantAddDouble(
giantDigit *accLow, /* IN/OUT */
giantDigit *accHigh, /* IN/OUT */
giantDigit val)
{
giantDigit sumLo = *accLow + val;
GI_CHECK_SP("giantAddDouble");
if((sumLo < *accLow) || (sumLo < val)) {
(*accHigh)++;
/* if it's zero we just overflowed */
GIASSERT(*accHigh != 0);
}
*accLow = sumLo;
}
/*
* Subtract a - b, return difference. Borrow bit returned as an out parameter.
*/
giantDigit giantSubDigits(
giantDigit a,
giantDigit b,
giantDigit *borrow) /* RETURNED, 0 or 1 */
{
giantDigit diff = a - b;
GI_CHECK_SP("giantSubDigits");
if(a < b) {
*borrow = 1;
}
else {
*borrow = 0;
}
return diff;
}
/*
* Multiply two digits, return two digits.
*/
void giantMulDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *lowProduct, /* RETURNED, low digit */
giantDigit *hiProduct) /* RETURNED, high digit */
{
giantDouble dprod;
GI_CHECK_SP("giantMulDigits");
dprod = (giantDouble)dig1 * (giantDouble)dig2;
*hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT);
*lowProduct = (giantDigit)dprod;
}
#if 0
/* this is currently unused. */
/*
* Multiply a vector of giantDigits, candVector, by a single giantDigit,
* plierDigit, adding results into prodVector. Returns m.s. digit from
* final multiply; only candLength digits of *prodVector will be written.
*/
giantDigit VectorMultiply(
giantDigit plierDigit,
giantDigit *candVector,
gi_size candLength,
giantDigit *prodVector)
{
gi_size candDex; // index into multiplicandVector
giantDigit lastCarry = 0;
giantDigit prodLo;
giantDigit prodHi;
for(candDex=0; candDex<candLength; ++candDex) {
/*
* prod = *(candVector++) * plierDigit + *prodVector + lastCarry
*/
giantMulDigits(*(candVector++),
plierDigit,
&prodLo,
&prodHi);
giantAddDouble(&prodLo, &prodHi, *prodVector);
giantAddDouble(&prodLo, &prodHi, lastCarry);
/*
* *(destptr++) = prodHi;
* lastCarry = prodLo;
*/
*(prodVector++) = prodLo;
lastCarry = prodHi;
}
return lastCarry;
}
#endif /* 0 - VectorMultiply disabled */
#endif /* !GI_GIANT_PORT_INLINE */
+160
View File
@@ -0,0 +1,160 @@
/* Copyright (c) 1998,2006-2007 Apple Inc. All Rights Reserved.
*
* NOTICE: USE OF THE MATERIALS ACCOMPANYING THIS NOTICE IS SUBJECT
* TO THE TERMS OF THE SIGNED "FAST ELLIPTIC ENCRYPTION (FEE) REFERENCE
* SOURCE CODE EVALUATION AGREEMENT" BETWEEN APPLE COMPUTER, INC. AND THE
* ORIGINAL LICENSEE THAT OBTAINED THESE MATERIALS FROM APPLE COMPUTER,
* INC. ANY USE OF THESE MATERIALS NOT PERMITTED BY SUCH AGREEMENT WILL
* EXPOSE YOU TO LIABILITY.
***************************************************************************
*
* giantPort_Generic.h - Generic giant definitions routines, implemented
* as static inlines, used when no platform-specific version is available.
*
* This module works on any size giantDigit up to and including
* the native unsigned int, as long as the platform does indeed
* supply a (2 x giantDigit) unsigned integer, defined (in
* giantPlatform.h) as a giantDouble.
*
* The module giantPort_C.c is functionaly identical to this
* except that its routines are actual C functions instead of
* inlines.
*
* Revision History
* ----------------
* 06 Apr 1998 Doug Mitchell at Apple
* Created.
*/
#ifndef _GIANT_PORT_GENERIC_H_
#define _GIANT_PORT_GENERIC_H_
#include <libGiants/giantTypes.h>
#include <libGiants/giantIntegers.h>
#include <libGiants/giantDebug.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Add two digits, return sum. Carry bit returned as an out parameter.
*/
static GI_INLINE giantDigit giantAddDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *carry) /* RETURNED, 0 or 1 */
{
giantDigit sum = dig1 + dig2;
if((sum < dig1) || (sum < dig2)) {
*carry = 1;
}
else {
*carry = 0;
}
return sum;
}
/*
* Add a single digit value to a double digit accumulator in place.
* Carry out of the MSD of the accumulator is not handled.
*/
static GI_INLINE void giantAddDouble(
giantDigit *accLow, /* IN/OUT */
giantDigit *accHigh, /* IN/OUT */
giantDigit val)
{
giantDigit sumLo = *accLow + val;
if((sumLo < *accLow) || (sumLo < val)) {
(*accHigh)++;
/* if it's zero we just overflowed */
GIASSERT(*accHigh != 0);
}
*accLow = sumLo;
}
/*
* Subtract a - b, return difference. Borrow bit returned as an out parameter.
*/
static GI_INLINE giantDigit giantSubDigits(
giantDigit a,
giantDigit b,
giantDigit *borrow) /* RETURNED, 0 or 1 */
{
giantDigit diff = a - b;
if(a < b) {
*borrow = 1;
}
else {
*borrow = 0;
}
return diff;
}
/*
* Multiply two digits, return two digits.
*/
static GI_INLINE void giantMulDigits(
giantDigit dig1,
giantDigit dig2,
giantDigit *lowProduct, /* RETURNED, low digit */
giantDigit *hiProduct) /* RETURNED, high digit */
{
giantDouble dprod;
dprod = (giantDouble)dig1 * (giantDouble)dig2;
*hiProduct = (giantDigit)(dprod >> GIANT_BITS_PER_DIGIT);
*lowProduct = (giantDigit)dprod;
}
#if 0
/* this is not currently used or needed */
/*
* Multiply a vector of giantDigits, candVector, by a single giantDigit,
* plierDigit, adding results into prodVector. Returns m.s. digit from
* final multiply; only candLength digits of *prodVector will be written.
*/
static GI_INLINE giantDigit VectorMultiply(
giantDigit plierDigit,
giantDigit *candVector,
gi_size candLength,
giantDigit *prodVector)
{
gi_size candDex; // index into multiplicandVector
giantDigit lastCarry = 0;
giantDigit prodLo;
giantDigit prodHi;
for(candDex=0; candDex<candLength; ++candDex) {
/*
* prod = *(candVector++) * plierDigit + *prodVector + lastCarry
*/
giantMulDigits(*(candVector++),
plierDigit,
&prodLo,
&prodHi);
giantAddDouble(&prodLo, &prodHi, *prodVector);
giantAddDouble(&prodLo, &prodHi, lastCarry);
/*
* *(destptr++) = prodHi;
* lastCarry = prodLo;
*/
*(prodVector++) = prodLo;
lastCarry = prodHi;
}
return lastCarry;
}
#endif
#ifdef __cplusplus
}
#endif
#endif /*_GIANT_PORT_GENERIC_H_*/
+42
View File
@@ -0,0 +1,42 @@
/* Copyright (c) 2005-2007 Apple Inc. All Rights Reserved. */
/*
* giantTypes.h - Standard typedefs
*
* Created Aug. 5 2005 by Doug Mitchell.
*/
#ifndef _GIANT_TYPES_H_
#define _GIANT_TYPES_H_
#include <libGiants/giantPlatform.h>
#ifdef __cplusplus
extern "C" {
#endif
/*
* Standard return codes.
*/
typedef enum {
GR_Success = 0,
GR_IllegalArg, /* illegal argument */
GR_Unimplemented, /* unimplemented function */
GR_Internal, /* internal library error */
GR_Overflow, /* caller error, buffer/giant overflow */
} GIReturn;
/*
* We administer the namespace for other libraries' return codes here, so
* all can share a common space.
*/
#define SFEE_RETURN_BASE 1000 /* libSFEE */
#define RSA_RETURN_BASE 2000 /* libgRSA */
#define LIBCERT_RETURN_BASE 3000 /* libCert */
#define DH_RETURN_BASE 4000 /* libgDH */
#ifdef __cplusplus
}
#endif
#endif /* _GIANT_TYPES_H_ */