Update NSS to 3.32.1-RTM

This commit is contained in:
wolfbeast 2018-02-06 11:46:26 +01:00 committed by Roy Tam
commit c91ef9012b
512 changed files with 83203 additions and 16839 deletions

View file

@ -110,6 +110,7 @@ endif
# NSS_X86_OR_X64 means the target is either x86 or x64
ifeq (,$(filter-out i386 x386 x86 x86_64,$(CPU_ARCH)))
DEFINES += -DNSS_X86_OR_X64
CFLAGS += -mpclmul -maes
ifneq (,$(USE_64)$(USE_X32))
DEFINES += -DNSS_X64
else
@ -232,8 +233,6 @@ ifeq ($(CPU_ARCH),x86)
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
DEFINES += -DMP_ASSEMBLY_DIV_2DX1D -DMP_USE_UINT_DIGIT
DEFINES += -DMP_IS_LITTLE_ENDIAN
# The floating point ECC code doesn't work on Linux x86 (bug 311432).
#ECL_USE_FP = 1
endif
ifeq ($(CPU_ARCH),arm)
DEFINES += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
@ -430,7 +429,6 @@ ifeq ($(CPU_ARCH),sparc)
ASFILES = mpv_sparcv8.s montmulfv8.s
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
DEFINES += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL
ECL_USE_FP = 1
endif
ifdef USE_ABI64_INT
# this builds for Sparc v9a pure 64-bit architecture
@ -443,7 +441,6 @@ ifeq ($(CPU_ARCH),sparc)
ASFILES = mpv_sparcv9.s montmulfv9.s
DEFINES += -DMP_NO_MP_WORD -DMP_USE_UINT_DIGIT -DMP_ASSEMBLY_MULTIPLY
DEFINES += -DMP_USING_MONT_MULF -DMP_MONT_USE_MP_MUL
ECL_USE_FP = 1
endif
else
@ -491,16 +488,7 @@ else
endif
endif
endif # Solaris for non-sparc family CPUs
endif # target == SunOS
ifndef NSS_DISABLE_ECC
ifdef ECL_USE_FP
#enable floating point ECC code
DEFINES += -DECL_USE_FP
ECL_SRCS += ecp_fp160.c ecp_fp192.c ecp_fp224.c ecp_fp.c
ECL_HDRS += ecp_fp.h
endif
endif
endif # target == SunO
# poly1305-donna-x64-sse2-incremental-source.c requires __int128 support
# in GCC 4.6.0.
@ -601,7 +589,7 @@ $(ECL_OBJS): $(ECL_HDRS)
$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c os2_rand.c
$(OBJDIR)/sysrand$(OBJ_SUFFIX): sysrand.c unix_rand.c win_rand.c
$(OBJDIR)/$(PROG_PREFIX)mpprime$(OBJ_SUFFIX): primes.c

View file

@ -22,8 +22,9 @@
#include "rijndael.h"
struct AESKeyWrapContextStr {
unsigned char iv[AES_KEY_WRAP_IV_BYTES];
AESContext aescx;
unsigned char iv[AES_KEY_WRAP_IV_BYTES];
void *mem; /* Pointer to beginning of allocated memory. */
};
/******************************************/
@ -34,8 +35,14 @@ struct AESKeyWrapContextStr {
AESKeyWrapContext *
AESKeyWrap_AllocateContext(void)
{
AESKeyWrapContext *cx = PORT_New(AESKeyWrapContext);
return cx;
/* aligned_alloc is C11 so we have to do it the old way. */
AESKeyWrapContext *ctx = PORT_ZAlloc(sizeof(AESKeyWrapContext) + 15);
if (ctx == NULL) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
return NULL;
}
ctx->mem = ctx;
return (AESKeyWrapContext *)(((uintptr_t)ctx + 15) & ~(uintptr_t)0x0F);
}
SECStatus
@ -77,7 +84,7 @@ AESKeyWrap_CreateContext(const unsigned char *key, const unsigned char *iv,
return NULL; /* error is already set */
rv = AESKeyWrap_InitContext(cx, key, keylen, iv, 0, encrypt, 0);
if (rv != SECSuccess) {
PORT_Free(cx);
PORT_Free(cx->mem);
cx = NULL; /* error should already be set */
}
return cx;
@ -94,8 +101,9 @@ AESKeyWrap_DestroyContext(AESKeyWrapContext *cx, PRBool freeit)
if (cx) {
AES_DestroyContext(&cx->aescx, PR_FALSE);
/* memset(cx, 0, sizeof *cx); */
if (freeit)
PORT_Free(cx);
if (freeit) {
PORT_Free(cx->mem);
}
}
}

View file

@ -801,8 +801,7 @@ SEED_Decrypt(SEEDContext *cx, unsigned char *output,
** Create a new AES context suitable for AES encryption/decryption.
** "key" raw key data
** "keylen" the number of bytes of key data (16, 24, or 32)
** "blocklen" is the blocksize to use (16, 24, or 32)
** XXX currently only blocksize==16 has been tested!
** "blocklen" is the blocksize to use. NOTE: only 16 is supported!
*/
extern AESContext *
AES_CreateContext(const unsigned char *key, const unsigned char *iv,
@ -1429,8 +1428,6 @@ extern SECStatus RNG_RandomUpdate(const void *data, size_t bytes);
*/
extern SECStatus RNG_GenerateGlobalRandomBytes(void *dest, size_t len);
extern SECStatus RNG_ResetForFuzzing(void);
/* Destroy the global RNG context. After a call to RNG_RNGShutdown()
** a call to RNG_RNGInit() is required in order to use the generator again,
** along with seed data (see the comment above RNG_RNGInit()).

View file

@ -9,6 +9,7 @@
#define _BLAPII_H_
#include "blapit.h"
#include "mpi.h"
/* max block size of supported block ciphers */
#define MAX_BLOCK_SIZE 16
@ -50,6 +51,18 @@ SEC_END_PROTOS
#define HAVE_NO_SANITIZE_ATTR 0
#endif
/* Alignment helpers. */
#if defined(_WINDOWS) && defined(NSS_X86_OR_X64)
#define pre_align __declspec(align(16))
#define post_align
#elif defined(NSS_X86_OR_X64)
#define pre_align
#define post_align __attribute__((aligned(16)))
#else
#define pre_align
#define post_align
#endif
#if defined(HAVE_UNALIGNED_ACCESS) && HAVE_NO_SANITIZE_ATTR
#define NO_SANITIZE_ALIGNMENT __attribute__((no_sanitize("alignment")))
#else
@ -58,4 +71,12 @@ SEC_END_PROTOS
#undef HAVE_NO_SANITIZE_ATTR
SECStatus RSA_Init();
SECStatus generate_prime(mp_int *prime, int primeLen);
/* Freebl state. */
PRBool aesni_support();
PRBool clmul_support();
PRBool avx_support();
#endif /* _BLAPII_H_ */

View file

@ -0,0 +1,119 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef FREEBL_NO_DEPEND
#include "stubs.h"
#endif
#include "blapii.h"
#include "mpi.h"
#include "secerr.h"
#include "prtypes.h"
#include "prinit.h"
#include "prenv.h"
#if defined(_MSC_VER) && !defined(_M_IX86)
#include <intrin.h> /* for _xgetbv() */
#endif
static PRCallOnceType coFreeblInit;
/* State variables. */
static PRBool aesni_support_ = PR_FALSE;
static PRBool clmul_support_ = PR_FALSE;
static PRBool avx_support_ = PR_FALSE;
#ifdef NSS_X86_OR_X64
/*
* Adapted from the example code in "How to detect New Instruction support in
* the 4th generation Intel Core processor family" by Max Locktyukhin.
*
* XGETBV:
* Reads an extended control register (XCR) specified by ECX into EDX:EAX.
*/
static PRBool
check_xcr0_ymm()
{
PRUint32 xcr0;
#if defined(_MSC_VER)
#if defined(_M_IX86)
__asm {
mov ecx, 0
xgetbv
mov xcr0, eax
}
#else
xcr0 = (PRUint32)_xgetbv(0); /* Requires VS2010 SP1 or later. */
#endif /* _M_IX86 */
#else /* _MSC_VER */
/* Old OSX compilers don't support xgetbv. Use byte form. */
__asm__(".byte 0x0F, 0x01, 0xd0"
: "=a"(xcr0)
: "c"(0)
: "%edx");
#endif /* _MSC_VER */
/* Check if xmm and ymm state are enabled in XCR0. */
return (xcr0 & 6) == 6;
}
#define ECX_AESNI (1 << 25)
#define ECX_CLMUL (1 << 1)
#define ECX_XSAVE (1 << 26)
#define ECX_OSXSAVE (1 << 27)
#define ECX_AVX (1 << 28)
#define AVX_BITS (ECX_XSAVE | ECX_OSXSAVE | ECX_AVX)
void
CheckX86CPUSupport()
{
unsigned long eax, ebx, ecx, edx;
char *disable_hw_aes = PR_GetEnvSecure("NSS_DISABLE_HW_AES");
char *disable_pclmul = PR_GetEnvSecure("NSS_DISABLE_PCLMUL");
char *disable_avx = PR_GetEnvSecure("NSS_DISABLE_AVX");
freebl_cpuid(1, &eax, &ebx, &ecx, &edx);
aesni_support_ = (PRBool)((ecx & ECX_AESNI) != 0 && disable_hw_aes == NULL);
clmul_support_ = (PRBool)((ecx & ECX_CLMUL) != 0 && disable_pclmul == NULL);
/* For AVX we check AVX, OSXSAVE, and XSAVE
* as well as XMM and YMM state. */
avx_support_ = (PRBool)((ecx & AVX_BITS) == AVX_BITS) && check_xcr0_ymm() &&
disable_avx == NULL;
}
#endif /* NSS_X86_OR_X64 */
PRBool
aesni_support()
{
return aesni_support_;
}
PRBool
clmul_support()
{
return clmul_support_;
}
PRBool
avx_support()
{
return avx_support_;
}
static PRStatus
FreeblInit(void)
{
#ifdef NSS_X86_OR_X64
CheckX86CPUSupport();
#endif
return PR_SUCCESS;
}
SECStatus
BL_Init()
{
if (PR_CallOnce(&coFreeblInit, FreeblInit) != PR_SUCCESS) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
RSA_Init();
return SECSuccess;
}

View file

@ -19,30 +19,30 @@
SECStatus
CTR_InitContext(CTRContext *ctr, void *context, freeblCipherFunc cipher,
const unsigned char *param, unsigned int blocksize)
const unsigned char *param)
{
const CK_AES_CTR_PARAMS *ctrParams = (const CK_AES_CTR_PARAMS *)param;
if (ctrParams->ulCounterBits == 0 ||
ctrParams->ulCounterBits > blocksize * PR_BITS_PER_BYTE) {
ctrParams->ulCounterBits > AES_BLOCK_SIZE * PR_BITS_PER_BYTE) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return SECFailure;
}
/* Invariant: 0 < ctr->bufPtr <= blocksize */
/* Invariant: 0 < ctr->bufPtr <= AES_BLOCK_SIZE */
ctr->checkWrap = PR_FALSE;
ctr->bufPtr = blocksize; /* no unused data in the buffer */
ctr->bufPtr = AES_BLOCK_SIZE; /* no unused data in the buffer */
ctr->cipher = cipher;
ctr->context = context;
ctr->counterBits = ctrParams->ulCounterBits;
if (blocksize > sizeof(ctr->counter) ||
blocksize > sizeof(ctrParams->cb)) {
if (AES_BLOCK_SIZE > sizeof(ctr->counter) ||
AES_BLOCK_SIZE > sizeof(ctrParams->cb)) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
PORT_Memcpy(ctr->counter, ctrParams->cb, blocksize);
PORT_Memcpy(ctr->counter, ctrParams->cb, AES_BLOCK_SIZE);
if (ctr->counterBits < 64) {
PORT_Memcpy(ctr->counterFirst, ctr->counter, blocksize);
PORT_Memcpy(ctr->counterFirst, ctr->counter, AES_BLOCK_SIZE);
ctr->checkWrap = PR_TRUE;
}
return SECSuccess;
@ -50,7 +50,7 @@ CTR_InitContext(CTRContext *ctr, void *context, freeblCipherFunc cipher,
CTRContext *
CTR_CreateContext(void *context, freeblCipherFunc cipher,
const unsigned char *param, unsigned int blocksize)
const unsigned char *param)
{
CTRContext *ctr;
SECStatus rv;
@ -60,7 +60,7 @@ CTR_CreateContext(void *context, freeblCipherFunc cipher,
if (ctr == NULL) {
return NULL;
}
rv = CTR_InitContext(ctr, context, cipher, param, blocksize);
rv = CTR_InitContext(ctr, context, cipher, param);
if (rv != SECSuccess) {
CTR_DestroyContext(ctr, PR_TRUE);
ctr = NULL;

View file

@ -23,8 +23,7 @@ struct CTRContextStr {
typedef struct CTRContextStr CTRContext;
SECStatus CTR_InitContext(CTRContext *ctr, void *context,
freeblCipherFunc cipher, const unsigned char *param,
unsigned int blocksize);
freeblCipherFunc cipher, const unsigned char *param);
/*
* The context argument is the inner cipher context to use with cipher. The
@ -34,7 +33,7 @@ SECStatus CTR_InitContext(CTRContext *ctr, void *context,
* The cipher argument is a block cipher in the ECB encrypt mode.
*/
CTRContext *CTR_CreateContext(void *context, freeblCipherFunc cipher,
const unsigned char *param, unsigned int blocksize);
const unsigned char *param);
void CTR_DestroyContext(CTRContext *ctr, PRBool freeit);

View file

@ -20,19 +20,15 @@ struct CTSContextStr {
CTSContext *
CTS_CreateContext(void *context, freeblCipherFunc cipher,
const unsigned char *iv, unsigned int blocksize)
const unsigned char *iv)
{
CTSContext *cts;
if (blocksize > MAX_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return NULL;
}
cts = PORT_ZNew(CTSContext);
if (cts == NULL) {
return NULL;
}
PORT_Memcpy(cts->iv, iv, blocksize);
PORT_Memcpy(cts->iv, iv, MAX_BLOCK_SIZE);
cts->cipher = cipher;
cts->context = context;
return cts;

View file

@ -17,7 +17,7 @@ typedef struct CTSContextStr CTSContext;
* The cipher argument is a block cipher in the CBC mode.
*/
CTSContext *CTS_CreateContext(void *context, freeblCipherFunc cipher,
const unsigned char *iv, unsigned int blocksize);
const unsigned char *iv);
void CTS_DestroyContext(CTSContext *cts, PRBool freeit);

View file

@ -9,10 +9,32 @@
#include "seccomon.h"
#include "secerr.h"
#define GLOBAL_BYTES_SIZE 100
static PRUint8 globalBytes[GLOBAL_BYTES_SIZE];
static unsigned long globalNumCalls = 0;
static PZLock *rng_lock = NULL;
SECStatus
prng_ResetForFuzzing(PZLock *rng_lock)
RNG_RNGInit(void)
{
rng_lock = PZ_NewLock(nssILockOther);
if (!rng_lock) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
return SECFailure;
}
/* --- LOCKED --- */
PZ_Lock(rng_lock);
memset(globalBytes, 0, GLOBAL_BYTES_SIZE);
PZ_Unlock(rng_lock);
/* --- UNLOCKED --- */
return SECSuccess;
}
/* Take min(size, GLOBAL_BYTES_SIZE) bytes from data and use as seed and reset
* the rng state. */
SECStatus
RNG_RandomUpdate(const void *data, size_t bytes)
{
/* Check for a valid RNG lock. */
PORT_Assert(rng_lock != NULL);
@ -23,7 +45,11 @@ prng_ResetForFuzzing(PZLock *rng_lock)
/* --- LOCKED --- */
PZ_Lock(rng_lock);
memset(globalBytes, 0, GLOBAL_BYTES_SIZE);
globalNumCalls = 0;
if (data) {
memcpy(globalBytes, (PRUint8 *)data, PR_MIN(bytes, GLOBAL_BYTES_SIZE));
}
PZ_Unlock(rng_lock);
/* --- UNLOCKED --- */
@ -31,9 +57,9 @@ prng_ResetForFuzzing(PZLock *rng_lock)
}
SECStatus
prng_GenerateDeterministicRandomBytes(PZLock *rng_lock, void *dest, size_t len)
RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
{
static const uint8_t key[32];
static const uint8_t key[32] = { 0 };
uint8_t nonce[12] = { 0 };
/* Check for a valid RNG lock. */
@ -58,10 +84,60 @@ prng_GenerateDeterministicRandomBytes(PZLock *rng_lock, void *dest, size_t len)
}
memset(dest, 0, len);
memcpy(dest, globalBytes, PR_MIN(len, GLOBAL_BYTES_SIZE));
ChaCha20XOR(dest, dest, len, key, nonce, 0);
ChaCha20Poly1305_DestroyContext(cx, PR_TRUE);
PZ_Unlock(rng_lock);
/* --- UNLOCKED --- */
return SECSuccess;
}
void
RNG_RNGShutdown(void)
{
PZ_DestroyLock(rng_lock);
rng_lock = NULL;
}
/* Test functions are not implemented! */
SECStatus
PRNGTEST_Instantiate(const PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *nonce, unsigned int nonce_len,
const PRUint8 *personal_string, unsigned int ps_len)
{
return SECFailure;
}
SECStatus
PRNGTEST_Reseed(const PRUint8 *entropy, unsigned int entropy_len,
const PRUint8 *additional, unsigned int additional_len)
{
return SECFailure;
}
SECStatus
PRNGTEST_Generate(PRUint8 *bytes, unsigned int bytes_len,
const PRUint8 *additional, unsigned int additional_len)
{
return SECFailure;
}
SECStatus
PRNGTEST_Uninstantiate()
{
return SECFailure;
}
SECStatus
PRNGTEST_RunHealthTests()
{
return SECFailure;
}
SECStatus
PRNGTEST_Instantiate_Kat()
{
return SECFailure;
}

View file

@ -14,9 +14,9 @@
#include "secerr.h"
#include "blapi.h"
#include "blapii.h"
#include "secitem.h"
#include "mpi.h"
#include "mpprime.h"
#include "secmpi.h"
#define KEA_DERIVED_SECRET_LEN 128
@ -46,9 +46,7 @@ DH_GenParam(int primeLen, DHParams **params)
{
PLArenaPool *arena;
DHParams *dhparams;
unsigned char *pb = NULL;
unsigned char *ab = NULL;
unsigned long counter = 0;
mp_int p, q, a, h, psub1, test;
mp_err err = MP_OKAY;
SECStatus rv = SECSuccess;
@ -81,17 +79,17 @@ DH_GenParam(int primeLen, DHParams **params)
CHECK_MPI_OK(mp_init(&psub1));
CHECK_MPI_OK(mp_init(&test));
/* generate prime with MPI, uses Miller-Rabin to generate strong prime. */
pb = PORT_Alloc(primeLen);
CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(pb, primeLen));
pb[0] |= 0x80; /* set high-order bit */
pb[primeLen - 1] |= 0x01; /* set low-order bit */
CHECK_MPI_OK(mp_read_unsigned_octets(&p, pb, primeLen));
CHECK_MPI_OK(mpp_make_prime(&p, primeLen * 8, PR_TRUE, &counter));
CHECK_SEC_OK(generate_prime(&p, primeLen));
/* construct Sophie-Germain prime q = (p-1)/2. */
CHECK_MPI_OK(mp_sub_d(&p, 1, &psub1));
CHECK_MPI_OK(mp_div_2(&psub1, &q));
/* construct a generator from the prime. */
ab = PORT_Alloc(primeLen);
if (!ab) {
PORT_SetError(SEC_ERROR_NO_MEMORY);
rv = SECFailure;
goto cleanup;
}
/* generate a candidate number a in p's field */
CHECK_SEC_OK(RNG_GenerateGlobalRandomBytes(ab, primeLen));
CHECK_MPI_OK(mp_read_unsigned_octets(&a, ab, primeLen));
@ -121,16 +119,16 @@ cleanup:
mp_clear(&h);
mp_clear(&psub1);
mp_clear(&test);
if (pb)
PORT_ZFree(pb, primeLen);
if (ab)
if (ab) {
PORT_ZFree(ab, primeLen);
}
if (err) {
MP_TO_SEC_ERROR(err);
rv = SECFailure;
}
if (rv)
if (rv != SECSuccess) {
PORT_FreeArena(arena, PR_TRUE);
}
return rv;
}

View file

@ -20,10 +20,6 @@
#include "secrng.h" /* for RNG_SystemRNG() */
#include "secmpi.h"
#ifdef UNSAFE_FUZZER_MODE
#include "det_rng.h"
#endif
/* PRNG_SEEDLEN defined in NIST SP 800-90 section 10.1
* for SHA-1, SHA-224, and SHA-256 it's 440 bits.
* for SHA-384 and SHA-512 it's 888 bits */
@ -438,10 +434,10 @@ rng_init(void)
globalrng = NULL;
return PR_FAILURE;
}
if (rv != SECSuccess) {
return PR_FAILURE;
}
/* the RNG is in a valid state */
globalrng->isValid = PR_TRUE;
globalrng->isKatTest = PR_FALSE;
@ -658,21 +654,7 @@ prng_GenerateGlobalRandomBytes(RNGContext *rng,
SECStatus
RNG_GenerateGlobalRandomBytes(void *dest, size_t len)
{
#ifdef UNSAFE_FUZZER_MODE
return prng_GenerateDeterministicRandomBytes(globalrng->lock, dest, len);
#else
return prng_GenerateGlobalRandomBytes(globalrng, dest, len);
#endif
}
SECStatus
RNG_ResetForFuzzing(void)
{
#ifdef UNSAFE_FUZZER_MODE
return prng_ResetForFuzzing(globalrng->lock);
#else
return SECFailure;
#endif
}
void

View file

@ -565,6 +565,15 @@ ECDH_Derive(SECItem *publicValue,
return SECFailure;
}
/*
* Make sure the point is on the requested curve to avoid
* certain small subgroup attacks.
*/
if (EC_ValidatePublicKey(ecParams, publicValue) != SECSuccess) {
PORT_SetError(SEC_ERROR_BAD_KEY);
return SECFailure;
}
/* Perform curve specific multiplication using ECMethod */
if (ecParams->fieldID.type == ec_field_plain) {
const ECMethod *method;
@ -580,10 +589,6 @@ ECDH_Derive(SECItem *publicValue,
PORT_SetError(SEC_ERROR_UNSUPPORTED_ELLIPTIC_CURVE);
return SECFailure;
}
if (method->validate(publicValue) != SECSuccess) {
PORT_SetError(SEC_ERROR_BAD_KEY);
return SECFailure;
}
return method->mul(derivedSecret, privateValue, publicValue);
}
@ -1001,9 +1006,14 @@ ECDSA_VerifyDigest(ECPublicKey *key, const SECItem *signature,
}
slen = signature->len / 2;
/*
* The incoming point has been verified in sftk_handlePublicKeyObject.
*/
SECITEM_AllocItem(NULL, &pointC, EC_GetPointSize(ecParams));
if (pointC.data == NULL)
if (pointC.data == NULL) {
goto cleanup;
}
CHECK_MPI_OK(mp_init(&r_));
CHECK_MPI_OK(mp_init(&s_));

View file

@ -22,57 +22,6 @@
if (SECSuccess != (rv = func)) \
goto cleanup
/*
* Initializes a SECItem from a hexadecimal string
*
* Warning: This function ignores leading 00's, so any leading 00's
* in the hexadecimal string must be optional.
*/
static SECItem *
hexString2SECItem(PLArenaPool *arena, SECItem *item, const char *str)
{
int i = 0;
int byteval = 0;
int tmp = PORT_Strlen(str);
PORT_Assert(arena);
PORT_Assert(item);
if ((tmp % 2) != 0)
return NULL;
/* skip leading 00's unless the hex string is "00" */
while ((tmp > 2) && (str[0] == '0') && (str[1] == '0')) {
str += 2;
tmp -= 2;
}
item->data = (unsigned char *)PORT_ArenaAlloc(arena, tmp / 2);
if (item->data == NULL)
return NULL;
item->len = tmp / 2;
while (str[i]) {
if ((str[i] >= '0') && (str[i] <= '9'))
tmp = str[i] - '0';
else if ((str[i] >= 'a') && (str[i] <= 'f'))
tmp = str[i] - 'a' + 10;
else if ((str[i] >= 'A') && (str[i] <= 'F'))
tmp = str[i] - 'A' + 10;
else
return NULL;
byteval = byteval * 16 + tmp;
if ((i % 2) != 0) {
item->data[i / 2] = byteval;
byteval = 0;
}
i++;
}
return item;
}
/* Copy all of the fields from srcParams into dstParams
*/
SECStatus
@ -120,12 +69,10 @@ cleanup:
}
static SECStatus
gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params)
gf_populate_params_bytes(ECCurveName name, ECFieldType field_type, ECParams *params)
{
SECStatus rv = SECFailure;
const ECCurveParams *curveParams;
/* 2 ['0'+'4'] + MAX_ECKEY_LEN * 2 [x,y] * 2 [hex string] + 1 ['\0'] */
char genenc[3 + 2 * 2 * MAX_ECKEY_LEN];
const ECCurveBytes *curveParams;
if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve))
goto cleanup;
@ -134,26 +81,19 @@ gf_populate_params(ECCurveName name, ECFieldType field_type, ECParams *params)
CHECK_OK(curveParams);
params->fieldID.size = curveParams->size;
params->fieldID.type = field_type;
if (field_type == ec_field_GFp ||
field_type == ec_field_plain) {
CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.prime,
curveParams->irr));
} else {
CHECK_OK(hexString2SECItem(params->arena, &params->fieldID.u.poly,
curveParams->irr));
if (field_type != ec_field_GFp && field_type != ec_field_plain) {
return SECFailure;
}
CHECK_OK(hexString2SECItem(params->arena, &params->curve.a,
curveParams->curvea));
CHECK_OK(hexString2SECItem(params->arena, &params->curve.b,
curveParams->curveb));
genenc[0] = '0';
genenc[1] = '4';
genenc[2] = '\0';
strcat(genenc, curveParams->genx);
strcat(genenc, curveParams->geny);
CHECK_OK(hexString2SECItem(params->arena, &params->base, genenc));
CHECK_OK(hexString2SECItem(params->arena, &params->order,
curveParams->order));
params->fieldID.u.prime.len = curveParams->scalarSize;
params->fieldID.u.prime.data = (unsigned char *)curveParams->irr;
params->curve.a.len = curveParams->scalarSize;
params->curve.a.data = (unsigned char *)curveParams->curvea;
params->curve.b.len = curveParams->scalarSize;
params->curve.b.data = (unsigned char *)curveParams->curveb;
params->base.len = curveParams->pointSize;
params->base.data = (unsigned char *)curveParams->base;
params->order.len = curveParams->scalarSize;
params->order.data = (unsigned char *)curveParams->order;
params->cofactor = curveParams->cofactor;
rv = SECSuccess;
@ -216,29 +156,30 @@ EC_FillParams(PLArenaPool *arena, const SECItem *encodedParams,
/* Populate params for prime256v1 aka secp256r1
* (the NIST P-256 curve)
*/
CHECK_SEC_OK(gf_populate_params(ECCurve_X9_62_PRIME_256V1, ec_field_GFp,
params));
CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_X9_62_PRIME_256V1,
ec_field_GFp, params));
break;
case SEC_OID_SECG_EC_SECP384R1:
/* Populate params for secp384r1
* (the NIST P-384 curve)
*/
CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_384R1, ec_field_GFp,
params));
CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_384R1,
ec_field_GFp, params));
break;
case SEC_OID_SECG_EC_SECP521R1:
/* Populate params for secp521r1
* (the NIST P-521 curve)
*/
CHECK_SEC_OK(gf_populate_params(ECCurve_SECG_PRIME_521R1, ec_field_GFp,
params));
CHECK_SEC_OK(gf_populate_params_bytes(ECCurve_SECG_PRIME_521R1,
ec_field_GFp, params));
break;
case SEC_OID_CURVE25519:
/* Populate params for Curve25519 */
CHECK_SEC_OK(gf_populate_params(ECCurve25519, ec_field_plain, params));
CHECK_SEC_OK(gf_populate_params_bytes(ECCurve25519, ec_field_plain,
params));
break;
default:
@ -296,16 +237,20 @@ int
EC_GetPointSize(const ECParams *params)
{
ECCurveName name = params->name;
const ECCurveParams *curveParams;
const ECCurveBytes *curveParams;
if ((name < ECCurve_noName) || (name > ECCurve_pastLastCurve) ||
((curveParams = ecCurve_map[name]) == NULL)) {
/* unknown curve, calculate point size from params. assume standard curves with 2 points
/* unknown curve, calculate point size from params. assume standard curves with 2 points
* and a point compression indicator byte */
int sizeInBytes = (params->fieldID.size + 7) / 8;
return sizeInBytes * 2 + 1;
}
return curveParams->pointSize;
if (name == ECCurve25519) {
/* Only X here */
return curveParams->scalarSize;
}
return curveParams->pointSize - 1;
}
#endif /* NSS_DISABLE_ECC */

View file

@ -90,20 +90,6 @@ the linear coefficient in the curve defining equation).
ecp_192.c and ecp_224.c provide optimized field arithmetic.
Point Arithmetic over Binary Polynomial Fields
----------------------------------------------
ec2_aff.c provides point arithmetic using affine coordinates.
ec2_proj.c provides point arithmetic using projective coordinates.
(Projective coordinates represent a point (x, y) as (X, Y, Z), where
x=X/Z, y=Y/Z^2).
ec2_mont.c provides point multiplication using Montgomery projective
coordinates.
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field arithmetic.
Field Arithmetic
----------------
@ -126,18 +112,6 @@ fields defined by nistp192 and nistp224 primes.
ecl_gf.c provides wrappers around the basic field operations.
Binary Polynomial Field Arithmetic
----------------------------------
../mpi/mp_gf2m.c provides basic binary polynomial field arithmetic,
including addition, multiplication, squaring, mod, and division, as well
as conversion ob polynomial representations between bitstring and int[].
ec2_163.c, ec2_193.c, and ec2_233.c provide optimized field mod, mul,
and sqr operations.
ecl_gf.c provides wrappers around the basic field operations.
Field Encoding
--------------
@ -187,81 +161,3 @@ arithmetic. Instead, they use basic field arithmetic with their
optimized reduction (as in ecp_192.c and ecp_224.c). They
use the same point multiplication and simultaneous point multiplication
algorithms as other curves over prime fields.
Curves over binary polynomial fields by default use generic field
arithmetic with montgomery point multiplication and basic kP + lQ
computation (multiply, multiply, and add). (Wiring in function
ECGroup_cons_GF2m in ecl.c.)
Curves over binary polynomial fields that have optimized field
arithmetic (i.e., any 163-, 193, or 233-bit field) use their optimized
field arithmetic. They use the same point multiplication and
simultaneous point multiplication algorithms as other curves over binary
fields.
Example
-------
We provide an example for plugging in an optimized implementation for
the Koblitz curve nistk163.
Suppose the file ec2_k163.c contains the optimized implementation. In
particular it contains a point multiplication function:
mp_err ec_GF2m_nistk163_pt_mul(const mp_int *n, const mp_int *px,
const mp_int *py, mp_int *rx, mp_int *ry, const ECGroup *group);
Since only a pt_mul function is provided, the generic pt_add function
will be used.
There are two options for handling the optimized field arithmetic used
by the ..._pt_mul function. Say the optimized field arithmetic includes
the following functions:
mp_err ec_GF2m_nistk163_add(const mp_int *a, const mp_int *b,
mp_int *r, const GFMethod *meth);
mp_err ec_GF2m_nistk163_mul(const mp_int *a, const mp_int *b,
mp_int *r, const GFMethod *meth);
mp_err ec_GF2m_nistk163_sqr(const mp_int *a, const mp_int *b,
mp_int *r, const GFMethod *meth);
mp_err ec_GF2m_nistk163_div(const mp_int *a, const mp_int *b,
mp_int *r, const GFMethod *meth);
First, the optimized field arithmetic could simply be called directly
by the ..._pt_mul function. This would be accomplished by changing
the ecgroup_fromNameAndHex function in ecl.c to include the following
statements:
if (name == ECCurve_NIST_K163) {
group = ECGroup_consGF2m(&irr, NULL, &curvea, &curveb, &genx,
&geny, &order, params->cofactor);
if (group == NULL) { res = MP_UNDEF; goto CLEANUP; }
MP_CHECKOK( ec_group_set_nistk163(group) );
}
and including in ec2_k163.c the following function:
mp_err ec_group_set_nistk163(ECGroup *group) {
group->point_mul = &ec_GF2m_nistk163_pt_mul;
return MP_OKAY;
}
As a result, ec_GF2m_pt_add and similar functions would use the
basic binary polynomial field arithmetic ec_GF2m_add, ec_GF2m_mul,
ec_GF2m_sqr, and ec_GF2m_div.
Alternatively, the optimized field arithmetic could be wired into the
group's GFMethod. This would be accomplished by putting the following
function in ec2_k163.c:
mp_err ec_group_set_nistk163(ECGroup *group) {
group->meth->field_add = &ec_GF2m_nistk163_add;
group->meth->field_mul = &ec_GF2m_nistk163_mul;
group->meth->field_sqr = &ec_GF2m_nistk163_sqr;
group->meth->field_div = &ec_GF2m_nistk163_div;
group->point_mul = &ec_GF2m_nistk163_pt_mul;
return MP_OKAY;
}
For an example of functions that use special field encodings, take a
look at ecp_mont.c.

View file

@ -206,7 +206,7 @@ fexpand(felem *output, const u8 *in)
output[1] = (*((const uint64_t *)(in + 6)) >> 3) & MASK51;
output[2] = (*((const uint64_t *)(in + 12)) >> 6) & MASK51;
output[3] = (*((const uint64_t *)(in + 19)) >> 1) & MASK51;
output[4] = (*((const uint64_t *)(in + 25)) >> 4) & MASK51;
output[4] = (*((const uint64_t *)(in + 24)) >> 12) & MASK51;
}
/* Take a fully reduced polynomial form number and contract it into a

View file

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ecl-exp.h"
#include "eclt.h"
#include <stdlib.h>
#ifndef __ecl_curve_h_
@ -12,52 +13,201 @@
#define KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */
#define KU_KEY_AGREEMENT (0x08) /* bit 4 */
static const ECCurveParams ecCurve_NIST_P256 = {
static const PRUint8 irr256[32] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const PRUint8 a256[32] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC };
static const PRUint8 b256[32] =
{ 0x5A, 0xC6, 0x35, 0xD8, 0xAA, 0x3A, 0x93, 0xE7, 0xB3, 0xEB, 0xBD, 0x55,
0x76, 0x98, 0x86, 0xBC, 0x65, 0x1D, 0x06, 0xB0, 0xCC, 0x53, 0xB0, 0xF6,
0x3B, 0xCE, 0x3C, 0x3E, 0x27, 0xD2, 0x60, 0x4B };
static const PRUint8 x256[32] =
{ 0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96 };
static const PRUint8 y256[32] =
{ 0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
static const PRUint8 order256[32] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xBC, 0xE6, 0xFA, 0xAD, 0xA7, 0x17, 0x9E, 0x84,
0xF3, 0xB9, 0xCA, 0xC2, 0xFC, 0x63, 0x25, 0x51 };
static const PRUint8 base256[66] =
{ 0x04, 0x00,
0x6B, 0x17, 0xD1, 0xF2, 0xE1, 0x2C, 0x42, 0x47, 0xF8, 0xBC, 0xE6, 0xE5,
0x63, 0xA4, 0x40, 0xF2, 0x77, 0x03, 0x7D, 0x81, 0x2D, 0xEB, 0x33, 0xA0,
0xF4, 0xA1, 0x39, 0x45, 0xD8, 0x98, 0xC2, 0x96,
0x4F, 0xE3, 0x42, 0xE2, 0xFE, 0x1A, 0x7F, 0x9B, 0x8E, 0xE7, 0xEB, 0x4A,
0x7C, 0x0F, 0x9E, 0x16, 0x2B, 0xCE, 0x33, 0x57, 0x6B, 0x31, 0x5E, 0xCE,
0xCB, 0xB6, 0x40, 0x68, 0x37, 0xBF, 0x51, 0xF5 };
static const ECCurveBytes ecCurve_NIST_P256 = {
"NIST-P256", ECField_GFp, 256,
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF",
"FFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC",
"5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B",
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296",
"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5",
"FFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551",
1, 128, 65, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
irr256, a256, b256, x256, y256, order256, base256,
1, 128, 66, 32,
KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
};
static const ECCurveParams ecCurve_NIST_P384 = {
static const PRUint8 irr384[48] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF };
static const PRUint8 a384[48] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFC };
static const PRUint8 b384[48] =
{ 0xB3, 0x31, 0x2F, 0xA7, 0xE2, 0x3E, 0xE7, 0xE4, 0x98, 0x8E, 0x05, 0x6B,
0xE3, 0xF8, 0x2D, 0x19, 0x18, 0x1D, 0x9C, 0x6E, 0xFE, 0x81, 0x41, 0x12,
0x03, 0x14, 0x08, 0x8F, 0x50, 0x13, 0x87, 0x5A, 0xC6, 0x56, 0x39, 0x8D,
0x8A, 0x2E, 0xD1, 0x9D, 0x2A, 0x85, 0xC8, 0xED, 0xD3, 0xEC, 0x2A, 0xEF };
static const PRUint8 x384[48] =
{ 0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7 };
static const PRUint8 y384[48] =
{ 0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
static const PRUint8 order384[48] =
{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xC7, 0x63, 0x4D, 0x81, 0xF4, 0x37, 0x2D, 0xDF, 0x58, 0x1A, 0x0D, 0xB2,
0x48, 0xB0, 0xA7, 0x7A, 0xEC, 0xEC, 0x19, 0x6A, 0xCC, 0xC5, 0x29, 0x73 };
static const PRUint8 base384[98] =
{ 0x04, 0x00,
0xAA, 0x87, 0xCA, 0x22, 0xBE, 0x8B, 0x05, 0x37, 0x8E, 0xB1, 0xC7, 0x1E,
0xF3, 0x20, 0xAD, 0x74, 0x6E, 0x1D, 0x3B, 0x62, 0x8B, 0xA7, 0x9B, 0x98,
0x59, 0xF7, 0x41, 0xE0, 0x82, 0x54, 0x2A, 0x38, 0x55, 0x02, 0xF2, 0x5D,
0xBF, 0x55, 0x29, 0x6C, 0x3A, 0x54, 0x5E, 0x38, 0x72, 0x76, 0x0A, 0xB7,
0x36, 0x17, 0xDE, 0x4A, 0x96, 0x26, 0x2C, 0x6F, 0x5D, 0x9E, 0x98, 0xBF,
0x92, 0x92, 0xDC, 0x29, 0xF8, 0xF4, 0x1D, 0xBD, 0x28, 0x9A, 0x14, 0x7C,
0xE9, 0xDA, 0x31, 0x13, 0xB5, 0xF0, 0xB8, 0xC0, 0x0A, 0x60, 0xB1, 0xCE,
0x1D, 0x7E, 0x81, 0x9D, 0x7A, 0x43, 0x1D, 0x7C, 0x90, 0xEA, 0x0E, 0x5F };
static const ECCurveBytes ecCurve_NIST_P384 = {
"NIST-P384", ECField_GFp, 384,
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFF",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFFFF0000000000000000FFFFFFFC",
"B3312FA7E23EE7E4988E056BE3F82D19181D9C6EFE8141120314088F5013875AC656398D8A2ED19D2A85C8EDD3EC2AEF",
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7",
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F",
"FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC7634D81F4372DDF581A0DB248B0A77AECEC196ACCC52973",
1, 192, 97, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
irr384, a384, b384, x384, y384, order384, base384,
1, 192, 98, 48,
KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
};
static const ECCurveParams ecCurve_NIST_P521 = {
static const PRUint8 irr521[66] =
{ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
static const PRUint8 a521[66] =
{ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFC };
static const PRUint8 b521[66] =
{ 0x00, 0x51, 0x95, 0x3E, 0xB9, 0x61, 0x8E, 0x1C, 0x9A, 0x1F, 0x92, 0x9A,
0x21, 0xA0, 0xB6, 0x85, 0x40, 0xEE, 0xA2, 0xDA, 0x72, 0x5B, 0x99, 0xB3,
0x15, 0xF3, 0xB8, 0xB4, 0x89, 0x91, 0x8E, 0xF1, 0x09, 0xE1, 0x56, 0x19,
0x39, 0x51, 0xEC, 0x7E, 0x93, 0x7B, 0x16, 0x52, 0xC0, 0xBD, 0x3B, 0xB1,
0xBF, 0x07, 0x35, 0x73, 0xDF, 0x88, 0x3D, 0x2C, 0x34, 0xF1, 0xEF, 0x45,
0x1F, 0xD4, 0x6B, 0x50, 0x3F, 0x00 };
static const PRUint8 x521[66] =
{ 0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66 };
static const PRUint8 y521[66] =
{ 0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50 };
static const PRUint8 order521[66] =
{ 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFA, 0x51, 0x86,
0x87, 0x83, 0xBF, 0x2F, 0x96, 0x6B, 0x7F, 0xCC, 0x01, 0x48, 0xF7, 0x09,
0xA5, 0xD0, 0x3B, 0xB5, 0xC9, 0xB8, 0x89, 0x9C, 0x47, 0xAE, 0xBB, 0x6F,
0xB7, 0x1E, 0x91, 0x38, 0x64, 0x09 };
static const PRUint8 base521[134] =
{
0x04, 0x00,
0x00, 0xC6, 0x85, 0x8E, 0x06, 0xB7, 0x04, 0x04, 0xE9, 0xCD, 0x9E, 0x3E,
0xCB, 0x66, 0x23, 0x95, 0xB4, 0x42, 0x9C, 0x64, 0x81, 0x39, 0x05, 0x3F,
0xB5, 0x21, 0xF8, 0x28, 0xAF, 0x60, 0x6B, 0x4D, 0x3D, 0xBA, 0xA1, 0x4B,
0x5E, 0x77, 0xEF, 0xE7, 0x59, 0x28, 0xFE, 0x1D, 0xC1, 0x27, 0xA2, 0xFF,
0xA8, 0xDE, 0x33, 0x48, 0xB3, 0xC1, 0x85, 0x6A, 0x42, 0x9B, 0xF9, 0x7E,
0x7E, 0x31, 0xC2, 0xE5, 0xBD, 0x66,
0x01, 0x18, 0x39, 0x29, 0x6A, 0x78, 0x9A, 0x3B, 0xC0, 0x04, 0x5C, 0x8A,
0x5F, 0xB4, 0x2C, 0x7D, 0x1B, 0xD9, 0x98, 0xF5, 0x44, 0x49, 0x57, 0x9B,
0x44, 0x68, 0x17, 0xAF, 0xBD, 0x17, 0x27, 0x3E, 0x66, 0x2C, 0x97, 0xEE,
0x72, 0x99, 0x5E, 0xF4, 0x26, 0x40, 0xC5, 0x50, 0xB9, 0x01, 0x3F, 0xAD,
0x07, 0x61, 0x35, 0x3C, 0x70, 0x86, 0xA2, 0x72, 0xC2, 0x40, 0x88, 0xBE,
0x94, 0x76, 0x9F, 0xD1, 0x66, 0x50
};
static const ECCurveBytes ecCurve_NIST_P521 = {
"NIST-P521", ECField_GFp, 521,
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF",
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFC",
"0051953EB9618E1C9A1F929A21A0B68540EEA2DA725B99B315F3B8B489918EF109E156193951EC7E937B1652C0BD3BB1BF073573DF883D2C34F1EF451FD46B503F00",
"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66",
"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650",
"01FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFA51868783BF2F966B7FCC0148F709A5D03BB5C9B8899C47AEBB6FB71E91386409",
1, 256, 133, KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
irr521, a521, b521, x521, y521, order521, base521,
1, 256, 134, 66,
KU_DIGITAL_SIGNATURE | KU_KEY_AGREEMENT
};
static const ECCurveParams ecCurve25519 = {
static const PRUint8 irr25519[32] =
{ 0xed, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f };
static const PRUint8 a25519[32] =
{ 0x06, 0x6d, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const PRUint8 b25519[32] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const PRUint8 x25519[32] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09 };
static const PRUint8 y25519[32] =
{ 0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20 };
static const PRUint8 order25519[32] =
{ 0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2,
0xde, 0xf9, 0xde, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10 };
static const PRUint8 base25519[66] =
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09,
0xd9, 0xd3, 0xce, 0x7e, 0xa2, 0xc5, 0xe9, 0x29, 0xb2, 0x61, 0x7c, 0x6d,
0x7e, 0x4d, 0x3d, 0x92, 0x4c, 0xd1, 0x48, 0x77, 0x2c, 0xdd, 0x1e, 0xe0,
0xb4, 0x86, 0xa0, 0xb8, 0xa1, 0x19, 0xae, 0x20, 0x00, 0x04 };
static const ECCurveBytes ecCurve_25519 = {
"Curve25519", ECField_GFp, 255,
"7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed",
"076D06",
"00",
"0900000000000000000000000000000000000000000000000000000000000000",
"20AE19A1B8A086B4E01EDD2C7748D14C923D4D7E6D7C61B229E9C5A27ECED3D9",
"1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed",
8, 128, 32, KU_KEY_AGREEMENT
irr25519, a25519, b25519, x25519, y25519, order25519, base25519,
8, 128, 66, 32,
KU_KEY_AGREEMENT
};
/* mapping between ECCurveName enum and pointers to ECCurveParams */
static const ECCurveParams *ecCurve_map[] = {
static const ECCurveBytes *ecCurve_map[] = {
NULL, /* ECCurve_noName */
NULL, /* ECCurve_NIST_P192 */
NULL, /* ECCurve_NIST_P224 */
@ -116,7 +266,7 @@ static const ECCurveParams *ecCurve_map[] = {
NULL, /* ECCurve_WTLS_1 */
NULL, /* ECCurve_WTLS_8 */
NULL, /* ECCurve_WTLS_9 */
&ecCurve25519, /* ECCurve25519 */
&ecCurve_25519, /* ECCurve25519 */
NULL /* ECCurve_pastLastCurve */
};

View file

@ -246,12 +246,5 @@ mp_err ec_group_set_gf2m233(ECGroup *group, ECCurveName name);
/* Optimized point multiplication */
mp_err ec_group_set_gfp256_32(ECGroup *group, ECCurveName name);
/* Optimized floating-point arithmetic */
#ifdef ECL_USE_FP
mp_err ec_group_set_secp160r1_fp(ECGroup *group);
mp_err ec_group_set_nistp192_fp(ECGroup *group);
mp_err ec_group_set_nistp224_fp(ECGroup *group);
#endif
SECStatus ec_Curve25519_mul(PRUint8 *q, const PRUint8 *s, const PRUint8 *p);
#endif /* __ecl_priv_h_ */

View file

@ -2,11 +2,16 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifdef FREEBL_NO_DEPEND
#include "../stubs.h"
#endif
#include "mpi.h"
#include "mplogic.h"
#include "ecl.h"
#include "ecl-priv.h"
#include "ecp.h"
#include "ecl-curve.h"
#include <stdlib.h>
#include <string.h>
@ -128,14 +133,84 @@ CLEANUP:
return group;
}
/* Construct ECGroup from hex parameters and name, if any. Called by
* ECGroup_fromHex and ECGroup_fromName. */
/* Construct an ECGroup. */
ECGroup *
ecgroup_fromNameAndHex(const ECCurveName name,
const ECCurveParams *params)
construct_ecgroup(const ECCurveName name, mp_int irr, mp_int curvea,
mp_int curveb, mp_int genx, mp_int geny, mp_int order,
int cofactor, ECField field, const char *text)
{
int bits;
ECGroup *group = NULL;
mp_err res = MP_OKAY;
/* determine number of bits */
bits = mpl_significant_bits(&irr) - 1;
if (bits < MP_OKAY) {
res = bits;
goto CLEANUP;
}
/* determine which optimizations (if any) to use */
if (field == ECField_GFp) {
switch (name) {
case ECCurve_SECG_PRIME_256R1:
group =
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
&order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
MP_CHECKOK(ec_group_set_gfp256(group, name));
MP_CHECKOK(ec_group_set_gfp256_32(group, name));
break;
case ECCurve_SECG_PRIME_521R1:
group =
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
&order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
MP_CHECKOK(ec_group_set_gfp521(group, name));
break;
default:
/* use generic arithmetic */
group =
ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
&order, cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
}
} else {
res = MP_UNDEF;
goto CLEANUP;
}
/* set name, if any */
if ((group != NULL) && (text != NULL)) {
group->text = strdup(text);
if (group->text == NULL) {
res = MP_MEM;
}
}
CLEANUP:
if (group && res != MP_OKAY) {
ECGroup_free(group);
return NULL;
}
return group;
}
/* Construct ECGroup from parameters and name, if any. */
ECGroup *
ecgroup_fromName(const ECCurveName name,
const ECCurveBytes *params)
{
mp_int irr, curvea, curveb, genx, geny, order;
int bits;
ECGroup *group = NULL;
mp_err res = MP_OKAY;
@ -152,66 +227,15 @@ ecgroup_fromNameAndHex(const ECCurveName name,
MP_CHECKOK(mp_init(&genx));
MP_CHECKOK(mp_init(&geny));
MP_CHECKOK(mp_init(&order));
MP_CHECKOK(mp_read_radix(&irr, params->irr, 16));
MP_CHECKOK(mp_read_radix(&curvea, params->curvea, 16));
MP_CHECKOK(mp_read_radix(&curveb, params->curveb, 16));
MP_CHECKOK(mp_read_radix(&genx, params->genx, 16));
MP_CHECKOK(mp_read_radix(&geny, params->geny, 16));
MP_CHECKOK(mp_read_radix(&order, params->order, 16));
MP_CHECKOK(mp_read_unsigned_octets(&irr, params->irr, params->scalarSize));
MP_CHECKOK(mp_read_unsigned_octets(&curvea, params->curvea, params->scalarSize));
MP_CHECKOK(mp_read_unsigned_octets(&curveb, params->curveb, params->scalarSize));
MP_CHECKOK(mp_read_unsigned_octets(&genx, params->genx, params->scalarSize));
MP_CHECKOK(mp_read_unsigned_octets(&geny, params->geny, params->scalarSize));
MP_CHECKOK(mp_read_unsigned_octets(&order, params->order, params->scalarSize));
/* determine number of bits */
bits = mpl_significant_bits(&irr) - 1;
if (bits < MP_OKAY) {
res = bits;
goto CLEANUP;
}
/* determine which optimizations (if any) to use */
if (params->field == ECField_GFp) {
switch (name) {
case ECCurve_SECG_PRIME_256R1:
group =
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
&order, params->cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
MP_CHECKOK(ec_group_set_gfp256(group, name));
MP_CHECKOK(ec_group_set_gfp256_32(group, name));
break;
case ECCurve_SECG_PRIME_521R1:
group =
ECGroup_consGFp(&irr, &curvea, &curveb, &genx, &geny,
&order, params->cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
MP_CHECKOK(ec_group_set_gfp521(group, name));
break;
default:
/* use generic arithmetic */
group =
ECGroup_consGFp_mont(&irr, &curvea, &curveb, &genx, &geny,
&order, params->cofactor);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
}
} else {
res = MP_UNDEF;
goto CLEANUP;
}
/* set name, if any */
if ((group != NULL) && (params->text != NULL)) {
group->text = strdup(params->text);
if (group->text == NULL) {
res = MP_MEM;
}
}
group = construct_ecgroup(name, irr, curvea, curveb, genx, geny, order,
params->cofactor, params->field, params->text);
CLEANUP:
mp_clear(&irr);
@ -220,48 +244,41 @@ CLEANUP:
mp_clear(&genx);
mp_clear(&geny);
mp_clear(&order);
if (res != MP_OKAY) {
if (group && res != MP_OKAY) {
ECGroup_free(group);
return NULL;
}
return group;
}
/* Construct ECGroup from hexadecimal representations of parameters. */
ECGroup *
ECGroup_fromHex(const ECCurveParams *params)
/* Construct ECCurveBytes from an ECCurveName */
const ECCurveBytes *
ec_GetNamedCurveParams(const ECCurveName name)
{
return ecgroup_fromNameAndHex(ECCurve_noName, params);
if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
(ecCurve_map[name] == NULL)) {
return NULL;
} else {
return ecCurve_map[name];
}
}
/* Construct ECGroup from named parameters. */
ECGroup *
ECGroup_fromName(const ECCurveName name)
{
ECGroup *group = NULL;
ECCurveParams *params = NULL;
mp_err res = MP_OKAY;
const ECCurveBytes *params = NULL;
params = EC_GetNamedCurveParams(name);
/* This doesn't work with Curve25519 but it's not necessary to. */
PORT_Assert(name != ECCurve25519);
params = ec_GetNamedCurveParams(name);
if (params == NULL) {
res = MP_UNDEF;
goto CLEANUP;
return NULL;
}
/* construct actual group */
group = ecgroup_fromNameAndHex(name, params);
if (group == NULL) {
res = MP_UNDEF;
goto CLEANUP;
}
CLEANUP:
EC_FreeCurveParams(params);
if (res != MP_OKAY) {
ECGroup_free(group);
return NULL;
}
return group;
return ecgroup_fromName(name, params);
}
/* Validates an EC public key as described in Section 5.2.2 of X9.62. */

View file

@ -11,28 +11,17 @@
#include "blapi.h"
#include "ecl-exp.h"
#include "mpi.h"
#include "eclt.h"
struct ECGroupStr;
typedef struct ECGroupStr ECGroup;
/* Construct ECGroup from hexadecimal representations of parameters. */
ECGroup *ECGroup_fromHex(const ECCurveParams *params);
/* Construct ECGroup from named parameters. */
ECGroup *ECGroup_fromName(const ECCurveName name);
/* Free an allocated ECGroup. */
void ECGroup_free(ECGroup *group);
/* Construct ECCurveParams from an ECCurveName */
ECCurveParams *EC_GetNamedCurveParams(const ECCurveName name);
/* Duplicates an ECCurveParams */
ECCurveParams *ECCurveParams_dup(const ECCurveParams *params);
/* Free an allocated ECCurveParams */
void EC_FreeCurveParams(ECCurveParams *params);
/* Elliptic curve scalar-point multiplication. Computes Q(x, y) = k * P(x,
* y). If x, y = NULL, then P is assumed to be the generator (base point)
* of the group of points on the elliptic curve. Input and output values

View file

@ -1,93 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ecl.h"
#include "ecl-curve.h"
#include "ecl-priv.h"
#include <stdlib.h>
#include <string.h>
#define CHECK(func) \
if ((func) == NULL) { \
res = 0; \
goto CLEANUP; \
}
/* Duplicates an ECCurveParams */
ECCurveParams *
ECCurveParams_dup(const ECCurveParams *params)
{
int res = 1;
ECCurveParams *ret = NULL;
CHECK(ret = (ECCurveParams *)calloc(1, sizeof(ECCurveParams)));
if (params->text != NULL) {
CHECK(ret->text = strdup(params->text));
}
ret->field = params->field;
ret->size = params->size;
if (params->irr != NULL) {
CHECK(ret->irr = strdup(params->irr));
}
if (params->curvea != NULL) {
CHECK(ret->curvea = strdup(params->curvea));
}
if (params->curveb != NULL) {
CHECK(ret->curveb = strdup(params->curveb));
}
if (params->genx != NULL) {
CHECK(ret->genx = strdup(params->genx));
}
if (params->geny != NULL) {
CHECK(ret->geny = strdup(params->geny));
}
if (params->order != NULL) {
CHECK(ret->order = strdup(params->order));
}
ret->cofactor = params->cofactor;
CLEANUP:
if (res != 1) {
EC_FreeCurveParams(ret);
return NULL;
}
return ret;
}
#undef CHECK
/* Construct ECCurveParams from an ECCurveName */
ECCurveParams *
EC_GetNamedCurveParams(const ECCurveName name)
{
if ((name <= ECCurve_noName) || (ECCurve_pastLastCurve <= name) ||
(ecCurve_map[name] == NULL)) {
return NULL;
} else {
return ECCurveParams_dup(ecCurve_map[name]);
}
}
/* Free the memory allocated (if any) to an ECCurveParams object. */
void
EC_FreeCurveParams(ECCurveParams *params)
{
if (params == NULL)
return;
if (params->text != NULL)
free(params->text);
if (params->irr != NULL)
free(params->irr);
if (params->curvea != NULL)
free(params->curvea);
if (params->curveb != NULL)
free(params->curveb);
if (params->genx != NULL)
free(params->genx);
if (params->geny != NULL)
free(params->geny);
if (params->order != NULL)
free(params->order);
free(params);
}

View file

@ -0,0 +1,30 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/* This header holds ECC types and must not be exported publicly. */
#ifndef __eclt_h_
#define __eclt_h_
/* byte encoding of curve parameters */
struct ECCurveBytesStr {
char *text;
ECField field;
size_t size;
const PRUint8 *irr;
const PRUint8 *curvea;
const PRUint8 *curveb;
const PRUint8 *genx;
const PRUint8 *geny;
const PRUint8 *order;
const PRUint8 *base;
int cofactor;
int security;
size_t pointSize;
size_t scalarSize;
unsigned int usage;
};
typedef struct ECCurveBytesStr ECCurveBytes;
#endif /* __ecl_h_ */

View file

@ -79,8 +79,7 @@ ec_Curve25519_pt_validate(const SECItem *px)
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff },
};
/* The point must not be longer than 32 (it can be smaller). */
if (px->len <= 32) {
if (px->len == 32) {
p = px->data;
} else {
return SECFailure;

View file

@ -127,6 +127,17 @@ ec_GFp_pt_add_jm_aff(const mp_int *px, const mp_int *py, const mp_int *pz,
MP_CHECKOK(group->meth->field_mul(A, qx, A, group->meth));
MP_CHECKOK(group->meth->field_mul(B, qy, B, group->meth));
/* Check P == Q */
if (mp_cmp(A, px) == 0) {
if (mp_cmp(B, py) == 0) {
/* If Px == Qx && Py == Qy, double P. */
return ec_GFp_pt_dbl_jm(px, py, pz, paz4, rx, ry, rz, raz4,
scratch, group);
}
/* If Px == Qx && Py != Qy, return point at infinity. */
return ec_GFp_pt_set_inf_jac(rx, ry, rz);
}
/* C = A - px, D = B - py */
MP_CHECKOK(group->meth->field_sub(A, px, C, group->meth));
MP_CHECKOK(group->meth->field_sub(B, py, D, group->meth));

View file

@ -1,121 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mpi.h"
#include "mplogic.h"
#include "ecl.h"
#include "ecp.h"
#include "ecl-priv.h"
#include <sys/types.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
/* Returns 2^e as an integer. This is meant to be used for small powers of
* two. */
int ec_twoTo(int e);
/* Number of bits of scalar to test */
#define BITSIZE 160
/* Time k repetitions of operation op. */
#define M_TimeOperation(op, k) \
{ \
double dStart, dNow, dUserTime; \
struct rusage ru; \
int i; \
getrusage(RUSAGE_SELF, &ru); \
dStart = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
for (i = 0; i < k; i++) { \
{ \
op; \
} \
}; \
getrusage(RUSAGE_SELF, &ru); \
dNow = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
dUserTime = dNow - dStart; \
if (dUserTime) \
printf(" %-45s\n k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
}
/* Tests wNAF computation. Non-adjacent-form is discussed in the paper: D.
* Hankerson, J. Hernandez and A. Menezes, "Software implementation of
* elliptic curve cryptography over binary fields", Proc. CHES 2000. */
mp_err
main(void)
{
signed char naf[BITSIZE + 1];
ECGroup *group = NULL;
mp_int k;
mp_int *scalar;
int i, count;
int res;
int w = 5;
char s[1000];
/* Get a 160 bit scalar to compute wNAF from */
group = ECGroup_fromName(ECCurve_SECG_PRIME_160R1);
scalar = &group->genx;
/* Compute wNAF representation of scalar */
ec_compute_wNAF(naf, BITSIZE, scalar, w);
/* Verify correctness of representation */
mp_init(&k); /* init k to 0 */
for (i = BITSIZE; i >= 0; i--) {
mp_add(&k, &k, &k);
/* digits in mp_???_d are unsigned */
if (naf[i] >= 0) {
mp_add_d(&k, naf[i], &k);
} else {
mp_sub_d(&k, -naf[i], &k);
}
}
if (mp_cmp(&k, scalar) != 0) {
printf("Error: incorrect NAF value.\n");
MP_CHECKOK(mp_toradix(&k, s, 16));
printf("NAF value %s\n", s);
MP_CHECKOK(mp_toradix(scalar, s, 16));
printf("original value %s\n", s);
goto CLEANUP;
}
/* Verify digits of representation are valid */
for (i = 0; i <= BITSIZE; i++) {
if (naf[i] % 2 == 0 && naf[i] != 0) {
printf("Error: Even non-zero digit found.\n");
goto CLEANUP;
}
if (naf[i] < -(ec_twoTo(w - 1)) || naf[i] >= ec_twoTo(w - 1)) {
printf("Error: Magnitude of naf digit too large.\n");
goto CLEANUP;
}
}
/* Verify sparsity of representation */
count = w - 1;
for (i = 0; i <= BITSIZE; i++) {
if (naf[i] != 0) {
if (count < w - 1) {
printf("Error: Sparsity failed.\n");
goto CLEANUP;
}
count = 0;
} else
count++;
}
/* Check timing */
M_TimeOperation(ec_compute_wNAF(naf, BITSIZE, scalar, w), 10000);
printf("Test passed.\n");
CLEANUP:
ECGroup_free(group);
return MP_OKAY;
}

View file

@ -1,409 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mpi.h"
#include "mplogic.h"
#include "mpprime.h"
#include "ecl.h"
#include "ecl-curve.h"
#include "ecp.h"
#include <stdio.h>
#include <strings.h>
#include <assert.h>
#include <time.h>
#include <sys/time.h>
#include <sys/resource.h>
/* Time k repetitions of operation op. */
#define M_TimeOperation(op, k) \
{ \
double dStart, dNow, dUserTime; \
struct rusage ru; \
int i; \
getrusage(RUSAGE_SELF, &ru); \
dStart = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
for (i = 0; i < k; i++) { \
{ \
op; \
} \
}; \
getrusage(RUSAGE_SELF, &ru); \
dNow = (double)ru.ru_utime.tv_sec + (double)ru.ru_utime.tv_usec * 0.000001; \
dUserTime = dNow - dStart; \
if (dUserTime) \
printf(" %-45s k: %6i, t: %6.2f sec\n", #op, k, dUserTime); \
}
/* Test curve using generic field arithmetic. */
#define ECTEST_GENERIC_GFP(name_c, name) \
printf("Testing %s using generic implementation...\n", name_c); \
params = EC_GetNamedCurveParams(name); \
if (params == NULL) { \
printf(" Error: could not construct params.\n"); \
res = MP_NO; \
goto CLEANUP; \
} \
ECGroup_free(group); \
group = ECGroup_fromHex(params); \
if (group == NULL) { \
printf(" Error: could not construct group.\n"); \
res = MP_NO; \
goto CLEANUP; \
} \
MP_CHECKOK(ectest_curve_GFp(group, ectestPrint, ectestTime, 1)); \
printf("... okay.\n");
/* Test curve using specific field arithmetic. */
#define ECTEST_NAMED_GFP(name_c, name) \
printf("Testing %s using specific implementation...\n", name_c); \
ECGroup_free(group); \
group = ECGroup_fromName(name); \
if (group == NULL) { \
printf(" Warning: could not construct group.\n"); \
printf("... failed; continuing with remaining tests.\n"); \
} else { \
MP_CHECKOK(ectest_curve_GFp(group, ectestPrint, ectestTime, 0)); \
printf("... okay.\n"); \
}
/* Performs basic tests of elliptic curve cryptography over prime fields.
* If tests fail, then it prints an error message, aborts, and returns an
* error code. Otherwise, returns 0. */
int
ectest_curve_GFp(ECGroup *group, int ectestPrint, int ectestTime,
int generic)
{
mp_int one, order_1, gx, gy, rx, ry, n;
int size;
mp_err res;
char s[1000];
/* initialize values */
MP_CHECKOK(mp_init(&one));
MP_CHECKOK(mp_init(&order_1));
MP_CHECKOK(mp_init(&gx));
MP_CHECKOK(mp_init(&gy));
MP_CHECKOK(mp_init(&rx));
MP_CHECKOK(mp_init(&ry));
MP_CHECKOK(mp_init(&n));
MP_CHECKOK(mp_set_int(&one, 1));
MP_CHECKOK(mp_sub(&group->order, &one, &order_1));
/* encode base point */
if (group->meth->field_dec) {
MP_CHECKOK(group->meth->field_dec(&group->genx, &gx, group->meth));
MP_CHECKOK(group->meth->field_dec(&group->geny, &gy, group->meth));
} else {
MP_CHECKOK(mp_copy(&group->genx, &gx));
MP_CHECKOK(mp_copy(&group->geny, &gy));
}
if (ectestPrint) {
/* output base point */
printf(" base point P:\n");
MP_CHECKOK(mp_toradix(&gx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&gy, s, 16));
printf(" %s\n", s);
if (group->meth->field_enc) {
printf(" base point P (encoded):\n");
MP_CHECKOK(mp_toradix(&group->genx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&group->geny, s, 16));
printf(" %s\n", s);
}
}
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
/* multiply base point by order - 1 and check for negative of base
* point */
MP_CHECKOK(ec_GFp_pt_mul_aff(&order_1, &group->genx, &group->geny, &rx, &ry, group));
if (ectestPrint) {
printf(" (order-1)*P (affine):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
printf(" Error: invalid result (expected (- base point)).\n");
res = MP_NO;
goto CLEANUP;
}
#endif
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
/* multiply base point by order - 1 and check for negative of base
* point */
MP_CHECKOK(ec_GFp_pt_mul_jac(&order_1, &group->genx, &group->geny, &rx, &ry, group));
if (ectestPrint) {
printf(" (order-1)*P (jacobian):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
MP_CHECKOK(group->meth->field_neg(&ry, &ry, group->meth));
if ((mp_cmp(&rx, &group->genx) != 0) || (mp_cmp(&ry, &group->geny) != 0)) {
printf(" Error: invalid result (expected (- base point)).\n");
res = MP_NO;
goto CLEANUP;
}
#endif
/* multiply base point by order - 1 and check for negative of base
* point */
MP_CHECKOK(ECPoint_mul(group, &order_1, NULL, NULL, &rx, &ry));
if (ectestPrint) {
printf(" (order-1)*P (ECPoint_mul):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
printf(" Error: invalid result (expected (- base point)).\n");
res = MP_NO;
goto CLEANUP;
}
/* multiply base point by order - 1 and check for negative of base
* point */
MP_CHECKOK(ECPoint_mul(group, &order_1, &gx, &gy, &rx, &ry));
if (ectestPrint) {
printf(" (order-1)*P (ECPoint_mul):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
printf(" Error: invalid result (expected (- base point)).\n");
res = MP_NO;
goto CLEANUP;
}
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
/* multiply base point by order and check for point at infinity */
MP_CHECKOK(ec_GFp_pt_mul_aff(&group->order, &group->genx, &group->geny, &rx, &ry,
group));
if (ectestPrint) {
printf(" (order)*P (affine):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
printf(" Error: invalid result (expected point at infinity).\n");
res = MP_NO;
goto CLEANUP;
}
#endif
#ifdef ECL_ENABLE_GFP_PT_MUL_JAC
/* multiply base point by order and check for point at infinity */
MP_CHECKOK(ec_GFp_pt_mul_jac(&group->order, &group->genx, &group->geny, &rx, &ry,
group));
if (ectestPrint) {
printf(" (order)*P (jacobian):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
printf(" Error: invalid result (expected point at infinity).\n");
res = MP_NO;
goto CLEANUP;
}
#endif
/* multiply base point by order and check for point at infinity */
MP_CHECKOK(ECPoint_mul(group, &group->order, NULL, NULL, &rx, &ry));
if (ectestPrint) {
printf(" (order)*P (ECPoint_mul):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
printf(" Error: invalid result (expected point at infinity).\n");
res = MP_NO;
goto CLEANUP;
}
/* multiply base point by order and check for point at infinity */
MP_CHECKOK(ECPoint_mul(group, &group->order, &gx, &gy, &rx, &ry));
if (ectestPrint) {
printf(" (order)*P (ECPoint_mul):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
if (ec_GFp_pt_is_inf_aff(&rx, &ry) != MP_YES) {
printf(" Error: invalid result (expected point at infinity).\n");
res = MP_NO;
goto CLEANUP;
}
/* check that (order-1)P + (order-1)P + P == (order-1)P */
MP_CHECKOK(ECPoints_mul(group, &order_1, &order_1, &gx, &gy, &rx, &ry));
MP_CHECKOK(ECPoints_mul(group, &one, &one, &rx, &ry, &rx, &ry));
if (ectestPrint) {
printf(" (order-1)*P + (order-1)*P + P == (order-1)*P (ECPoints_mul):\n");
MP_CHECKOK(mp_toradix(&rx, s, 16));
printf(" %s\n", s);
MP_CHECKOK(mp_toradix(&ry, s, 16));
printf(" %s\n", s);
}
MP_CHECKOK(mp_submod(&group->meth->irr, &ry, &group->meth->irr, &ry));
if ((mp_cmp(&rx, &gx) != 0) || (mp_cmp(&ry, &gy) != 0)) {
printf(" Error: invalid result (expected (- base point)).\n");
res = MP_NO;
goto CLEANUP;
}
/* test validate_point function */
if (ECPoint_validate(group, &gx, &gy) != MP_YES) {
printf(" Error: validate point on base point failed.\n");
res = MP_NO;
goto CLEANUP;
}
MP_CHECKOK(mp_add_d(&gy, 1, &ry));
if (ECPoint_validate(group, &gx, &ry) != MP_NO) {
printf(" Error: validate point on invalid point passed.\n");
res = MP_NO;
goto CLEANUP;
}
if (ectestTime) {
/* compute random scalar */
size = mpl_significant_bits(&group->meth->irr);
if (size < MP_OKAY) {
goto CLEANUP;
}
MP_CHECKOK(mpp_random_size(&n, (size + ECL_BITS - 1) / ECL_BITS));
MP_CHECKOK(group->meth->field_mod(&n, &n, group->meth));
/* timed test */
if (generic) {
#ifdef ECL_ENABLE_GFP_PT_MUL_AFF
M_TimeOperation(MP_CHECKOK(ec_GFp_pt_mul_aff(&n, &group->genx, &group->geny, &rx, &ry,
group)),
100);
#endif
M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
100);
M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
} else {
M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, NULL, NULL, &rx, &ry)),
100);
M_TimeOperation(MP_CHECKOK(ECPoint_mul(group, &n, &gx, &gy, &rx, &ry)),
100);
M_TimeOperation(MP_CHECKOK(ECPoints_mul(group, &n, &n, &gx, &gy, &rx, &ry)), 100);
}
}
CLEANUP:
mp_clear(&one);
mp_clear(&order_1);
mp_clear(&gx);
mp_clear(&gy);
mp_clear(&rx);
mp_clear(&ry);
mp_clear(&n);
if (res != MP_OKAY) {
printf(" Error: exiting with error value %i\n", res);
}
return res;
}
/* Prints help information. */
void
printUsage()
{
printf("Usage: ecp_test [--print] [--time]\n");
printf(" --print Print out results of each point arithmetic test.\n");
printf(" --time Benchmark point operations and print results.\n");
}
/* Performs tests of elliptic curve cryptography over prime fields If
* tests fail, then it prints an error message, aborts, and returns an
* error code. Otherwise, returns 0. */
int
main(int argv, char **argc)
{
int ectestTime = 0;
int ectestPrint = 0;
int i;
ECGroup *group = NULL;
ECCurveParams *params = NULL;
mp_err res;
/* read command-line arguments */
for (i = 1; i < argv; i++) {
if ((strcasecmp(argc[i], "time") == 0) || (strcasecmp(argc[i], "-time") == 0) || (strcasecmp(argc[i], "--time") == 0)) {
ectestTime = 1;
} else if ((strcasecmp(argc[i], "print") == 0) || (strcasecmp(argc[i], "-print") == 0) || (strcasecmp(argc[i], "--print") == 0)) {
ectestPrint = 1;
} else {
printUsage();
return 0;
}
}
/* generic arithmetic tests */
ECTEST_GENERIC_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
/* specific arithmetic tests */
ECTEST_NAMED_GFP("NIST-P192", ECCurve_NIST_P192);
ECTEST_NAMED_GFP("NIST-P224", ECCurve_NIST_P224);
ECTEST_NAMED_GFP("NIST-P256", ECCurve_NIST_P256);
ECTEST_NAMED_GFP("NIST-P384", ECCurve_NIST_P384);
ECTEST_NAMED_GFP("NIST-P521", ECCurve_NIST_P521);
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v1", ECCurve_X9_62_PRIME_192V1);
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v2", ECCurve_X9_62_PRIME_192V2);
ECTEST_NAMED_GFP("ANSI X9.62 PRIME192v3", ECCurve_X9_62_PRIME_192V3);
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v1", ECCurve_X9_62_PRIME_239V1);
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v2", ECCurve_X9_62_PRIME_239V2);
ECTEST_NAMED_GFP("ANSI X9.62 PRIME239v3", ECCurve_X9_62_PRIME_239V3);
ECTEST_NAMED_GFP("ANSI X9.62 PRIME256v1", ECCurve_X9_62_PRIME_256V1);
ECTEST_NAMED_GFP("SECP-112R1", ECCurve_SECG_PRIME_112R1);
ECTEST_NAMED_GFP("SECP-112R2", ECCurve_SECG_PRIME_112R2);
ECTEST_NAMED_GFP("SECP-128R1", ECCurve_SECG_PRIME_128R1);
ECTEST_NAMED_GFP("SECP-128R2", ECCurve_SECG_PRIME_128R2);
ECTEST_NAMED_GFP("SECP-160K1", ECCurve_SECG_PRIME_160K1);
ECTEST_NAMED_GFP("SECP-160R1", ECCurve_SECG_PRIME_160R1);
ECTEST_NAMED_GFP("SECP-160R2", ECCurve_SECG_PRIME_160R2);
ECTEST_NAMED_GFP("SECP-192K1", ECCurve_SECG_PRIME_192K1);
ECTEST_NAMED_GFP("SECP-192R1", ECCurve_SECG_PRIME_192R1);
ECTEST_NAMED_GFP("SECP-224K1", ECCurve_SECG_PRIME_224K1);
ECTEST_NAMED_GFP("SECP-224R1", ECCurve_SECG_PRIME_224R1);
ECTEST_NAMED_GFP("SECP-256K1", ECCurve_SECG_PRIME_256K1);
ECTEST_NAMED_GFP("SECP-256R1", ECCurve_SECG_PRIME_256R1);
ECTEST_NAMED_GFP("SECP-384R1", ECCurve_SECG_PRIME_384R1);
ECTEST_NAMED_GFP("SECP-521R1", ECCurve_SECG_PRIME_521R1);
ECTEST_NAMED_GFP("WTLS-6 (112)", ECCurve_WTLS_6);
ECTEST_NAMED_GFP("WTLS-7 (160)", ECCurve_WTLS_7);
ECTEST_NAMED_GFP("WTLS-8 (112)", ECCurve_WTLS_8);
ECTEST_NAMED_GFP("WTLS-9 (160)", ECCurve_WTLS_9);
ECTEST_NAMED_GFP("WTLS-12 (224)", ECCurve_WTLS_12);
ECTEST_NAMED_GFP("Curve25519", ECCurve25519);
CLEANUP:
EC_FreeCurveParams(params);
ECGroup_free(group);
if (res != MP_OKAY) {
printf("Error: exiting with error value %i\n", res);
}
return res;
}

View file

@ -31,6 +31,9 @@ init128x(uint64_t x)
return ret;
}
#define CONSTANT_TIME_CARRY(a, b) \
((a ^ ((a ^ b) | ((a - b) ^ b))) >> (sizeof(a) * 8 - 1))
/* arithmetic */
uint128_t
@ -38,7 +41,7 @@ add128(uint128_t a, uint128_t b)
{
uint128_t ret;
ret.lo = a.lo + b.lo;
ret.hi = a.hi + b.hi + (ret.lo < b.lo);
ret.hi = a.hi + b.hi + CONSTANT_TIME_CARRY(ret.lo, b.lo);
return ret;
}

View file

@ -33,6 +33,7 @@
'ec.h',
'ecl/ecl-curve.h',
'ecl/ecl.h',
'ecl/eclt.h',
'hmacct.h',
'secmpi.h',
'secrng.h'

View file

@ -1707,7 +1707,7 @@ BL_FIPSEntryOK(PRBool freebl_only)
return SECSuccess;
}
/* standalone freebl can initialize */
if (freebl_only & self_tests_freebl_success) {
if (freebl_only && self_tests_freebl_success) {
return SECSuccess;
}
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);

View file

@ -32,121 +32,55 @@
'<(DEPTH)/exports.gyp:nss_exports'
]
},
# For test builds, build a static freebl library so we can statically
# link it into the test build binary. This way we don't have to
# dlopen() the shared lib but can directly call freebl functions.
{
'target_name': '<(freebl_name)',
'type': 'shared_library',
'sources': [
'aeskeywrap.c',
'alg2268.c',
'alghmac.c',
'arcfive.c',
'arcfour.c',
'camellia.c',
'chacha20poly1305.c',
'ctr.c',
'cts.c',
'des.c',
'desblapi.c',
'dh.c',
'drbg.c',
'dsa.c',
'ec.c',
'ecdecode.c',
'ecl/ec_naf.c',
'ecl/ecl.c',
'ecl/ecl_curve.c',
'ecl/ecl_gf.c',
'ecl/ecl_mult.c',
'ecl/ecp_25519.c',
'ecl/ecp_256.c',
'ecl/ecp_256_32.c',
'ecl/ecp_384.c',
'ecl/ecp_521.c',
'ecl/ecp_aff.c',
'ecl/ecp_jac.c',
'ecl/ecp_jm.c',
'ecl/ecp_mont.c',
'fipsfreebl.c',
'freeblver.c',
'gcm.c',
'hmacct.c',
'jpake.c',
'ldvector.c',
'md2.c',
'md5.c',
'mpi/mp_gf2m.c',
'mpi/mpcpucache.c',
'mpi/mpi.c',
'mpi/mplogic.c',
'mpi/mpmontg.c',
'mpi/mpprime.c',
'pqg.c',
'rawhash.c',
'rijndael.c',
'rsa.c',
'rsapkcs.c',
'seed.c',
'sha512.c',
'sha_fast.c',
'shvfy.c',
'sysrand.c',
'tlsprfalg.c'
'target_name': 'freebl_static',
'type': 'static_library',
'includes': [
'freebl_base.gypi',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
],
'conditions': [
[ 'OS=="linux"', {
'sources': [
'nsslowhash.c',
'stubs.c',
'defines!': [
'FREEBL_NO_DEPEND',
'FREEBL_LOWHASH',
'USE_HW_AES',
'INTEL_GCM',
],
'conditions': [
[ 'test_build==1', {
'dependencies': [
'<(DEPTH)/lib/util/util.gyp:nssutil3',
],
}],
[ 'target_arch=="x64"', {
'sources': [
'arcfour-amd64-gas.s',
# The AES assembler code doesn't work in static test builds.
# The linker complains about non-relocatable code, and I
# currently don't know how to fix this properly.
'sources!': [
'intel-aes.s',
'intel-gcm.s',
'mpi/mpi_amd64.c',
'mpi/mpi_amd64_gas.s',
'mpi/mp_comba.c',
],
'dependencies': [
'intel-gcm-wrap_c_lib',
],
'conditions': [
[ 'cc_is_clang==1', {
'cflags': [
'-no-integrated-as',
],
'cflags_mozilla': [
'-no-integrated-as',
],
'asflags_mozilla': [
'-no-integrated-as',
],
}],
],
}],
[ 'target_arch=="ia32"', {
'sources': [
'mpi/mpi_x86.s',
],
}],
[ 'target_arch=="arm"', {
'sources': [
'mpi/mpi_arm.c',
],
}],
],
}, {
# not Linux
}],
],
},
{
'target_name': '<(freebl_name)',
'type': 'shared_library',
'includes': [
'freebl_base.gypi',
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
],
'conditions': [
[ 'OS!="linux" and OS!="android"', {
'conditions': [
[ 'moz_fold_libs==0', {
'dependencies': [
'../util/util.gyp:nssutil3',
'<(DEPTH)/lib/util/util.gyp:nssutil3',
],
}, {
'libraries': [
@ -154,96 +88,22 @@
],
}],
],
}, 'target_arch=="x64"', {
'dependencies': [
'intel-gcm-wrap_c_lib',
],
}],
[ 'OS=="win"', {
[ 'OS=="win" and cc_is_clang==1', {
'dependencies': [
'intel-gcm-wrap_c_lib',
],
}],
[ 'OS=="linux"', {
'sources': [
#TODO: building with mingw should not need this.
'ecl/uint128.c',
#TODO: clang-cl needs -msse3 here
'intel-gcm-wrap.c',
],
'libraries': [
'advapi32.lib',
],
'conditions': [
[ 'target_arch=="x64"', {
'sources': [
'arcfour-amd64-masm.asm',
'mpi/mpi_amd64.c',
'mpi/mpi_amd64_masm.asm',
'mpi/mp_comba_amd64_masm.asm',
'intel-aes-x64-masm.asm',
'intel-gcm-x64-masm.asm',
],
}, {
# not x64
'sources': [
'mpi/mpi_x86_asm.c',
'intel-aes-x86-masm.asm',
'intel-gcm-x86-masm.asm',
],
}],
'nsslowhash.c',
'stubs.c',
],
}],
['target_arch=="ia32" or target_arch=="x64"', {
'sources': [
# All intel architectures get the 64 bit version
'ecl/curve25519_64.c',
],
}, {
'sources': [
# All non intel architectures get the generic 32 bit implementation (slow!)
'ecl/curve25519_32.c',
],
}],
#TODO uint128.c
[ 'disable_chachapoly==0', {
'conditions': [
[ 'OS!="win" and target_arch=="x64"', {
'sources': [
'chacha20_vec.c',
'poly1305-donna-x64-sse2-incremental-source.c',
],
}, {
# not x64
'sources': [
'chacha20.c',
'poly1305.c',
],
}],
],
}],
[ 'fuzz==1', {
'sources': [
'det_rng.c',
],
'defines': [
'UNSAFE_FUZZER_MODE',
],
}],
[ 'test_build==1', {
'defines': [
'CT_VERIF',
],
}],
[ 'OS=="mac"', {
'conditions': [
[ 'target_arch=="ia32"', {
'sources': [
'mpi/mpi_sse2.s',
],
'defines': [
'MP_USE_UINT_DIGIT',
'MP_ASSEMBLY_MULTIPLY',
'MP_ASSEMBLY_SQUARE',
'MP_ASSEMBLY_DIV_2DX1D',
],
}],
],
}],
],
'dependencies': [
'<(DEPTH)/exports.gyp:nss_exports',
],
'variables': {
'conditions': [
@ -254,9 +114,6 @@
}],
]
},
'ldflags': [
'-Wl,-Bsymbolic'
]
},
],
'conditions': [
@ -296,13 +153,27 @@
'MP_API_COMPATIBLE'
],
'conditions': [
[ 'target_arch=="ia32" or target_arch=="x64"', {
'cflags_mozilla': [
'-mpclmul',
'-maes',
],
}],
[ 'OS=="mac"', {
'xcode_settings': {
# I'm not sure since when this is supported.
# But I hope that doesn't matter. We also assume this is x86/x64.
'OTHER_CFLAGS': [
'-mpclmul',
'-maes',
],
},
}],
[ 'OS=="win" and target_arch=="ia32"', {
'msvs_settings': {
'VCCLCompilerTool': {
#TODO: -Ox optimize flags
'PreprocessorDefinitions': [
'NSS_X86_OR_X64',
'NSS_X86',
'MP_ASSEMBLY_MULTIPLY',
'MP_ASSEMBLY_SQUARE',
'MP_ASSEMBLY_DIV_2DX1D',
@ -319,9 +190,7 @@
'VCCLCompilerTool': {
#TODO: -Ox optimize flags
'PreprocessorDefinitions': [
'NSS_USE_64',
'NSS_X86_OR_X64',
'NSS_X64',
# Should be copied to mingw defines below
'MP_IS_LITTLE_ENDIAN',
'NSS_BEVAND_ARCFOUR',
'MPI_AMD64',
@ -333,13 +202,21 @@
},
},
}],
[ 'cc_use_gnu_ld==1 and OS=="win" and target_arch=="x64"', {
'defines': [
'MP_IS_LITTLE_ENDIAN',
'NSS_BEVAND_ARCFOUR',
'MPI_AMD64',
'MP_ASSEMBLY_MULTIPLY',
'NSS_USE_COMBA',
'USE_HW_AES',
'INTEL_GCM',
],
}],
[ 'OS!="win"', {
'conditions': [
[ 'target_arch=="x64"', {
[ 'target_arch=="x64" or target_arch=="arm64" or target_arch=="aarch64"', {
'defines': [
'NSS_USE_64',
'NSS_X86_OR_X64',
'NSS_X64',
# The Makefile does version-tests on GCC, but we're not doing that here.
'HAVE_INT128_SUPPORT',
],
@ -348,24 +225,16 @@
'ecl/uint128.c',
],
}],
[ 'target_arch=="ia32"', {
'defines': [
'NSS_X86_OR_X64',
'NSS_X86',
],
}],
],
}],
[ 'OS=="linux"', {
'defines': [
'FREEBL_LOWHASH',
'FREEBL_NO_DEPEND',
],
}],
[ 'OS=="linux" or OS=="android"', {
'conditions': [
[ 'test_build==0', {
'defines': [
'FREEBL_NO_DEPEND',
],
}],
[ 'target_arch=="x64"', {
'defines': [
'MP_IS_LITTLE_ENDIAN',
@ -375,7 +244,7 @@
'NSS_USE_COMBA',
],
}],
[ 'target_arch=="x64" and use_msan==0', {
[ 'target_arch=="x64"', {
'defines': [
'USE_HW_AES',
'INTEL_GCM',
@ -390,12 +259,21 @@
'MP_USE_UINT_DIGIT',
],
}],
[ 'target_arch=="ia32" or target_arch=="x64"', {
'cflags': [
# enable isa option for pclmul am aes-ni; supported since gcc 4.4
# This is only support by x84/x64. It's not needed for Windows.
'-mpclmul',
'-maes',
],
}],
[ 'target_arch=="arm"', {
'defines': [
'MP_ASSEMBLY_MULTIPLY',
'MP_ASSEMBLY_SQUARE',
'MP_USE_UINT_DIGIT',
'SHA_NO_LONG_LONG',
'ARMHF',
],
}],
],

View file

@ -0,0 +1,201 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
{
'sources': [
'aeskeywrap.c',
'alg2268.c',
'alghmac.c',
'arcfive.c',
'arcfour.c',
'camellia.c',
'chacha20poly1305.c',
'ctr.c',
'cts.c',
'des.c',
'desblapi.c',
'dh.c',
'drbg.c',
'dsa.c',
'ec.c',
'ecdecode.c',
'ecl/ec_naf.c',
'ecl/ecl.c',
'ecl/ecl_gf.c',
'ecl/ecl_mult.c',
'ecl/ecp_25519.c',
'ecl/ecp_256.c',
'ecl/ecp_256_32.c',
'ecl/ecp_384.c',
'ecl/ecp_521.c',
'ecl/ecp_aff.c',
'ecl/ecp_jac.c',
'ecl/ecp_jm.c',
'ecl/ecp_mont.c',
'fipsfreebl.c',
'blinit.c',
'freeblver.c',
'gcm.c',
'hmacct.c',
'jpake.c',
'ldvector.c',
'md2.c',
'md5.c',
'mpi/mp_gf2m.c',
'mpi/mpcpucache.c',
'mpi/mpi.c',
'mpi/mplogic.c',
'mpi/mpmontg.c',
'mpi/mpprime.c',
'pqg.c',
'rawhash.c',
'rijndael.c',
'rsa.c',
'rsapkcs.c',
'seed.c',
'sha512.c',
'sha_fast.c',
'shvfy.c',
'sysrand.c',
'tlsprfalg.c'
],
'conditions': [
[ 'OS=="linux" or OS=="android"', {
'conditions': [
[ 'target_arch=="x64"', {
'sources': [
'arcfour-amd64-gas.s',
'intel-aes.s',
'intel-gcm.s',
'mpi/mpi_amd64.c',
'mpi/mpi_amd64_gas.s',
'mpi/mp_comba.c',
],
'conditions': [
[ 'cc_is_clang==1', {
'cflags': [
'-no-integrated-as',
],
'cflags_mozilla': [
'-no-integrated-as',
],
'asflags_mozilla': [
'-no-integrated-as',
],
}],
],
}],
[ 'target_arch=="ia32"', {
'sources': [
'mpi/mpi_x86.s',
],
}],
[ 'target_arch=="arm"', {
'sources': [
'mpi/mpi_arm.c',
],
}],
],
}],
[ 'OS=="win"', {
'sources': [
#TODO: building with mingw should not need this.
'ecl/uint128.c',
],
'libraries': [
'advapi32.lib',
],
'conditions': [
[ 'cc_use_gnu_ld!=1 and target_arch=="x64"', {
'sources': [
'arcfour-amd64-masm.asm',
'mpi/mpi_amd64.c',
'mpi/mpi_amd64_masm.asm',
'mpi/mp_comba_amd64_masm.asm',
'intel-aes-x64-masm.asm',
'intel-gcm-x64-masm.asm',
],
}],
[ 'cc_use_gnu_ld!=1 and target_arch!="x64"', {
# not x64
'sources': [
'mpi/mpi_x86_asm.c',
'intel-aes-x86-masm.asm',
'intel-gcm-x86-masm.asm',
],
}],
[ 'cc_is_clang!=1', {
# MSVC
'sources': [
'intel-gcm-wrap.c',
],
}],
],
}],
['target_arch=="ia32" or target_arch=="x64"', {
'sources': [
# All intel architectures get the 64 bit version
'ecl/curve25519_64.c',
],
}, {
'sources': [
# All non intel architectures get the generic 32 bit implementation (slow!)
'ecl/curve25519_32.c',
],
}],
#TODO uint128.c
[ 'disable_chachapoly==0', {
'conditions': [
[ 'OS!="win" and target_arch=="x64"', {
'sources': [
'chacha20_vec.c',
'poly1305-donna-x64-sse2-incremental-source.c',
],
}, {
# not x64
'sources': [
'chacha20.c',
'poly1305.c',
],
}],
],
}],
[ 'fuzz==1', {
'sources!': [ 'drbg.c' ],
'sources': [ 'det_rng.c' ],
}],
[ 'fuzz_tls==1', {
'defines': [
'UNSAFE_FUZZER_MODE',
],
}],
[ 'ct_verif==1', {
'defines': [
'CT_VERIF',
],
}],
[ 'only_dev_random==1', {
'defines': [
'SEED_ONLY_DEV_URANDOM',
]
}],
[ 'OS=="mac"', {
'conditions': [
[ 'target_arch=="ia32"', {
'sources': [
'mpi/mpi_sse2.s',
],
'defines': [
'MP_USE_UINT_DIGIT',
'MP_ASSEMBLY_MULTIPLY',
'MP_ASSEMBLY_SQUARE',
'MP_ASSEMBLY_DIV_2DX1D',
],
}],
],
}],
],
'ldflags': [
'-Wl,-Bsymbolic'
],
}

File diff suppressed because it is too large Load diff

View file

@ -6,6 +6,17 @@
#define GCM_H 1
#include "blapii.h"
#include <stdint.h>
#ifdef NSS_X86_OR_X64
#include <emmintrin.h> /* __m128i */
#endif
SEC_BEGIN_PROTOS
#ifdef HAVE_INT128_SUPPORT
typedef unsigned __int128 uint128_t;
#endif
typedef struct GCMContextStr GCMContext;
@ -17,7 +28,7 @@ typedef struct GCMContextStr GCMContext;
* The cipher argument is a block cipher in the ECB encrypt mode.
*/
GCMContext *GCM_CreateContext(void *context, freeblCipherFunc cipher,
const unsigned char *params, unsigned int blocksize);
const unsigned char *params);
void GCM_DestroyContext(GCMContext *gcm, PRBool freeit);
SECStatus GCM_EncryptUpdate(GCMContext *gcm, unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout,
@ -28,4 +39,34 @@ SECStatus GCM_DecryptUpdate(GCMContext *gcm, unsigned char *outbuf,
const unsigned char *inbuf, unsigned int inlen,
unsigned int blocksize);
/* These functions are here only so we can test them */
#define GCM_HASH_LEN_LEN 8 /* gcm hash defines lengths to be 64 bits */
typedef struct gcmHashContextStr gcmHashContext;
typedef SECStatus (*ghash_t)(gcmHashContext *, const unsigned char *,
unsigned int);
pre_align struct gcmHashContextStr {
#ifdef NSS_X86_OR_X64
__m128i x, h;
#endif
uint64_t x_low, x_high, h_high, h_low;
unsigned char buffer[MAX_BLOCK_SIZE];
unsigned int bufLen;
uint8_t counterBuf[16];
uint64_t cLen;
ghash_t ghash_mul;
PRBool hw;
gcmHashContext *mem;
} post_align;
SECStatus gcmHash_Update(gcmHashContext *ghash, const unsigned char *buf,
unsigned int len);
SECStatus gcmHash_InitContext(gcmHashContext *ghash, const unsigned char *H,
PRBool sw);
SECStatus gcmHash_Reset(gcmHashContext *ghash, const unsigned char *AAD,
unsigned int AADLen);
SECStatus gcmHash_Final(gcmHashContext *ghash, unsigned char *outbuf,
unsigned int *outlen, unsigned int maxout);
SEC_END_PROTOS
#endif

View file

@ -91,8 +91,6 @@ LOCAL bail
movdqu [rsp + 1*16], xmm7
movdqu [rsp + 2*16], xmm8
lea ctx, [48+ctx]
loop8:
cmp inputLen, 8*16
jb loop1
@ -555,9 +553,7 @@ LOCAL bail
movdqu [rsp + 1*16], xmm7
movdqu [rsp + 2*16], xmm8
lea ctx, [48+ctx]
movdqu xmm0, [-32+ctx]
movdqu xmm0, [256+ctx]
movdqu xmm2, [0*16 + ctx]
movdqu xmm3, [1*16 + ctx]
@ -597,7 +593,7 @@ loop1:
jmp loop1
bail:
movdqu [-32+ctx], xmm0
movdqu [256+ctx], xmm0
xor rax, rax
@ -625,8 +621,6 @@ LOCAL bail
movdqu [rsp + 1*16], xmm7
movdqu [rsp + 2*16], xmm8
lea ctx, [48+ctx]
loop8:
cmp inputLen, 8*16
jb dec1
@ -657,7 +651,7 @@ loop8:
ENDM
aes_dec_last_rnd rnds
movdqu xmm8, [-32 + ctx]
movdqu xmm8, [256 + ctx]
pxor xmm0, xmm8
movdqu xmm8, [0*16 + input]
pxor xmm1, xmm8
@ -683,7 +677,7 @@ loop8:
movdqu [5*16 + output], xmm5
movdqu [6*16 + output], xmm6
movdqu [7*16 + output], xmm7
movdqu [-32 + ctx], xmm8
movdqu [256 + ctx], xmm8
lea input, [8*16 + input]
lea output, [8*16 + output]
@ -691,7 +685,7 @@ loop8:
jmp loop8
dec1:
movdqu xmm3, [-32 + ctx]
movdqu xmm3, [256 + ctx]
loop1:
cmp inputLen, 1*16
@ -721,7 +715,7 @@ loop1:
jmp loop1
bail:
movdqu [-32 + ctx], xmm3
movdqu [256 + ctx], xmm3
xor rax, rax
movdqu xmm6, [rsp + 0*16]
@ -773,7 +767,6 @@ LOCAL bail
mov ctrCtx, ctx
mov ctx, [8+ctrCtx]
lea ctx, [48+ctx]
sub rsp, 3*16
movdqu [rsp + 0*16], xmm6

View file

@ -87,8 +87,6 @@ LOCAL bail
mov input, [esp + 2*4 + 4*4]
mov inputLen, [esp + 2*4 + 5*4]
lea ctx, [44+ctx]
loop7:
cmp inputLen, 7*16
jb loop1
@ -557,9 +555,7 @@ LOCAL bail
mov input, [esp + 2*4 + 4*4]
mov inputLen, [esp + 2*4 + 5*4]
lea ctx, [44+ctx]
movdqu xmm0, [-32+ctx]
movdqu xmm0, [252+ctx]
movdqu xmm2, [0*16 + ctx]
movdqu xmm3, [1*16 + ctx]
@ -597,7 +593,7 @@ loop1:
jmp loop1
bail:
movdqu [-32+ctx], xmm0
movdqu [252+ctx], xmm0
xor eax, eax
pop inputLen
@ -619,8 +615,6 @@ LOCAL bail
mov input, [esp + 2*4 + 4*4]
mov inputLen, [esp + 2*4 + 5*4]
lea ctx, [44+ctx]
loop7:
cmp inputLen, 7*16
jb dec1
@ -649,7 +643,7 @@ loop7:
ENDM
aes_dec_last_rnd rnds
movdqu xmm7, [-32 + ctx]
movdqu xmm7, [252 + ctx]
pxor xmm0, xmm7
movdqu xmm7, [0*16 + input]
pxor xmm1, xmm7
@ -672,7 +666,7 @@ loop7:
movdqu [4*16 + output], xmm4
movdqu [5*16 + output], xmm5
movdqu [6*16 + output], xmm6
movdqu [-32 + ctx], xmm7
movdqu [252 + ctx], xmm7
lea input, [7*16 + input]
lea output, [7*16 + output]
@ -680,7 +674,7 @@ loop7:
jmp loop7
dec1:
movdqu xmm3, [-32 + ctx]
movdqu xmm3, [252 + ctx]
loop1:
cmp inputLen, 1*16
@ -710,7 +704,7 @@ loop1:
jmp loop1
bail:
movdqu [-32 + ctx], xmm3
movdqu [252 + ctx], xmm3
xor eax, eax
pop inputLen
ret
@ -769,7 +763,6 @@ LOCAL bail
mov inputLen, [esp + 4*5 + 5*4]
mov ctx, [4+ctrCtx]
lea ctx, [44+ctx]
mov ebp, esp
sub esp, 7*16

View file

@ -4,8 +4,7 @@
.text
#define IV_OFFSET 16
#define EXPANDED_KEY_OFFSET 48
#define IV_OFFSET 256
/*
* Warning: the length values used in this module are "unsigned int"
@ -144,9 +143,6 @@ key_expansion128:
.globl intel_aes_encrypt_ecb_128
.align 16
intel_aes_encrypt_ecb_128:
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
leaq 48(%rdi), %rdi
movdqu (%rdi), %xmm2
movdqu 160(%rdi), %xmm12
xor %eax, %eax
@ -328,9 +324,6 @@ intel_aes_encrypt_ecb_128:
.globl intel_aes_decrypt_ecb_128
.align 16
intel_aes_decrypt_ecb_128:
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
leaq 48(%rdi), %rdi
movdqu (%rdi), %xmm2
movdqu 160(%rdi), %xmm12
xorl %eax, %eax
@ -516,9 +509,7 @@ intel_aes_encrypt_cbc_128:
je 2f
// leaq IV_OFFSET(%rdi), %rdx
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
leaq 16(%rdi), %rdx
leaq 48(%rdi), %rdi
leaq 256(%rdi), %rdx
movdqu (%rdx), %xmm0
movdqu (%rdi), %xmm2
@ -575,9 +566,7 @@ intel_aes_encrypt_cbc_128:
.align 16
intel_aes_decrypt_cbc_128:
// leaq IV_OFFSET(%rdi), %rdx
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
leaq 16(%rdi), %rdx
leaq 48(%rdi), %rdi
leaq 256(%rdi), %rdx
movdqu (%rdx), %xmm0 /* iv */
movdqu (%rdi), %xmm2 /* first key block */
@ -902,9 +891,6 @@ key_expansion192:
.globl intel_aes_encrypt_ecb_192
.align 16
intel_aes_encrypt_ecb_192:
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
leaq 48(%rdi), %rdi
movdqu (%rdi), %xmm2
movdqu 192(%rdi), %xmm14
xorl %eax, %eax
@ -1109,9 +1095,6 @@ intel_aes_encrypt_ecb_192:
.globl intel_aes_decrypt_ecb_192
.align 16
intel_aes_decrypt_ecb_192:
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
leaq 48(%rdi), %rdi
movdqu (%rdi), %xmm2
movdqu 192(%rdi), %xmm14
xorl %eax, %eax
@ -1320,9 +1303,7 @@ intel_aes_encrypt_cbc_192:
je 2f
// leaq IV_OFFSET(%rdi), %rdx
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
leaq 16(%rdi), %rdx
leaq 48(%rdi), %rdi
leaq 256(%rdi), %rdx
movdqu (%rdx), %xmm0
movdqu (%rdi), %xmm2
@ -1382,8 +1363,8 @@ intel_aes_encrypt_cbc_192:
.globl intel_aes_decrypt_cbc_192
.align 16
intel_aes_decrypt_cbc_192:
leaq 16(%rdi), %rdx
leaq 48(%rdi), %rdi
// leaq IV_OFFSET(%rdi), %rdx
leaq 256(%rdi), %rdx
movdqu (%rdx), %xmm0
movdqu (%rdi), %xmm2
@ -1738,9 +1719,6 @@ key_expansion256:
.globl intel_aes_encrypt_ecb_256
.align 16
intel_aes_encrypt_ecb_256:
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
leaq 48(%rdi), %rdi
movdqu (%rdi), %xmm2
movdqu 224(%rdi), %xmm15
xorl %eax, %eax
@ -1970,9 +1948,6 @@ intel_aes_encrypt_ecb_256:
.globl intel_aes_decrypt_ecb_256
.align 16
intel_aes_decrypt_ecb_256:
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
leaq 48(%rdi), %rdi
movdqu (%rdi), %xmm2
movdqu 224(%rdi), %xmm15
xorl %eax, %eax
@ -2206,9 +2181,7 @@ intel_aes_encrypt_cbc_256:
je 2f
// leaq IV_OFFSET(%rdi), %rdx
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
leaq 16(%rdi), %rdx
leaq 48(%rdi), %rdi
leaq 256(%rdi), %rdx
movdqu (%rdx), %xmm0
movdqu (%rdi), %xmm8
@ -2274,9 +2247,7 @@ intel_aes_encrypt_cbc_256:
.align 16
intel_aes_decrypt_cbc_256:
// leaq IV_OFFSET(%rdi), %rdx
// leaq EXPANDED_KEY_OFFSET(%rdi), %rdi
leaq 16(%rdi), %rdx
leaq 48(%rdi), %rdi
leaq 256(%rdi), %rdx
movdqu (%rdx), %xmm0
movdqu (%rdi), %xmm2

View file

@ -41,8 +41,7 @@ struct intel_AES_GCMContextStr {
intel_AES_GCMContext *
intel_AES_GCM_CreateContext(void *context,
freeblCipherFunc cipher,
const unsigned char *params,
unsigned int blocksize)
const unsigned char *params)
{
intel_AES_GCMContext *gcm = NULL;
AESContext *aes = (AESContext *)context;
@ -59,12 +58,11 @@ intel_AES_GCM_CreateContext(void *context,
unsigned int j;
SECStatus rv;
if (blocksize != AES_BLOCK_SIZE) {
PORT_SetError(SEC_ERROR_LIBRARY_FAILURE);
if (gcmParams->ulIvLen == 0) {
PORT_SetError(SEC_ERROR_INVALID_ARGS);
return NULL;
}
gcm = PORT_ZNew(intel_AES_GCMContext);
if (gcm == NULL) {
return NULL;
}

View file

@ -496,8 +496,8 @@ LbeginENC:
vmovdqu CTR0, XMMWORD PTR[16*16 + 2*16 + Gctx]
vmovdqu BSWAPMASK, XMMWORD PTR[Lbswap_mask]
mov KS, [16*16 + 3*16 + Gctx]
mov NR, [4 + KS]
lea KS, [48 + KS]
mov NR, [244 + KS]
lea KS, [KS]
vpshufb CTR0, CTR0, BSWAPMASK
@ -994,8 +994,7 @@ LbeginDEC:
vmovdqu CTR0, XMMWORD PTR[16*16 + 2*16 + Gctx]
vmovdqu BSWAPMASK, XMMWORD PTR[Lbswap_mask]
mov KS, [16*16 + 3*16 + Gctx]
mov NR, [4 + KS]
lea KS, [48 + KS]
mov NR, [244 + KS]
vpshufb CTR0, CTR0, BSWAPMASK

View file

@ -390,7 +390,7 @@ Htbl textequ <edx>
Gctx textequ <edx>
len textequ <DWORD PTR[ebp + 5*4 + 3*4]>
KS textequ <esi>
NR textequ <DWORD PTR[-40 + KS]>
NR textequ <DWORD PTR[244+KS]>
aluCTR textequ <ebx>
aluTMP textequ <edi>
@ -463,7 +463,6 @@ LbeginENC:
mov Gctx, [ebp + 5*4 + 2*4]
mov KS, [16*16 + 3*16 + Gctx]
lea KS, [44 + KS]
mov aluCTR, [16*16 + 2*16 + 3*4 + Gctx]
bswap aluCTR
@ -931,7 +930,6 @@ LbeginDEC:
mov Gctx, [ebp + 5*4 + 2*4]
mov KS, [16*16 + 3*16 + Gctx]
lea KS, [44 + KS]
mov aluCTR, [16*16 + 2*16 + 3*4 + Gctx]
bswap aluCTR

View file

@ -27,7 +27,7 @@
typedef struct intel_AES_GCMContextStr intel_AES_GCMContext;
intel_AES_GCMContext *intel_AES_GCM_CreateContext(void *context, freeblCipherFunc cipher,
const unsigned char *params, unsigned int blocksize);
const unsigned char *params);
void intel_AES_GCM_DestroyContext(intel_AES_GCMContext *gcm, PRBool freeit);

View file

@ -467,8 +467,8 @@ intel_aes_gcmENC:
vmovdqu 288(Gctx), CTR
vmovdqu 272(Gctx), T
mov 304(Gctx), KS
mov 4(KS), NR
lea 48(KS), KS
# AESContext->Nr
mov 244(KS), NR
vpshufb .Lbswap_mask(%rip), CTR, CTR
vpshufb .Lbswap_mask(%rip), T, T
@ -1001,8 +1001,8 @@ intel_aes_gcmDEC:
vmovdqu 288(Gctx), CTR
vmovdqu 272(Gctx), T
mov 304(Gctx), KS
mov 4(KS), NR
lea 48(KS), KS
# AESContext->Nr
mov 244(KS), NR
vpshufb .Lbswap_mask(%rip), CTR, CTR
vpshufb .Lbswap_mask(%rip), T, T

View file

@ -94,6 +94,7 @@ PRIVATE_EXPORTS = \
ec.h \
ecl.h \
ecl-curve.h \
eclt.h \
$(NULL)
MPI_HDRS = mpi-config.h mpi.h mpi-priv.h mplogic.h mpprime.h logtab.h mp_gf2m.h
@ -102,7 +103,7 @@ MPI_SRCS = mpprime.c mpmontg.c mplogic.c mpi.c mp_gf2m.c
ECL_HDRS = ecl-exp.h ecl.h ecp.h ecl-priv.h
ifndef NSS_DISABLE_ECC
ECL_SRCS = ecl.c ecl_curve.c ecl_mult.c ecl_gf.c \
ECL_SRCS = ecl.c ecl_mult.c ecl_gf.c \
ecp_aff.c ecp_jac.c ecp_mont.c \
ec_naf.c ecp_jm.c ecp_256.c ecp_384.c ecp_521.c \
ecp_256_32.c ecp_25519.c
@ -131,6 +132,7 @@ CSRCS = \
chacha20poly1305.c \
cts.c \
ctr.c \
blinit.c \
fipsfreebl.c \
gcm.c \
hmacct.c \

View file

@ -1,244 +0,0 @@
#
# Makefile for MPI library
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
## Define CC to be the C compiler you wish to use. The GNU cc
## compiler (gcc) should work, at the very least
#CC=cc
#CC=gcc
##
## Define PERL to point to your local Perl interpreter. It
## should be Perl 5.x, although it's conceivable that Perl 4
## might work ... I haven't tested it.
##
#PERL=/usr/bin/perl
#PERL=perl
include target.mk
CFLAGS+= $(XCFLAGS)
##
## Define LIBS to include any libraries you need to link against.
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
## necessary to bring in the math library. Otherwise, it can be
## left alone, unless your system has other peculiar requirements.
##
LIBS=#-lmalloc#-lefence#-lm
##
## Define RANLIB to be the library header randomizer; you might not
## need this on some systems (just set it to 'echo' on these systems,
## such as IRIX)
##
RANLIB=echo
##
## This is the version string used for the documentation and
## building the distribution tarball. Don't mess with it unless
## you are releasing a new version
VERS=1.7p6
## ----------------------------------------------------------------------
## You probably don't need to change anything below this line...
##
##
## This is the list of source files that need to be packed into
## the distribution file
SRCS= mpi.c mpprime.c mplogic.c mp_gf2m.c mpmontg.c mpi-test.c primes.c \
mpcpucache.c tests/ \
utils/gcd.c utils/invmod.c utils/lap.c \
utils/ptab.pl utils/sieve.c utils/isprime.c\
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
utils/bbsrand.c utils/prng.c utils/primegen.c \
utils/basecvt.c utils/makeprime.c\
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
utils/mpi.h utils/mpprime.h mulsqr.c \
make-test-arrays test-arrays.txt all-tests make-logtab \
types.pl stats timetest multest
## These are the header files that go into the distribution file
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h mp_gf2m.h \
mp_gf2m-priv.h utils/bbs_rand.h tests/mpi.h tests/mpprime.h
## These are the documentation files that go into the distribution file
DOCS=README doc utils/README utils/PRIMES
## This is the list of tools built by 'make tools'
TOOLS=gcd invmod isprime lap dec2hex hex2dec primegen prng \
basecvt fact exptmod pi makeprime identest
LIBOBJS = mpprime.o mpmontg.o mplogic.o mp_gf2m.o mpi.o mpcpucache.o $(AS_OBJS)
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
APPHDRS = mpi-config.h mpi.h mplogic.h mp_gf2m.h mpprime.h
help:
@ echo ""
@ echo "The following targets can be built with this Makefile:"
@ echo ""
@ echo "libmpi.a - arithmetic and prime testing library"
@ echo "mpi-test - test driver (requires MP_IOFUNC)"
@ echo "tools - command line tools"
@ echo "doc - manual pages for tools"
@ echo "clean - clean up objects and such"
@ echo "distclean - get ready for distribution"
@ echo "dist - distribution tarball"
@ echo ""
.SUFFIXES: .c .o .i
.c.i:
$(CC) $(CFLAGS) -E $< > $@
#.c.o: $*.h $*.c
# $(CC) $(CFLAGS) -c $<
#---------------------------------------
$(LIBOBJS): $(LIBHDRS)
logtab.h: make-logtab
$(PERL) make-logtab > logtab.h
mpi.o: mpi.c logtab.h $(LIBHDRS)
mplogic.o: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
mp_gf2m.o: mp_gf2m.c mpi-priv.h mp_gf2m.h mp_gf2m-priv.h $(LIBHDRS)
mpmontg.o: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
mpprime.o: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
mpcpucache.o: mpcpucache.c $(LIBHDRS)
mpi_mips.o: mpi_mips.s
$(CC) -o $@ $(ASFLAGS) -c mpi_mips.s
mpi_sparc.o : montmulf.h
mpv_sparcv9.s: vis_64.il mpv_sparc.c
$(CC) -o $@ $(SOLARIS_FPU_FLAGS) -S vis_64.il mpv_sparc.c
mpv_sparcv8.s: vis_64.il mpv_sparc.c
$(CC) -o $@ $(SOLARIS_FPU_FLAGS) -S vis_32.il mpv_sparc.c
montmulfv8.o montmulfv9.o mpv_sparcv8.o mpv_sparcv9.o : %.o : %.s
$(CC) -o $@ $(SOLARIS_ASM_FLAGS) -c $<
mpi_arm.o: mpi_arm.c $(LIBHDRS)
# This rule is used to build the .s sources, which are then hand optimized.
#montmulfv8.s montmulfv9.s : montmulf%.s : montmulf%.il montmulf.c montmulf.h
# $(CC) -o $@ $(SOLARIS_ASM_FLAGS) -S montmulf$*.il montmulf.c
libmpi.a: $(LIBOBJS)
ar -cvr libmpi.a $(LIBOBJS)
$(RANLIB) libmpi.a
lib libs: libmpi.a
mpi.i: mpi.h
#---------------------------------------
MPTESTOBJS = mptest1.o mptest2.o mptest3.o mptest3a.o mptest4.o mptest4a.o \
mptest4b.o mptest6.o mptest7.o mptest8.o mptest9.o mptestb.o
MPTESTS = $(MPTESTOBJS:.o=)
$(MPTESTOBJS): mptest%.o: tests/mptest-%.c $(LIBHDRS)
$(CC) $(CFLAGS) -o $@ -c $<
$(MPTESTS): mptest%: mptest%.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
tests: mptest1 mptest2 mptest3 mptest3a mptest4 mptest4a mptest4b mptest6 \
mptestb bbsrand
utests: mptest7 mptest8 mptest9
#---------------------------------------
EXTRAOBJS = bbsrand.o bbs_rand.o prng.o
UTILOBJS = primegen.o metime.o identest.o basecvt.o fact.o exptmod.o pi.o \
makeprime.o gcd.o invmod.o lap.o isprime.o \
dec2hex.o hex2dec.o
UTILS = $(UTILOBJS:.o=)
$(UTILS): % : %.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
$(UTILOBJS) $(EXTRAOBJS): %.o : utils/%.c $(LIBHDRS)
$(CC) $(CFLAGS) -o $@ -c $<
prng: prng.o bbs_rand.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
bbsrand: bbsrand.o bbs_rand.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
utils: $(UTILS) prng bbsrand
#---------------------------------------
test-info.c: test-arrays.txt
$(PERL) make-test-arrays test-arrays.txt > test-info.c
mpi-test.o: mpi-test.c test-info.c $(LIBHDRS)
$(CC) $(CFLAGS) -o $@ -c $<
mpi-test: mpi-test.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
mdxptest.o: mdxptest.c $(LIBHDRS) mpi-priv.h
mdxptest: mdxptest.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
mulsqr.o: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
$(CC) $(CFLAGS) -DMP_SQUARE=1 -o $@ -c mulsqr.c
mulsqr: mulsqr.o libmpi.a
$(CC) $(CFLAGS) -o $@ $^ $(LIBS)
#---------------------------------------
alltests: tests utests mpi-test
tools: $(TOOLS)
doc:
(cd doc; ./build)
clean:
rm -f *.o *.a *.i
rm -f core
rm -f *~ .*~
rm -f utils/*.o
rm -f utils/core
rm -f utils/*~ utils/.*~
clobber: clean
rm -f $(TOOLS) $(UTILS)
distclean: clean
rm -f mptest? mpi-test metime mulsqr karatsuba
rm -f mptest?a mptest?b
rm -f utils/mptest?
rm -f test-info.c logtab.h
rm -f libmpi.a
rm -f $(TOOLS)
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
pgps -ab mpi-$(VERS).tar
chmod +r mpi-$(VERS).tar.asc
gzip -9 mpi-$(VERS).tar
# END

View file

@ -1,243 +0,0 @@
#
# Makefile.win - gmake Makefile for building MPI with VACPP on OS/2
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
## Define CC to be the C compiler you wish to use. The GNU cc
## compiler (gcc) should work, at the very least
#CC=cc
#CC=gcc
CC=icc.exe
AS=alp.exe
##
## Define PERL to point to your local Perl interpreter. It
## should be Perl 5.x, although it's conceivable that Perl 4
## might work ... I haven't tested it.
##
#PERL=/usr/bin/perl
#PERL=perl
##
## Define CFLAGS to contain any local options your compiler
## setup requires.
##
## Conditional compilation options are no longer here; see
## the file 'mpi-config.h' instead.
##
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
#OS/2
AS_SRCS = mpi_x86.asm
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
#CFLAGS= -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC \
-DDEBUG -D_DEBUG -UNDEBUG -DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
#CFLAGS = -O2 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
#CFLAGS = -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
CFLAGS = /Ti+ -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
$(MPICMN)
ASFLAGS =
##
## Define LIBS to include any libraries you need to link against.
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
## necessary to bring in the math library. Otherwise, it can be
## left alone, unless your system has other peculiar requirements.
##
LIBS=#-lmalloc#-lefence#-lm
##
## Define RANLIB to be the library header randomizer; you might not
## need this on some systems (just set it to 'echo' on these systems,
## such as IRIX)
##
RANLIB=echo
##
## This is the version string used for the documentation and
## building the distribution tarball. Don't mess with it unless
## you are releasing a new version
VERS=1.7p6
## ----------------------------------------------------------------------
## You probably don't need to change anything below this line...
##
##
## This is the list of source files that need to be packed into
## the distribution file
SRCS= mpi.c mpprime.c mplogic.c mpmontg.c mpi-test.c primes.c tests/ \
utils/gcd.c utils/invmod.c utils/lap.c \
utils/ptab.pl utils/sieve.c utils/isprime.c\
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
utils/bbsrand.c utils/prng.c utils/primegen.c \
utils/basecvt.c utils/makeprime.c\
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
utils/mpi.h utils/mpprime.h mulsqr.c \
make-test-arrays test-arrays.txt all-tests make-logtab \
types.pl stats timetest multest
## These are the header files that go into the distribution file
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h \
utils/bbs_rand.h tests/mpi.h tests/mpprime.h
## These are the documentation files that go into the distribution file
DOCS=README doc utils/README utils/PRIMES
## This is the list of tools built by 'make tools'
TOOLS=gcd.exe invmod.exe isprime.exe lap.exe dec2hex.exe hex2dec.exe \
primegen.exe prng.exe basecvt.exe fact.exe exptmod.exe pi.exe makeprime.exe
AS_OBJS = $(AS_SRCS:.asm=.obj)
LIBOBJS = mpprime.obj mpmontg.obj mplogic.obj mpi.obj $(AS_OBJS)
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
APPHDRS = mpi-config.h mpi.h mplogic.h mpprime.h
help:
@ echo ""
@ echo "The following targets can be built with this Makefile:"
@ echo ""
@ echo "mpi.lib - arithmetic and prime testing library"
@ echo "mpi-test.exe - test driver (requires MP_IOFUNC)"
@ echo "tools - command line tools"
@ echo "doc - manual pages for tools"
@ echo "clean - clean up objects and such"
@ echo "distclean - get ready for distribution"
@ echo "dist - distribution tarball"
@ echo ""
.SUFFIXES: .c .obj .i .lib .exe .asm
.c.i:
$(CC) $(CFLAGS) -E $< > $@
.c.obj:
$(CC) $(CFLAGS) -c $<
.asm.obj:
$(AS) $(ASFLAGS) $<
.obj.exe:
$(CC) $(CFLAGS) -Fo$@ $<
#---------------------------------------
$(LIBOBJS): $(LIBHDRS)
logtab.h: make-logtab
$(PERL) make-logtab > logtab.h
mpi.obj: mpi.c logtab.h $(LIBHDRS)
mplogic.obj: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
mpmontg.obj: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
mpprime.obj: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
mpi_mips.obj: mpi_mips.s
$(CC) -Fo$@ $(ASFLAGS) -c mpi_mips.s
mpi.lib: $(LIBOBJS)
ilib /out:mpi.lib $(LIBOBJS)
$(RANLIB) mpi.lib
lib libs: mpi.lib
#---------------------------------------
MPTESTOBJS = mptest1.obj mptest2.obj mptest3.obj mptest3a.obj mptest4.obj \
mptest4a.obj mptest4b.obj mptest6.obj mptest7.obj mptest8.obj mptest9.obj
MPTESTS = $(MPTESTOBJS:.obj=.exe)
$(MPTESTOBJS): mptest%.obj: tests/mptest-%.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
$(MPTESTS): mptest%.exe: mptest%.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
tests: mptest1.exe mptest2.exe mptest3.exe mptest3a.exe mptest4.exe \
mptest4a.exe mptest4b.exe mptest6.exe bbsrand.exe
utests: mptest7.exe mptest8.exe mptest9.exe
#---------------------------------------
EXTRAOBJS = bbsrand.obj bbs_rand.obj prng.obj
UTILOBJS = primegen.obj metime.obj identest.obj basecvt.obj fact.obj \
exptmod.obj pi.obj makeprime.obj karatsuba.obj gcd.obj invmod.obj lap.obj \
isprime.obj dec2hex.obj hex2dec.obj
UTILS = $(UTILOBJS:.obj=.exe)
$(UTILS): %.exe : %.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
$(UTILOBJS) $(EXTRAOBJS): %.obj : utils/%.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
prng.exe: prng.obj bbs_rand.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
bbsrand.exe: bbsrand.obj bbs_rand.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
utils: $(UTILS) prng.exe bbsrand.exe
#---------------------------------------
test-info.c: test-arrays.txt
$(PERL) make-test-arrays test-arrays.txt > test-info.c
mpi-test.obj: mpi-test.c test-info.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
mpi-test.exe: mpi-test.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
mdxptest.obj: mdxptest.c $(LIBHDRS) mpi-priv.h
mdxptest.exe: mdxptest.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
mulsqr.obj: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
$(CC) $(CFLAGS) -DMP_SQUARE=1 -Fo$@ -c mulsqr.c
mulsqr.exe: mulsqr.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
#---------------------------------------
alltests: tests utests mpi-test.exe
tools: $(TOOLS)
doc:
(cd doc; ./build)
clean:
rm -f *.obj *.lib *.pdb *.ilk
cd utils; rm -f *.obj *.lib *.pdb *.ilk
distclean: clean
rm -f mptest? mpi-test metime mulsqr karatsuba
rm -f mptest?a mptest?b
rm -f utils/mptest?
rm -f test-info.c logtab.h
rm -f mpi.lib
rm -f $(TOOLS)
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
pgps -ab mpi-$(VERS).tar
chmod +r mpi-$(VERS).tar.asc
gzip -9 mpi-$(VERS).tar
print:
@echo LIBOBJS = $(LIBOBJS)
# END

View file

@ -1,254 +0,0 @@
#
# Makefile.win - gmake Makefile for building MPI with MSVC on NT
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
## Define CC to be the C compiler you wish to use. The GNU cc
## compiler (gcc) should work, at the very least
#CC=cc
#CC=gcc
CC=cl.exe
ifeq ($(CPU_ARCH),x86_64)
AS=ml64.exe
else
AS=ml.exe
endif
##
## Define PERL to point to your local Perl interpreter. It
## should be Perl 5.x, although it's conceivable that Perl 4
## might work ... I haven't tested it.
##
#PERL=/usr/bin/perl
#PERL=perl
##
## Define CFLAGS to contain any local options your compiler
## setup requires.
##
## Conditional compilation options are no longer here; see
## the file 'mpi-config.h' instead.
##
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC
ifeq ($(CPU_ARCH),x86_64)
AS_SRCS = mpi_x86_64.asm
CFLAGS = -O2 -Z7 -MD -W3 -nologo -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
-DWIN32 -D_WIN64 -D_AMD64_ -D_M_AMD64 -D_WINDOWS -DWIN95 $(MPICMN)
ASFLAGS = -Cp -Sn -Zi -I.
else
#NT
AS_SRCS = mpi_x86.asm
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
#CFLAGS= -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC \
-DDEBUG -D_DEBUG -UNDEBUG -DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
#CFLAGS = -O2 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
#CFLAGS = -Od -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
CFLAGS = -O2 -Z7 -MD -W3 -nologo -D_X86_ -DXP_PC -UDEBUG -U_DEBUG -DNDEBUG \
-DWIN32 -D_WINDOWS -DWIN95 $(MPICMN)
ASFLAGS = -Cp -Sn -Zi -coff -I.
endif
##
## Define LIBS to include any libraries you need to link against.
## If NO_TABLE is define, LIBS should include '-lm' or whatever is
## necessary to bring in the math library. Otherwise, it can be
## left alone, unless your system has other peculiar requirements.
##
LIBS=#-lmalloc#-lefence#-lm
##
## Define RANLIB to be the library header randomizer; you might not
## need this on some systems (just set it to 'echo' on these systems,
## such as IRIX)
##
RANLIB=echo
##
## This is the version string used for the documentation and
## building the distribution tarball. Don't mess with it unless
## you are releasing a new version
VERS=1.7p6
## ----------------------------------------------------------------------
## You probably don't need to change anything below this line...
##
##
## This is the list of source files that need to be packed into
## the distribution file
SRCS= mpi.c mpprime.c mplogic.c mpmontg.c mpi-test.c primes.c tests/ \
utils/gcd.c utils/invmod.c utils/lap.c \
utils/ptab.pl utils/sieve.c utils/isprime.c\
utils/dec2hex.c utils/hex2dec.c utils/bbs_rand.c \
utils/bbsrand.c utils/prng.c utils/primegen.c \
utils/basecvt.c utils/makeprime.c\
utils/fact.c utils/exptmod.c utils/pi.c utils/metime.c \
utils/mpi.h utils/mpprime.h mulsqr.c \
make-test-arrays test-arrays.txt all-tests make-logtab \
types.pl stats timetest multest
## These are the header files that go into the distribution file
HDRS=mpi.h mpi-config.h utils/mpi.h utils/mpi-config.h mpprime.h mplogic.h \
utils/bbs_rand.h tests/mpi.h tests/mpprime.h
## These are the documentation files that go into the distribution file
DOCS=README doc utils/README utils/PRIMES
## This is the list of tools built by 'make tools'
TOOLS=gcd.exe invmod.exe isprime.exe lap.exe dec2hex.exe hex2dec.exe \
primegen.exe prng.exe basecvt.exe fact.exe exptmod.exe pi.exe makeprime.exe
AS_OBJS = $(AS_SRCS:.asm=.obj)
LIBOBJS = mpprime.obj mpmontg.obj mplogic.obj mpi.obj $(AS_OBJS)
LIBHDRS = mpi-config.h mpi-priv.h mpi.h
APPHDRS = mpi-config.h mpi.h mplogic.h mpprime.h
help:
@ echo ""
@ echo "The following targets can be built with this Makefile:"
@ echo ""
@ echo "mpi.lib - arithmetic and prime testing library"
@ echo "mpi-test - test driver (requires MP_IOFUNC)"
@ echo "tools - command line tools"
@ echo "doc - manual pages for tools"
@ echo "clean - clean up objects and such"
@ echo "distclean - get ready for distribution"
@ echo "dist - distribution tarball"
@ echo ""
.SUFFIXES: .c .obj .i .lib .exe .asm
.c.i:
$(CC) $(CFLAGS) -E $< > $@
.c.obj:
$(CC) $(CFLAGS) -c $<
.asm.obj:
$(AS) $(ASFLAGS) -c $<
.obj.exe:
$(CC) $(CFLAGS) -Fo$@ $<
#---------------------------------------
$(LIBOBJS): $(LIBHDRS)
logtab.h: make-logtab
$(PERL) make-logtab > logtab.h
mpi.obj: mpi.c logtab.h $(LIBHDRS)
mplogic.obj: mplogic.c mpi-priv.h mplogic.h $(LIBHDRS)
mpmontg.obj: mpmontg.c mpi-priv.h mplogic.h mpprime.h $(LIBHDRS)
mpprime.obj: mpprime.c mpi-priv.h mpprime.h mplogic.h primes.c $(LIBHDRS)
mpi_mips.obj: mpi_mips.s
$(CC) -Fo$@ $(ASFLAGS) -c mpi_mips.s
mpi.lib: $(LIBOBJS)
ar -cvr mpi.lib $(LIBOBJS)
$(RANLIB) mpi.lib
lib libs: mpi.lib
#---------------------------------------
MPTESTOBJS = mptest1.obj mptest2.obj mptest3.obj mptest3a.obj mptest4.obj \
mptest4a.obj mptest4b.obj mptest6.obj mptest7.obj mptest8.obj mptest9.obj
MPTESTS = $(MPTESTOBJS:.obj=.exe)
$(MPTESTOBJS): mptest%.obj: tests/mptest-%.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
$(MPTESTS): mptest%.exe: mptest%.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
tests: mptest1.exe mptest2.exe mptest3.exe mptest3a.exe mptest4.exe \
mptest4a.exe mptest4b.exe mptest6.exe bbsrand.exe
utests: mptest7.exe mptest8.exe mptest9.exe
#---------------------------------------
EXTRAOBJS = bbsrand.obj bbs_rand.obj prng.obj
UTILOBJS = primegen.obj metime.obj identest.obj basecvt.obj fact.obj \
exptmod.obj pi.obj makeprime.obj karatsuba.obj gcd.obj invmod.obj lap.obj \
isprime.obj dec2hex.obj hex2dec.obj
UTILS = $(UTILOBJS:.obj=.exe)
$(UTILS): %.exe : %.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
$(UTILOBJS) $(EXTRAOBJS): %.obj : utils/%.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
prng.exe: prng.obj bbs_rand.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
bbsrand.exe: bbsrand.obj bbs_rand.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
utils: $(UTILS) prng.exe bbsrand.exe
#---------------------------------------
test-info.c: test-arrays.txt
$(PERL) make-test-arrays test-arrays.txt > test-info.c
mpi-test.obj: mpi-test.c test-info.c $(LIBHDRS)
$(CC) $(CFLAGS) -Fo$@ -c $<
mpi-test.exe: mpi-test.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
mdxptest.obj: mdxptest.c $(LIBHDRS) mpi-priv.h
mdxptest.exe: mdxptest.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
mulsqr.obj: mulsqr.c logtab.h mpi.h mpi-config.h mpprime.h
$(CC) $(CFLAGS) -DMP_SQUARE=1 -Fo$@ -c mulsqr.c
mulsqr.exe: mulsqr.obj mpi.lib $(LIBS)
$(CC) $(CFLAGS) -Fo$@ $^
#---------------------------------------
alltests: tests utests mpi-test.exe
tools: $(TOOLS)
doc:
(cd doc; ./build)
clean:
rm -f *.obj *.lib *.pdb *.ilk
cd utils; rm -f *.obj *.lib *.pdb *.ilk
distclean: clean
rm -f mptest? mpi-test metime mulsqr karatsuba
rm -f mptest?a mptest?b
rm -f utils/mptest?
rm -f test-info.c logtab.h
rm -f mpi.lib
rm -f $(TOOLS)
dist: Makefile $(HDRS) $(SRCS) $(DOCS)
tar -cvf mpi-$(VERS).tar Makefile $(HDRS) $(SRCS) $(DOCS)
pgps -ab mpi-$(VERS).tar
chmod +r mpi-$(VERS).tar.asc
gzip -9 mpi-$(VERS).tar
print:
@echo LIBOBJS = $(LIBOBJS)
# END

View file

@ -67,14 +67,6 @@ assumptions about the sizes of things, but there is little if any
reason to change the other parameters, so I would recommend you leave
them as you found them.
The library comes with a Perl script, 'types.pl', which will scan your
current Makefile settings, and attempt to find good definitions for
these types. It relies on a Unix sort of build environment, so it
probably won't work under MacOS or Windows, but it can be convenient
if you're porting to a new flavour of Unix. Just run 'types.pl' at
the command line, and it will spit out its results to the standard
output.
Conventions
-----------
@ -503,9 +495,6 @@ MP_MODARITH - Define true to include the modular arithmetic
in your application, you can set this to zero to
leave out all the modular routines.
MP_NUMTH - Define true to include number theoretic functions
such as mp_gcd(), mp_lcm(), and mp_invmod().
MP_LOGTAB - If true, the file "logtab.h" is included, which
is basically a static table of base 2 logarithms.
These are used to compute how big the buffers for
@ -633,92 +622,6 @@ Most of these can be built from the Makefile that comes with the
library. Try 'make tools', if your environment supports it.
Testing the Library
-------------------
Automatic test vectors are included, in the form of a program called
'mpi-test'. To build this program and run all the tests, simply
invoke the shell script 'all-tests'. If all the tests pass, you
should see a message:
All tests passed
If something went wrong, you'll get:
One or more tests failed.
If this happens, scan back through the preceding lines, to see which
test failed. Any failure indicates a bug in the library, which needs
to be fixed before it will give accurate results. If you get any such
thing, please let me know, and I'll try to fix it. Please let me know
what platform and compiler you were using, as well as which test
failed. If a reason for failure was given, please send me that text
as well.
If you're on a system where the standard Unix build tools don't work,
you can build the 'mpi-test' program manually, and run it by hand.
This is tedious and obnoxious, sorry.
Further manual testing can be performed by building the manual testing
programs, whose source is found in the 'tests' subdirectory. Each
test is in a source file called 'mptest-X.c'. The Makefile contains a
target to build all of them at once:
make tests
Read the comments at the top of each source file to see what the
driver is supposed to test. You probably don't need to do this; these
programs were only written to help me as I was developing the library.
The relevant files are:
mpi-test.c The source for the test driver
make-test-arrays A Perl script to generate some of the internal
data structures used by mpi-test.c
test-arrays.txt The source file for make-test-arrays
all-tests A Bourne shell script which runs all the
tests in the mpi-test suite
Running 'make mpi-test' should build the mpi-test program. If you
cannot use make, here is what needs to be done:
(1) Use 'make-test-arrays' to generate the file 'test-info.c' from
the 'test-arrays.txt' file. Since Perl can be found everywhere,
this should be no trouble. Under Unix, this looks like:
make-test-arrays test-arrays.txt > test-info.c
(2) Build the MPI library:
gcc -ansi -pedantic -Wall -c mpi.c
(3) Build the mpi-test program:
gcc -ansi -pedantic -Wall -o mpi-test mpi.o mpi-test.c
When you've got mpi-test, you can use 'all-tests' to run all the tests
made available by mpi-test. If any of them fail, there should be a
diagnostic indicating what went wrong. These are fairly high-level
diagnostics, and won't really help you debug the problem; they're
simply intended to help you isolate which function caused the problem.
If you encounter a problem of this sort, feel free to e-mail me, and I
will certainly attempt to help you debug it.
Note: Several of the tests hard-wired into 'mpi-test' operate under
---- the assumption that you are using at least a 16-bit mp_digit
type. If that is not true, several tests might fail, because
of range problems with the maximum digit value.
If you are using an 8-bit digit, you will also need to
modify the code for mp_read_raw(), which assumes that
multiplication by 256 can be done with mp_mul_d(), a
fact that fails when DIGIT_MAX is 255. You can replace
the call with s_mp_lshd(), which will give you the same
effect, and without doing as much work. :)
Acknowledgements:
----------------

View file

@ -1,83 +0,0 @@
#!/bin/sh
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
ECHO=/bin/echo
MAKE=gmake
$ECHO "\n** Running unit tests for MPI library\n"
# Build the mpi-test program, which comprises all the unit tests for
# the MPI library...
$ECHO "Bringing mpi-test up to date ... "
if $MAKE mpi-test ; then
:
else
$ECHO " "
$ECHO "Make failed to build mpi-test."
$ECHO " "
exit 1
fi
if [ ! -x mpi-test ] ; then
$ECHO " "
$ECHO "Cannot find 'mpi-test' program, testing cannot continue."
$ECHO " "
exit 1
fi
# Get the list of available test suites...
tests=`./mpi-test list | awk '{print $1}'`
errs=0
# Run each test suite and check the result code of mpi-test
for test in $tests ; do
$ECHO "$test ... \c"
if ./mpi-test $test ; then
$ECHO "passed"
else
$ECHO "FAILED"
errs=1
fi
done
# If any tests failed, we'll stop at this point
if [ "$errs" = "0" ] ; then
$ECHO "All unit tests passed"
else
$ECHO "One or more tests failed"
exit 1
fi
# Now try to build the 'pi' program, and see if it can compute the
# first thousand digits of pi correctly
$ECHO "\n** Running other tests\n"
$ECHO "Bringing 'pi' up to date ... "
if $MAKE pi ; then
:
else
$ECHO "\nMake failed to build pi.\n"
exit 1
fi
if [ ! -x pi ] ; then
$ECHO "\nCannot find 'pi' program; testing cannot continue.\n"
exit 1
fi
./pi 2000 > /tmp/pi.tmp.$$
if cmp tests/pi2k.txt /tmp/pi.tmp.$$ ; then
$ECHO "Okay! The pi test passes."
else
$ECHO "Oops! The pi test failed. :("
exit 1
fi
rm -f /tmp/pi.tmp.$$
exit 0
# Here there be dragons

View file

@ -1,21 +0,0 @@
#/bin/sh
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# script to change the system id in an object file from PA-RISC 2.0 to 1.1
adb -w $1 << EOF
?m 0 -1 0
0x0?X
0x0?W (@0x0&~0x40000)|(~@0x0&0x40000)
0?"change checksum"
0x7c?X
0x7c?W (@0x7c&~0x40000)|(~@0x7c&0x40000)
$q
EOF
exit 0

View file

@ -1,29 +0,0 @@
#!/usr/bin/perl
#
# make-logtab
#
# Generate a table of logarithms of 2 in various bases, for use in
# estimating the output sizes of various bases.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
$ARRAYNAME = $ENV{'ARRAYNAME'} || "s_logv_2";
$ARRAYTYPE = $ENV{'ARRAYTYPE'} || "float";
printf("const %s %s[] = {\n %0.9ff, %0.9ff, ",
$ARRAYTYPE, $ARRAYNAME, 0, 0);
$brk = 2;
for($ix = 2; $ix < 64; $ix++) {
printf("%0.9ff, ", (log(2)/log($ix)));
$brk = ($brk + 1) & 3;
if(!$brk) {
printf(" /* %2d %2d %2d %2d */\n ",
$ix - 3, $ix - 2, $ix - 1, $ix);
}
}
printf("%0.9ff\n};\n\n", (log(2)/log($ix)));
exit 0;

View file

@ -1,98 +0,0 @@
#!/usr/bin/perl
#
# make-test-arrays
#
# Given a test-arrays file, which specifies the test suite names, the
# names of the functions which perform those test suites, and
# descriptive comments, this script generates C structures for the
# mpi-test program. The input consists of lines of the form:
#
# suite-name:function-name:comment
#
# The output is written to the standard output. Blank lines are
# ignored, and comments beginning with '#' are stripped.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Read parameters from the environment, if available
$NAMEVAR = $ENV{'NAMEVAR'} || "g_names";
$COUNTVAR = $ENV{'COUNTVAR'} || "g_count";
$FUNCVAR = $ENV{'FUNCVAR'} || "g_tests";
$DESCVAR = $ENV{'DESCVAR'} || "g_descs";
$FUNCLEN = 13;
$NAMELEN = 18;
$DESCLEN = 45;
#------------------------------------------------------------------------
# Suck in input from the files on the command line, or standard input
while(<>) {
chomp;
s/\#.*$//;
next if /^\s*$/;
($suite, $func, $desc) = split(/:/, $_);
$tmp = { "suite" => $suite,
"func" => $func,
"desc" => $desc };
push(@item, $tmp);
}
$count = scalar(@item);
$last = pop(@item);
#------------------------------------------------------------------------
# Output the table of names
print "/* Table mapping test suite names to index numbers */\n";
printf("const int %s = %d;\n", $COUNTVAR, $count);
printf("const char *%s[] = {\n", $NAMEVAR);
foreach $elt (@item) {
printf(" \"%s\",%s/* %s%s */\n", $elt->{"suite"},
" " x ($NAMELEN - length($elt->{"suite"})),
$elt->{"desc"},
" " x ($DESCLEN - length($elt->{"desc"})));
}
printf(" \"%s\" %s/* %s%s */\n", $last->{"suite"},
" " x ($NAMELEN - length($last->{"suite"})),
$last->{"desc"},
" " x ($DESCLEN - length($last->{"desc"})));
print "};\n\n";
#------------------------------------------------------------------------
# Output the driver function prototypes
print "/* Test function prototypes */\n";
foreach $elt (@item, $last) {
printf("int %s(void);\n", $elt->{"func"});
}
print "\n";
#------------------------------------------------------------------------
# Output the table of functions
print "/* Table mapping index numbers to functions */\n";
printf("int (*%s[])(void) = {\n ", $FUNCVAR);
$brk = 0;
foreach $elt (@item) {
print($elt->{"func"}, ", ",
" " x ($FUNCLEN - length($elt->{"func"})));
$brk = ($brk + 1) & 3;
print "\n " unless($brk);
}
print $last->{"func"}, "\n};\n\n";
#------------------------------------------------------------------------
# Output the table of descriptions
print "/* Table mapping index numbers to descriptions */\n";
printf("const char *%s[] = {\n", $DESCVAR);
foreach $elt (@item) {
printf(" \"%s\",\n", $elt->{"desc"});
}
printf(" \"%s\"\n};\n\n", $last->{"desc"});
exit 0;

View file

@ -1,306 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "mpi.h"
#include "mpi-priv.h"
/* #define OLD_WAY 1 */
/* This key is the 1024-bit test key used for speed testing of RSA private
** key ops.
*/
#define CONST const
static CONST unsigned char default_n[128] = {
0xc2, 0xae, 0x96, 0x89, 0xaf, 0xce, 0xd0, 0x7b, 0x3b, 0x35, 0xfd, 0x0f, 0xb1, 0xf4, 0x7a, 0xd1,
0x3c, 0x7d, 0xb5, 0x86, 0xf2, 0x68, 0x36, 0xc9, 0x97, 0xe6, 0x82, 0x94, 0x86, 0xaa, 0x05, 0x39,
0xec, 0x11, 0x51, 0xcc, 0x5c, 0xa1, 0x59, 0xba, 0x29, 0x18, 0xf3, 0x28, 0xf1, 0x9d, 0xe3, 0xae,
0x96, 0x5d, 0x6d, 0x87, 0x73, 0xf6, 0xf6, 0x1f, 0xd0, 0x2d, 0xfb, 0x2f, 0x7a, 0x13, 0x7f, 0xc8,
0x0c, 0x7a, 0xe9, 0x85, 0xfb, 0xce, 0x74, 0x86, 0xf8, 0xef, 0x2f, 0x85, 0x37, 0x73, 0x0f, 0x62,
0x4e, 0x93, 0x17, 0xb7, 0x7e, 0x84, 0x9a, 0x94, 0x11, 0x05, 0xca, 0x0d, 0x31, 0x4b, 0x2a, 0xc8,
0xdf, 0xfe, 0xe9, 0x0c, 0x13, 0xc7, 0xf2, 0xad, 0x19, 0x64, 0x28, 0x3c, 0xb5, 0x6a, 0xc8, 0x4b,
0x79, 0xea, 0x7c, 0xce, 0x75, 0x92, 0x45, 0x3e, 0xa3, 0x9d, 0x64, 0x6f, 0x04, 0x69, 0x19, 0x17
};
static CONST unsigned char default_d[128] = {
0x13, 0xcb, 0xbc, 0xf2, 0xf3, 0x35, 0x8c, 0x6d, 0x7b, 0x6f, 0xd9, 0xf3, 0xa6, 0x9c, 0xbd, 0x80,
0x59, 0x2e, 0x4f, 0x2f, 0x11, 0xa7, 0x17, 0x2b, 0x18, 0x8f, 0x0f, 0xe8, 0x1a, 0x69, 0x5f, 0x6e,
0xac, 0x5a, 0x76, 0x7e, 0xd9, 0x4c, 0x6e, 0xdb, 0x47, 0x22, 0x8a, 0x57, 0x37, 0x7a, 0x5e, 0x94,
0x7a, 0x25, 0xb5, 0xe5, 0x78, 0x1d, 0x3c, 0x99, 0xaf, 0x89, 0x7d, 0x69, 0x2e, 0x78, 0x9d, 0x1d,
0x84, 0xc8, 0xc1, 0xd7, 0x1a, 0xb2, 0x6d, 0x2d, 0x8a, 0xd9, 0xab, 0x6b, 0xce, 0xae, 0xb0, 0xa0,
0x58, 0x55, 0xad, 0x5c, 0x40, 0x8a, 0xd6, 0x96, 0x08, 0x8a, 0xe8, 0x63, 0xe6, 0x3d, 0x6c, 0x20,
0x49, 0xc7, 0xaf, 0x0f, 0x25, 0x73, 0xd3, 0x69, 0x43, 0x3b, 0xf2, 0x32, 0xf8, 0x3d, 0x5e, 0xee,
0x7a, 0xca, 0xd6, 0x94, 0x55, 0xe5, 0xbd, 0x25, 0x34, 0x8d, 0x63, 0x40, 0xb5, 0x8a, 0xc3, 0x01
};
#define DEFAULT_ITERS 50
typedef clock_t timetype;
#define gettime(x) *(x) = clock()
#define subtime(a, b) a -= b
#define msec(x) ((clock_t)((double)x * 1000.0 / CLOCKS_PER_SEC))
#define sec(x) (x / CLOCKS_PER_SEC)
struct TimingContextStr {
timetype start;
timetype end;
timetype interval;
int minutes;
int seconds;
int millisecs;
};
typedef struct TimingContextStr TimingContext;
TimingContext *
CreateTimingContext(void)
{
return (TimingContext *)malloc(sizeof(TimingContext));
}
void
DestroyTimingContext(TimingContext *ctx)
{
free(ctx);
}
void
TimingBegin(TimingContext *ctx)
{
gettime(&ctx->start);
}
static void
timingUpdate(TimingContext *ctx)
{
ctx->millisecs = msec(ctx->interval) % 1000;
ctx->seconds = sec(ctx->interval);
ctx->minutes = ctx->seconds / 60;
ctx->seconds %= 60;
}
void
TimingEnd(TimingContext *ctx)
{
gettime(&ctx->end);
ctx->interval = ctx->end;
subtime(ctx->interval, ctx->start);
timingUpdate(ctx);
}
char *
TimingGenerateString(TimingContext *ctx)
{
static char sBuf[4096];
sprintf(sBuf, "%d minutes, %d.%03d seconds", ctx->minutes,
ctx->seconds, ctx->millisecs);
return sBuf;
}
static void
dumpBytes(unsigned char *b, int l)
{
int i;
if (l <= 0)
return;
for (i = 0; i < l; ++i) {
if (i % 16 == 0)
printf("\t");
printf(" %02x", b[i]);
if (i % 16 == 15)
printf("\n");
}
if ((i % 16) != 0)
printf("\n");
printf("\n");
}
static mp_err
testNewFuncs(const unsigned char *modulusBytes, int modulus_len)
{
mp_err mperr = MP_OKAY;
mp_int modulus;
unsigned char buf[512];
mperr = mp_init(&modulus);
mperr = mp_read_unsigned_octets(&modulus, modulusBytes, modulus_len);
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len);
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len + 1);
mperr = mp_to_fixlen_octets(&modulus, buf, modulus_len + 4);
mperr = mp_to_unsigned_octets(&modulus, buf, modulus_len);
mperr = mp_to_signed_octets(&modulus, buf, modulus_len + 1);
mp_clear(&modulus);
return mperr;
}
int
testModExp(const unsigned char *modulusBytes,
const unsigned int expo,
const unsigned char *input,
unsigned char *output,
int modulus_len)
{
mp_err mperr = MP_OKAY;
mp_int modulus;
mp_int base;
mp_int exponent;
mp_int result;
mperr = mp_init(&modulus);
mperr += mp_init(&base);
mperr += mp_init(&exponent);
mperr += mp_init(&result);
/* we initialize all mp_ints unconditionally, even if some fail.
** This guarantees that the DIGITS pointer is valid (even if null).
** So, mp_clear will do the right thing below.
*/
if (mperr == MP_OKAY) {
mperr = mp_read_unsigned_octets(&modulus,
modulusBytes + (sizeof default_n - modulus_len), modulus_len);
mperr += mp_read_unsigned_octets(&base, input, modulus_len);
mp_set(&exponent, expo);
if (mperr == MP_OKAY) {
#if OLD_WAY
mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
#else
mperr = mp_exptmod(&base, &exponent, &modulus, &result);
#endif
if (mperr == MP_OKAY) {
mperr = mp_to_fixlen_octets(&result, output, modulus_len);
}
}
}
mp_clear(&base);
mp_clear(&result);
mp_clear(&modulus);
mp_clear(&exponent);
return (int)mperr;
}
int
doModExp(const unsigned char *modulusBytes,
const unsigned char *exponentBytes,
const unsigned char *input,
unsigned char *output,
int modulus_len)
{
mp_err mperr = MP_OKAY;
mp_int modulus;
mp_int base;
mp_int exponent;
mp_int result;
mperr = mp_init(&modulus);
mperr += mp_init(&base);
mperr += mp_init(&exponent);
mperr += mp_init(&result);
/* we initialize all mp_ints unconditionally, even if some fail.
** This guarantees that the DIGITS pointer is valid (even if null).
** So, mp_clear will do the right thing below.
*/
if (mperr == MP_OKAY) {
mperr = mp_read_unsigned_octets(&modulus,
modulusBytes + (sizeof default_n - modulus_len), modulus_len);
mperr += mp_read_unsigned_octets(&exponent, exponentBytes, modulus_len);
mperr += mp_read_unsigned_octets(&base, input, modulus_len);
if (mperr == MP_OKAY) {
#if OLD_WAY
mperr = s_mp_exptmod(&base, &exponent, &modulus, &result);
#else
mperr = mp_exptmod(&base, &exponent, &modulus, &result);
#endif
if (mperr == MP_OKAY) {
mperr = mp_to_fixlen_octets(&result, output, modulus_len);
}
}
}
mp_clear(&base);
mp_clear(&result);
mp_clear(&modulus);
mp_clear(&exponent);
return (int)mperr;
}
int
main(int argc, char **argv)
{
TimingContext *timeCtx;
char *progName;
long iters = DEFAULT_ITERS;
unsigned int modulus_len;
int i;
int rv;
unsigned char buf[1024];
unsigned char buf2[1024];
progName = strrchr(argv[0], '/');
if (!progName)
progName = strrchr(argv[0], '\\');
progName = progName ? progName + 1 : argv[0];
if (argc >= 2) {
iters = atol(argv[1]);
}
if (argc >= 3) {
modulus_len = atol(argv[2]);
} else
modulus_len = sizeof default_n;
/* no library init function !? */
memset(buf, 0x41, sizeof buf);
if (iters < 2) {
testNewFuncs(default_n, modulus_len);
testNewFuncs(default_n + 1, modulus_len - 1);
testNewFuncs(default_n + 2, modulus_len - 2);
testNewFuncs(default_n + 3, modulus_len - 3);
rv = testModExp(default_n, 0, buf, buf2, modulus_len);
dumpBytes((unsigned char *)buf2, modulus_len);
rv = testModExp(default_n, 1, buf, buf2, modulus_len);
dumpBytes((unsigned char *)buf2, modulus_len);
rv = testModExp(default_n, 2, buf, buf2, modulus_len);
dumpBytes((unsigned char *)buf2, modulus_len);
rv = testModExp(default_n, 3, buf, buf2, modulus_len);
dumpBytes((unsigned char *)buf2, modulus_len);
}
rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
if (rv != 0) {
fprintf(stderr, "Error in modexp operation:\n");
exit(1);
}
dumpBytes((unsigned char *)buf2, modulus_len);
timeCtx = CreateTimingContext();
TimingBegin(timeCtx);
i = iters;
while (i--) {
rv = doModExp(default_n, default_d, buf, buf2, modulus_len);
if (rv != 0) {
fprintf(stderr, "Error in modexp operation\n");
exit(1);
}
}
TimingEnd(timeCtx);
printf("%ld iterations in %s\n", iters, TimingGenerateString(timeCtx));
return 0;
}

View file

@ -17,7 +17,7 @@
*
* Currently the file returns good data for most modern x86 processors, and
* reasonable data on 64-bit ppc processors. All other processors are assumed
* to have a cache line size of 32 bytes unless modified by target.mk.
* to have a cache line size of 32 bytes.
*
*/
@ -775,18 +775,6 @@ s_mpi_getProcessorLineSize()
*
*/
/* target.mk can define MPI_CACHE_LINE_SIZE if it's common for the family or
* OS */
#if defined(MPI_CACHE_LINE_SIZE) && !defined(MPI_GET_PROCESSOR_LINE_SIZE_DEFINED)
unsigned long
s_mpi_getProcessorLineSize()
{
return MPI_CACHE_LINE_SIZE;
}
#define MPI_GET_PROCESSOR_LINE_SIZE_DEFINED 1
#endif
/* If no way to get the processor cache line size has been defined, assume
* it's 32 bytes (most common value, does not significantly impact performance)
*/
@ -797,12 +785,3 @@ s_mpi_getProcessorLineSize()
return 32;
}
#endif
#ifdef TEST_IT
#include <stdio.h>
main()
{
printf("line size = %d\n", s_mpi_getProcessorLineSize());
}
#endif

View file

@ -24,10 +24,6 @@
#define MP_MODARITH 1 /* include modular arithmetic ? */
#endif
#ifndef MP_NUMTH
#define MP_NUMTH 1 /* include number theoretic functions? */
#endif
#ifndef MP_LOGTAB
#define MP_LOGTAB 1 /* use table of logs instead of log()? */
#endif

View file

@ -1695,7 +1695,6 @@ mp_iseven(const mp_int *a)
/*------------------------------------------------------------------------*/
/* {{{ Number theoretic functions */
#if MP_NUMTH
/* {{{ mp_gcd(a, b, c) */
/*
@ -2376,7 +2375,6 @@ mp_invmod(const mp_int *a, const mp_int *m, mp_int *c)
} /* end mp_invmod() */
/* }}} */
#endif /* if MP_NUMTH */
/* }}} */
@ -2861,6 +2859,9 @@ void
s_mp_exch(mp_int *a, mp_int *b)
{
mp_int tmp;
if (!a || !b) {
return;
}
tmp = *a;
*a = *b;
@ -4088,7 +4089,7 @@ s_mpv_sqr_add_prop(const mp_digit *pa, mp_size a_len, mp_digit *ps)
}
#endif
#if (defined(MP_NO_MP_WORD) || defined(MP_NO_DIV_WORD)) && !defined(MP_ASSEMBLY_DIV_2DX1D)
#if !defined(MP_ASSEMBLY_DIV_2DX1D)
/*
** Divide 64-bit (Nhi,Nlo) by 32-bit divisor, which must be normalized
** so its high bit is 1. This code is from NSPR.
@ -4166,11 +4167,7 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
mp_int *quot) /* i: 0; o: quotient */
{
mp_int part, t;
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
mp_word q_msd;
#else
mp_digit q_msd;
#endif
mp_err res;
mp_digit d;
mp_digit div_msd;
@ -4215,7 +4212,7 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
MP_USED(&part) = MP_USED(div);
/* We have now truncated the part of the remainder to the same length as
* the divisor. If part is smaller than div, extend part by one digit. */
* the divisor. If part is smaller than div, extend part by one digit. */
if (s_mp_cmp(&part, div) < 0) {
--unusedRem;
#if MP_ARGCHK == 2
@ -4232,18 +4229,12 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
div_msd = MP_DIGIT(div, MP_USED(div) - 1);
if (!partExtended) {
/* In this case, q_msd /= div_msd is always 1. First, since div_msd is
* normalized to have the high bit set, 2*div_msd > MP_DIGIT_MAX. Since
* we didn't extend part, q_msd >= div_msd. Therefore we know that
* div_msd <= q_msd <= MP_DIGIT_MAX < 2*div_msd. Dividing by div_msd we
* get 1 <= q_msd/div_msd < 2. So q_msd /= div_msd must be 1. */
* normalized to have the high bit set, 2*div_msd > MP_DIGIT_MAX. Since
* we didn't extend part, q_msd >= div_msd. Therefore we know that
* div_msd <= q_msd <= MP_DIGIT_MAX < 2*div_msd. Dividing by div_msd we
* get 1 <= q_msd/div_msd < 2. So q_msd /= div_msd must be 1. */
q_msd = 1;
} else {
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
q_msd = (q_msd << MP_DIGIT_BIT) | MP_DIGIT(&part, MP_USED(&part) - 2);
q_msd /= div_msd;
if (q_msd == RADIX)
--q_msd;
#else
if (q_msd == div_msd) {
q_msd = MP_DIGIT_MAX;
} else {
@ -4251,7 +4242,6 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
MP_CHECKOK(s_mpv_div_2dx1d(q_msd, MP_DIGIT(&part, MP_USED(&part) - 2),
div_msd, &q_msd, &r));
}
#endif
}
#if MP_ARGCHK == 2
assert(q_msd > 0); /* This case should never occur any more. */
@ -4261,15 +4251,15 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
/* See what that multiplies out to */
mp_copy(div, &t);
MP_CHECKOK(s_mp_mul_d(&t, (mp_digit)q_msd));
MP_CHECKOK(s_mp_mul_d(&t, q_msd));
/*
If it's too big, back it off. We should not have to do this
more than once, or, in rare cases, twice. Knuth describes a
method by which this could be reduced to a maximum of once, but
I didn't implement that here.
* When using s_mpv_div_2dx1d, we may have to do this 3 times.
*/
If it's too big, back it off. We should not have to do this
more than once, or, in rare cases, twice. Knuth describes a
method by which this could be reduced to a maximum of once, but
I didn't implement that here.
When using s_mpv_div_2dx1d, we may have to do this 3 times.
*/
for (i = 4; s_mp_cmp(&t, &part) > 0 && i > 0; --i) {
--q_msd;
MP_CHECKOK(s_mp_sub(&t, div)); /* t -= div */
@ -4284,11 +4274,11 @@ mp_err s_mp_div(mp_int *rem, /* i: dividend, o: remainder */
s_mp_clamp(rem);
/*
Include the digit in the quotient. We allocated enough memory
for any quotient we could ever possibly get, so we should not
have to check for failures here
*/
MP_DIGIT(quot, unusedRem) = (mp_digit)q_msd;
Include the digit in the quotient. We allocated enough memory
for any quotient we could ever possibly get, so we should not
have to check for failures here
*/
MP_DIGIT(quot, unusedRem) = q_msd;
}
/* Denormalize remainder */

View file

@ -225,13 +225,11 @@ int mp_isodd(const mp_int *a);
int mp_iseven(const mp_int *a);
/* Number theoretic */
#if MP_NUMTH
mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_lcm(mp_int *a, mp_int *b, mp_int *c);
mp_err mp_xgcd(const mp_int *a, const mp_int *b, mp_int *g, mp_int *x, mp_int *y);
mp_err mp_invmod(const mp_int *a, const mp_int *m, mp_int *c);
mp_err mp_invmod_xgcd(const mp_int *a, const mp_int *m, mp_int *c);
#endif /* end MP_NUMTH */
/* Input and output */
#if MP_IOFUNC

View file

@ -205,7 +205,11 @@ mp_exptmod_f(const mp_int *montBase,
dTmpSize = 2 * oddPowSize;
dSize = sizeof(double) * (nLen * 4 + 1 +
((odd_ints + 1) * oddPowSize) + dTmpSize);
dBuf = (double *)malloc(dSize);
dBuf = malloc(dSize);
if (!dBuf) {
res = MP_MEM;
goto CLEANUP;
}
dm1 = dBuf; /* array of d32 */
dn = dBuf + nLen; /* array of d32 */
dSqr = dn + nLen; /* array of d32 */

View file

@ -402,8 +402,7 @@ mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes,
#define SIEVE_SIZE 32 * 1024
mp_err
mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
unsigned long *nTries)
mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong)
{
mp_digit np;
mp_err res;
@ -548,8 +547,6 @@ mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
CLEANUP:
mp_clear(&trial);
mp_clear(&q);
if (nTries)
*nTries += i;
if (sieve != NULL) {
memset(sieve, 0, SIEVE_SIZE);
free(sieve);

View file

@ -13,6 +13,8 @@
#include "mpi.h"
SEC_BEGIN_PROTOS
extern const int prime_tab_size; /* number of primes available */
extern const mp_digit prime_tab[];
@ -32,7 +34,8 @@ mp_err mpp_fermat_list(mp_int *a, const mp_digit *primes, mp_size nPrimes);
mp_err mpp_pprime(mp_int *a, int nt);
mp_err mpp_sieve(mp_int *trial, const mp_digit *primes, mp_size nPrimes,
unsigned char *sieve, mp_size nSieve);
mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong,
unsigned long *nTries);
mp_err mpp_make_prime(mp_int *start, mp_size nBits, mp_size strong);
SEC_END_PROTOS
#endif /* end _H_MP_PRIME_ */

View file

@ -1,76 +0,0 @@
#!/bin/sh
#
# multest
#
# Run multiply and square timing tests, to compute a chart for the
# current processor and compiler combination.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
ECHO=/bin/echo
MAKE=gmake
$ECHO "\n** Running multiply and square timing tests\n"
$ECHO "Bringing 'mulsqr' up to date ... "
if $MAKE mulsqr ; then
:
else
$ECHO "\nMake failed to build mulsqr.\n"
exit 1
fi
if [ ! -x ./mulsqr ] ; then
$ECHO "\nCannot find 'mulsqr' program, testing cannot continue.\n"
exit 1
fi
sizes='64 128 192 256 320 384 448 512 640 768 896 1024 1536 2048'
ntests=500000
$ECHO "Running timing tests, please wait ... "
trap 'echo "oop!";rm -f tt*.tmp;exit 0' INT HUP
touch tt$$.tmp
$ECHO $ntests tests >> tt$$.tmp
for size in $sizes ; do
$ECHO "$size bits ... \c"
set -A res `./mulsqr $ntests $size|head -3|tr -d '%'|awk '{print $2}'`
$ECHO $size"\t"${res[0]}"\t"${res[1]}"\t"${res[2]} >> tt$$.tmp
$ECHO "(done)"
done
mv tt$$.tmp mulsqr-results.txt
rm -f tt$$.tmp
$ECHO "\n** Running Karatsuba-Ofman multiplication tests\n"
$ECHO "Brining 'karatsuba' up to date ... "
if $MAKE karatsuba ; then
:
else
$ECHO "\nMake failed to build karatsuba.\n"
exit 1
fi
if [ ! -x ./karatsuba ] ; then
$ECHO "\nCannot find 'karatsuba' program, testing cannot continue.\n"
exit 1
fi
ntests=100000
trap 'echo "oop!";rm -f tt*.tmp;exit 0' INT HUP
touch tt$$.tmp
for size in $sizes ; do
$ECHO "$size bits ... "
./karatsuba $ntests $size >> tt$$.tmp
tail -2 tt$$.tmp
done
mv tt$$.tmp karatsuba-results.txt
rm -f tt$$.tmp
exit 0

View file

@ -1,39 +0,0 @@
#!/usr/bin/perl
#
# Treat each line as a sequence of comma and/or space delimited
# floating point numbers, and compute basic statistics on them.
# These are written to standard output
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
$min = 1.7976931348623157E+308;
$max = 2.2250738585072014E-308;
$sum = $num = 0;
while(<>) {
chomp;
@nums = split(/[\s,]+/, $_);
next if($#nums < 0);
$num += scalar @nums;
foreach (@nums) {
$min = $_ if($_ < $min);
$max = $_ if($_ > $max);
$sum += $_;
}
}
if($num) {
$avg = $sum / $num;
} else {
$min = $max = 0;
}
printf "%d\tmin=%.2f, avg=%.2f, max=%.2f, sum=%.2f\n",
$num, $min, $avg, $max, $sum;
# end

View file

@ -1,233 +0,0 @@
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
##
## Define CFLAGS to contain any local options your compiler
## setup requires.
##
## Conditional compilation options are no longer here; see
## the file 'mpi-config.h' instead.
##
MPICMN = -I. -DMP_API_COMPATIBLE -DMP_IOFUNC
CFLAGS= -O $(MPICMN)
#CFLAGS=-ansi -fullwarn -woff 1521 -O3 $(MPICMN)
#CFLAGS=-ansi -pedantic -Wall -O3 $(MPICMN)
#CFLAGS=-ansi -pedantic -Wall -g -O2 -DMP_DEBUG=1 $(MPICMN)
ifeq ($(TARGET),mipsIRIX)
#IRIX
#MPICMN += -DMP_MONT_USE_MP_MUL
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
MPICMN += -DMP_USE_UINT_DIGIT
#MPICMN += -DMP_NO_MP_WORD
AS_OBJS = mpi_mips.o
#ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3 -exceptions
ASFLAGS = -O -OPT:Olimit=4000 -dollar -fullwarn -xansi -n32 -mips3
#CFLAGS=-ansi -n32 -O3 -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN)
CFLAGS=-ansi -n32 -O2 -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN)
#CFLAGS=-ansi -n32 -g -fullwarn -woff 1429 -D_SGI_SOURCE $(MPICMN)
#CFLAGS=-ansi -64 -O2 -fullwarn -woff 1429 -D_SGI_SOURCE -DMP_NO_MP_WORD \
$(MPICMN)
endif
ifeq ($(TARGET),alphaOSF1)
#Alpha/OSF1
MPICMN += -DMP_ASSEMBLY_MULTIPLY
AS_OBJS+= mpvalpha.o
#CFLAGS= -O -Olimit 4000 -ieee_with_inexact -std1 -DOSF1 -D_REENTRANT $(MPICMN)
CFLAGS= -O -Olimit 4000 -ieee_with_inexact -std1 -DOSF1 -D_REENTRANT \
-DMP_NO_MP_WORD $(MPICMN)
endif
ifeq ($(TARGET),v9SOLARIS)
#Solaris 64
SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xchip=ultra -xarch=v9a -KPIC -mt
#SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v9a -KPIC -mt
SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v9a -KPIC -mt
AS_OBJS += montmulfv9.o
AS_OBJS += mpi_sparc.o mpv_sparcv9.o
MPICMN += -DMP_USE_UINT_DIGIT
#MPICMN += -DMP_NO_MP_WORD
MPICMN += -DMP_ASSEMBLY_MULTIPLY
MPICMN += -DMP_USING_MONT_MULF
CFLAGS= -O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \
-DSOLARIS2_8 -xarch=v9 -DXP_UNIX $(MPICMN)
#CFLAGS= -g -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \
-DSOLARIS2_8 -xarch=v9 -DXP_UNIX $(MPICMN)
endif
ifeq ($(TARGET),v8plusSOLARIS)
#Solaris 32
SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v8plusa -KPIC -mt
SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v8plusa -KPIC -mt
AS_OBJS += montmulfv8.o
AS_OBJS += mpi_sparc.o mpv_sparcv8.o
#AS_OBJS = montmulf.o
MPICMN += -DMP_ASSEMBLY_MULTIPLY
MPICMN += -DMP_USING_MONT_MULF
MPICMN += -DMP_USE_UINT_DIGIT
MPICMN += -DMP_NO_MP_WORD
CFLAGS=-O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \
-DSOLARIS2_6 -xarch=v8plus -DXP_UNIX $(MPICMN)
endif
ifeq ($(TARGET),v8SOLARIS)
#Solaris 32
#SOLARIS_FPU_FLAGS = -fast -xO5 -xrestrict=%all -xdepend -xchip=ultra -xarch=v8 -KPIC -mt
#SOLARIS_ASM_FLAGS = -xchip=ultra -xarch=v8plusa -KPIC -mt
#AS_OBJS = montmulfv8.o mpi_sparc.o mpv_sparcv8.o
#AS_OBJS = montmulf.o
#MPICMN += -DMP_USING_MONT_MULF
#MPICMN += -DMP_ASSEMBLY_MULTIPLY
MPICMN += -DMP_USE_LONG_LONG_MULTIPLY -DMP_USE_UINT_DIGIT
MPICMN += -DMP_NO_MP_WORD
CFLAGS=-O -KPIC -DSVR4 -DSYSV -D__svr4 -D__svr4__ -DSOLARIS -D_REENTRANT \
-DSOLARIS2_6 -xarch=v8 -DXP_UNIX $(MPICMN)
endif
ifeq ($(TARGET),ia64HPUX)
#HPUX 32 on ia64 -- 64 bit digits SCREAM.
# This one is for DD32 which is the 32-bit ABI with 64-bit registers.
CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \
-D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN)
#CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \
-D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN)
#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \
-D_HPUX_SOURCE -Aa +e -z +p +DD32 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN)
endif
ifeq ($(TARGET),ia64HPUX64)
#HPUX 32 on ia64
# This one is for DD64 which is the 64-bit ABI
CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Aa +Z -DHPUX -Dhppa \
-D_HPUX_SOURCE -Aa +e -z +p +DD64 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN)
#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \
-D_HPUX_SOURCE -Aa +e -z +p +DD64 -DHPUX11 -DXP_UNIX -Wl,+k $(MPICMN)
endif
ifeq ($(TARGET),PA2.0WHPUX)
#HPUX64 (HP PA 2.0 Wide) using MAXPY and 64-bit digits
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
AS_OBJS = mpi_hp.o hpma512.o hppa20.o
CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \
-D_HPUX_SOURCE -Aa +e -z +DA2.0W +DS2.0 +O3 +DChpux -DHPUX11 -DXP_UNIX \
$(MPICMN)
#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \
-D_HPUX_SOURCE -Aa +e -z +DA2.0W +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \
$(MPICMN)
AS = $(CC) $(CFLAGS) -c
endif
ifeq ($(TARGET),PA2.0NHPUX)
#HPUX32 (HP PA 2.0 Narrow) hybrid model, using 32-bit digits
# This one is for DA2.0 (N) which is the 32-bit ABI with 64-bit registers.
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
AS_OBJS = mpi_hp.o hpma512.o hppa20.o
CFLAGS= +O3 -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \
-D_HPUX_SOURCE -Aa +e -z +DA2.0 +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \
-Wl,+k $(MPICMN)
#CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \
-D_HPUX_SOURCE -Aa +e -z +DA2.0 +DS2.0 +DChpux -DHPUX11 -DXP_UNIX \
-Wl,+k $(MPICMN)
AS = $(CC) $(CFLAGS) -c
endif
ifeq ($(TARGET),PA1.1HPUX)
#HPUX32 (HP PA 1.1) Pure 32 bit
MPICMN += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD
#MPICMN += -DMP_USE_LONG_LONG_MULTIPLY
CFLAGS= -O -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \
-D_HPUX_SOURCE +DAportable +DS1.1 -DHPUX11 -DXP_UNIX $(MPICMN)
##CFLAGS= -g -DHPUX10 -D_POSIX_C_SOURCE=199506L -Ae +Z -DHPUX -Dhppa \
# -D_HPUX_SOURCE +DAportable +DS1.1 -DHPUX11 -DXP_UNIX $(MPICMN)
endif
ifeq ($(TARGET),32AIX)
#
CC = xlC_r
MPICMN += -DMP_USE_UINT_DIGIT
MPICMN += -DMP_NO_DIV_WORD
#MPICMN += -DMP_NO_MUL_WORD
MPICMN += -DMP_NO_ADD_WORD
MPICMN += -DMP_NO_SUB_WORD
#MPICMN += -DMP_NO_MP_WORD
#MPICMN += -DMP_USE_LONG_LONG_MULTIPLY
CFLAGS = -O -DAIX -DSYSV -qarch=com -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN)
#CFLAGS = -g -DAIX -DSYSV -qarch=com -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN)
#CFLAGS += -pg
endif
ifeq ($(TARGET),64AIX)
#
CC = xlC_r
MPICMN += -DMP_USE_UINT_DIGIT
CFLAGS = -O -O2 -DAIX -DSYSV -qarch=com -DAIX_64BIT -DAIX4_3 -DXP_UNIX -UDEBUG -DNDEBUG $(MPICMN)
OBJECT_MODE=64
export OBJECT_MODE
endif
ifeq ($(TARGET),x86LINUX)
#Linux
AS_OBJS = mpi_x86.o
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
MPICMN += -DMP_MONT_USE_MP_MUL -DMP_IS_LITTLE_ENDIAN
CFLAGS= -O2 -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \
-pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \
-DXP_UNIX -UDEBUG -DNDEBUG -D_REENTRANT $(MPICMN)
#CFLAGS= -g -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \
-pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \
-DXP_UNIX -DDEBUG -UNDEBUG -D_REENTRANT $(MPICMN)
#CFLAGS= -g -fPIC -DLINUX1_2 -Di386 -D_XOPEN_SOURCE -DLINUX2_1 -ansi -Wall \
-pipe -DLINUX -Dlinux -D_POSIX_SOURCE -D_BSD_SOURCE -DHAVE_STRERROR \
-DXP_UNIX -UDEBUG -DNDEBUG -D_REENTRANT $(MPICMN)
endif
ifeq ($(TARGET),armLINUX)
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE
MPICMN += -DMP_USE_UINT_DIGIT
AS_OBJS += mpi_arm.o
endif
ifeq ($(TARGET),AMD64SOLARIS)
ASFLAGS += -xarch=generic64
AS_OBJS = mpi_amd64.o mpi_amd64_sun.o
MP_CONFIG = -DMP_ASSEMBLY_MULTIPLY -DMPI_AMD64
MP_CONFIG += -DMP_IS_LITTLE_ENDIAN
CFLAGS = -xarch=generic64 -xO4 -I. -DMP_API_COMPATIBLE -DMP_IOFUNC $(MP_CONFIG)
MPICMN += $(MP_CONFIG)
mpi_amd64_asm.o: mpi_amd64_sun.s
$(AS) -xarch=generic64 -P -D_ASM mpi_amd64_sun.s
endif
ifeq ($(TARGET),WIN32)
ifeq ($(CPU_ARCH),x86_64)
AS_OBJS = mpi_amd64.obj mpi_amd64_masm.obj mp_comba_amd64_masm.asm
CFLAGS = -Od -Z7 -MDd -W3 -nologo -DDEBUG -D_DEBUG -UNDEBUG -DDEBUG_$(USER)
CFLAGS += -DWIN32 -DWIN64 -D_WINDOWS -D_AMD_64_ -D_M_AMD64 -DWIN95 -DXP_PC
CFLAGS += $(MPICMN)
$(AS_OBJS): %.obj : %.asm
ml64 -Cp -Sn -Zi -coff -nologo -c $<
$(LIBOBJS): %.obj : %.c
cl $(CFLAGS) -Fo$@ -c $<
else
AS_OBJS = mpi_x86.obj
MPICMN += -DMP_ASSEMBLY_MULTIPLY -DMP_ASSEMBLY_SQUARE -DMP_ASSEMBLY_DIV_2DX1D
MPICMN += -DMP_USE_UINT_DIGIT -DMP_NO_MP_WORD -DMP_API_COMPATIBLE
MPICMN += -DMP_MONT_USE_MP_MUL
MPICMN += -DMP_CHAR_STORE_SLOW -DMP_IS_LITTLE_ENDIAN
CFLAGS = -Od -Z7 -MDd -W3 -nologo -DDEBUG -D_DEBUG -UNDEBUG -DDEBUG_$(USER)
CFLAGS += -DWIN32 -D_WINDOWS -D_X86_ -DWIN95 -DXP_PC
CFLAGS += $(MPICMN)
$(AS_OBJS): %.obj : %.asm
ml -Cp -Sn -Zi -coff -nologo -c $<
$(LIBOBJS): %.obj : %.c
cl $(CFLAGS) -Fo$@ -c $<
endif
endif

View file

@ -1,55 +0,0 @@
#
# Test suite table for MPI library
#
# Format of entries:
# suite-name:function-name:description
#
# suite-name The name used to identify this test in mpi-test
# function-name The function called to perform this test in mpi-test.c
# description A brief description of what the suite tests
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
list:test_list:print out a list of the available test suites
copy:test_copy:test assignment of mp-int structures
exchange:test_exch:test exchange of mp-int structures
zero:test_zero:test zeroing of an mp-int
set:test_set:test setting an mp-int to a small constant
absolute-value:test_abs:test the absolute value function
negate:test_neg:test the arithmetic negation function
add-digit:test_add_d:test digit addition
add:test_add:test full addition
subtract-digit:test_sub_d:test digit subtraction
subtract:test_sub:test full subtraction
multiply-digit:test_mul_d:test digit multiplication
multiply:test_mul:test full multiplication
square:test_sqr:test full squaring function
divide-digit:test_div_d:test digit division
divide-2:test_div_2:test division by two
divide-2d:test_div_2d:test division & remainder by 2^d
divide:test_div:test full division
expt-digit:test_expt_d:test digit exponentiation
expt:test_expt:test full exponentiation
expt-2:test_2expt:test power-of-two exponentiation
modulo-digit:test_mod_d:test digit modular reduction
modulo:test_mod:test full modular reduction
mod-add:test_addmod:test modular addition
mod-subtract:test_submod:test modular subtraction
mod-multiply:test_mulmod:test modular multiplication
mod-square:test_sqrmod:test modular squaring function
mod-expt:test_exptmod:test full modular exponentiation
mod-expt-digit:test_exptmod_d:test digit modular exponentiation
mod-inverse:test_invmod:test modular inverse function
compare-digit:test_cmp_d:test digit comparison function
compare-zero:test_cmp_z:test zero comparison function
compare:test_cmp:test general signed comparison
compare-magnitude:test_cmp_mag:test general magnitude comparison
parity:test_parity:test parity comparison functions
gcd:test_gcd:test greatest common divisor functions
lcm:test_lcm:test least common multiple function
conversion:test_convert:test general radix conversion facilities
binary:test_raw:test raw output format
pprime:test_pprime:test probabilistic primality tester
fermat:test_fermat:test Fermat pseudoprimality tester

View file

@ -1,6 +0,0 @@
Within this directory, each of the file listed below is licensed under
the terms given in the file LICENSE-MPL, also in this directory.
pi1k.txt
pi2k.txt
pi5k.txt

View file

@ -1,3 +0,0 @@
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.

View file

@ -1,43 +0,0 @@
/*
* Simple test driver for MPI library
*
* Test 1: Simple input test (drives single-digit multiply and add,
* as well as I/O routines)
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#ifdef MAC_CW_SIOUX
#include <console.h>
#endif
#include "mpi.h"
int
main(int argc, char *argv[])
{
int ix;
mp_int mp;
#ifdef MAC_CW_SIOUX
argc = ccommand(&argv);
#endif
mp_init(&mp);
for (ix = 1; ix < argc; ix++) {
mp_read_radix(&mp, argv[ix], 10);
mp_print(&mp, stdout);
fputc('\n', stdout);
}
mp_clear(&mp);
return 0;
}

View file

@ -1,62 +0,0 @@
/*
* Simple test driver for MPI library
*
* Test 2: Basic addition and subtraction test
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "mpi.h"
int
main(int argc, char *argv[])
{
mp_int a, b, c;
if (argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]);
return 1;
}
printf("Test 2: Basic addition and subtraction\n\n");
mp_init(&a);
mp_init(&b);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
printf("a = ");
mp_print(&a, stdout);
fputc('\n', stdout);
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
mp_init(&c);
printf("c = a + b\n");
mp_add(&a, &b, &c);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("c = a - b\n");
mp_sub(&a, &b, &c);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mp_clear(&c);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View file

@ -1,105 +0,0 @@
/*
* Simple test driver for MPI library
*
* Test 3: Multiplication, division, and exponentiation test
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#include "mpi.h"
#define EXPT 0 /* define nonzero to get exponentiate test */
int
main(int argc, char *argv[])
{
int ix;
mp_int a, b, c, d;
mp_digit r;
mp_err res;
if (argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]);
return 1;
}
printf("Test 3: Multiplication and division\n\n");
srand(time(NULL));
mp_init(&a);
mp_init(&b);
mp_read_variable_radix(&a, argv[1], 10);
mp_read_variable_radix(&b, argv[2], 10);
printf("a = ");
mp_print(&a, stdout);
fputc('\n', stdout);
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
mp_init(&c);
printf("\nc = a * b\n");
mp_mul(&a, &b, &c);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("\nc = b * 32523\n");
mp_mul_d(&b, 32523, &c);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mp_init(&d);
printf("\nc = a / b, d = a mod b\n");
mp_div(&a, &b, &c, &d);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("d = ");
mp_print(&d, stdout);
fputc('\n', stdout);
ix = rand() % 256;
printf("\nc = a / %d, r = a mod %d\n", ix, ix);
mp_div_d(&a, (mp_digit)ix, &c, &r);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("r = %04X\n", r);
#if EXPT
printf("\nc = a ** b\n");
mp_expt(&a, &b, &c);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
#endif
ix = rand() % 256;
printf("\nc = 2^%d\n", ix);
mp_2expt(&c, ix);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mp_clear(&d);
mp_clear(&c);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View file

@ -1,123 +0,0 @@
/*
* Simple test driver for MPI library
*
* Test 3a: Multiplication vs. squaring timing test
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#include "mpi.h"
#include "mpprime.h"
int
main(int argc, char *argv[])
{
int ix, num, prec = 8;
double d1, d2;
clock_t start, finish;
time_t seed;
mp_int a, c, d;
seed = time(NULL);
if (argc < 2) {
fprintf(stderr, "Usage: %s <num-tests> [<precision>]\n", argv[0]);
return 1;
}
if ((num = atoi(argv[1])) < 0)
num = -num;
if (!num) {
fprintf(stderr, "%s: must perform at least 1 test\n", argv[0]);
return 1;
}
if (argc > 2) {
if ((prec = atoi(argv[2])) <= 0)
prec = 8;
else
prec = (prec + (DIGIT_BIT - 1)) / DIGIT_BIT;
}
printf("Test 3a: Multiplication vs squaring timing test\n"
"Precision: %d digits (%u bits)\n"
"# of tests: %d\n\n",
prec, prec * DIGIT_BIT, num);
mp_init_size(&a, prec);
mp_init(&c);
mp_init(&d);
printf("Verifying accuracy ... \n");
srand((unsigned int)seed);
for (ix = 0; ix < num; ix++) {
mpp_random_size(&a, prec);
mp_mul(&a, &a, &c);
mp_sqr(&a, &d);
if (mp_cmp(&c, &d) != 0) {
printf("Error! Results not accurate:\n");
printf("a = ");
mp_print(&a, stdout);
fputc('\n', stdout);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("d = ");
mp_print(&d, stdout);
fputc('\n', stdout);
mp_sub(&c, &d, &d);
printf("dif ");
mp_print(&d, stdout);
fputc('\n', stdout);
mp_clear(&c);
mp_clear(&d);
mp_clear(&a);
return 1;
}
}
printf("Accuracy is confirmed for the %d test samples\n", num);
mp_clear(&d);
printf("Testing squaring ... \n");
srand((unsigned int)seed);
start = clock();
for (ix = 0; ix < num; ix++) {
mpp_random_size(&a, prec);
mp_sqr(&a, &c);
}
finish = clock();
d2 = (double)(finish - start) / CLOCKS_PER_SEC;
printf("Testing multiplication ... \n");
srand((unsigned int)seed);
start = clock();
for (ix = 0; ix < num; ix++) {
mpp_random(&a);
mp_mul(&a, &a, &c);
}
finish = clock();
d1 = (double)(finish - start) / CLOCKS_PER_SEC;
printf("Multiplication time: %.3f sec (%.3f each)\n", d1, d1 / num);
printf("Squaring time: %.3f sec (%.3f each)\n", d2, d2 / num);
printf("Improvement: %.2f%%\n", (1.0 - (d2 / d1)) * 100.0);
mp_clear(&c);
mp_clear(&a);
return 0;
}

View file

@ -1,111 +0,0 @@
/*
* Simple test driver for MPI library
*
* Test 4: Modular arithmetic tests
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "mpi.h"
int
main(int argc, char *argv[])
{
int ix;
mp_int a, b, c, m;
mp_digit r;
if (argc < 4) {
fprintf(stderr, "Usage: %s <a> <b> <m>\n", argv[0]);
return 1;
}
printf("Test 4: Modular arithmetic\n\n");
mp_init(&a);
mp_init(&b);
mp_init(&m);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
mp_read_radix(&m, argv[3], 10);
printf("a = ");
mp_print(&a, stdout);
fputc('\n', stdout);
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
printf("m = ");
mp_print(&m, stdout);
fputc('\n', stdout);
mp_init(&c);
printf("\nc = a (mod m)\n");
mp_mod(&a, &m, &c);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("\nc = b (mod m)\n");
mp_mod(&b, &m, &c);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("\nc = b (mod 1853)\n");
mp_mod_d(&b, 1853, &r);
printf("c = %04X\n", r);
printf("\nc = (a + b) mod m\n");
mp_addmod(&a, &b, &m, &c);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("\nc = (a - b) mod m\n");
mp_submod(&a, &b, &m, &c);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("\nc = (a * b) mod m\n");
mp_mulmod(&a, &b, &m, &c);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("\nc = (a ** b) mod m\n");
mp_exptmod(&a, &b, &m, &c);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("\nIn-place modular squaring test:\n");
for (ix = 0; ix < 5; ix++) {
printf("a = (a * a) mod m a = ");
mp_sqrmod(&a, &m, &a);
mp_print(&a, stdout);
fputc('\n', stdout);
}
mp_clear(&c);
mp_clear(&m);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View file

@ -1,109 +0,0 @@
/*
* mptest4a - modular exponentiation speed test
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include "mpi.h"
#include "mpprime.h"
typedef struct {
unsigned int sec;
unsigned int usec;
} instant_t;
instant_t
now(void)
{
struct timeval clk;
instant_t res;
res.sec = res.usec = 0;
if (gettimeofday(&clk, NULL) != 0)
return res;
res.sec = clk.tv_sec;
res.usec = clk.tv_usec;
return res;
}
extern mp_err s_mp_pad();
int
main(int argc, char *argv[])
{
int ix, num, prec = 8;
unsigned int d;
instant_t start, finish;
time_t seed;
mp_int a, m, c;
seed = time(NULL);
if (argc < 2) {
fprintf(stderr, "Usage: %s <num-tests> [<precision>]\n", argv[0]);
return 1;
}
if ((num = atoi(argv[1])) < 0)
num = -num;
if (!num) {
fprintf(stderr, "%s: must perform at least 1 test\n", argv[0]);
return 1;
}
if (argc > 2) {
if ((prec = atoi(argv[2])) <= 0)
prec = 8;
}
printf("Test 3a: Modular exponentiation timing test\n"
"Precision: %d digits (%d bits)\n"
"# of tests: %d\n\n",
prec, prec * DIGIT_BIT, num);
mp_init_size(&a, prec);
mp_init_size(&m, prec);
mp_init_size(&c, prec);
s_mp_pad(&a, prec);
s_mp_pad(&m, prec);
s_mp_pad(&c, prec);
printf("Testing modular exponentiation ... \n");
srand((unsigned int)seed);
start = now();
for (ix = 0; ix < num; ix++) {
mpp_random(&a);
mpp_random(&c);
mpp_random(&m);
mp_exptmod(&a, &c, &m, &c);
}
finish = now();
d = (finish.sec - start.sec) * 1000000;
d -= start.usec;
d += finish.usec;
printf("Total time elapsed: %u usec\n", d);
printf("Time per exponentiation: %u usec (%.3f sec)\n",
(d / num), (double)(d / num) / 1000000);
mp_clear(&c);
mp_clear(&a);
mp_clear(&m);
return 0;
}

View file

@ -1,107 +0,0 @@
/*
* mptest-4b.c
*
* Test speed of a large modular exponentiation of a primitive element
* modulo a prime.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include "mpi.h"
#include "mpprime.h"
char *g_prime =
"34BD53C07350E817CCD49721020F1754527959C421C1533244769D4CF060A8B1C3DA"
"25094BE723FB1E2369B55FEEBBE0FAC16425161BF82684062B5EC5D7D47D1B23C117"
"0FA19745E44A55E148314E582EB813AC9EE5126295E2E380CACC2F6D206B293E5ED9"
"23B54EE961A8C69CD625CE4EC38B70C649D7F014432AEF3A1C93";
char *g_gen = "5";
typedef struct {
unsigned int sec;
unsigned int usec;
} instant_t;
instant_t
now(void)
{
struct timeval clk;
instant_t res;
res.sec = res.usec = 0;
if (gettimeofday(&clk, NULL) != 0)
return res;
res.sec = clk.tv_sec;
res.usec = clk.tv_usec;
return res;
}
extern mp_err s_mp_pad();
int
main(int argc, char *argv[])
{
instant_t start, finish;
mp_int prime, gen, expt, res;
unsigned int ix, diff;
int num;
srand(time(NULL));
if (argc < 2) {
fprintf(stderr, "Usage: %s <num-tests>\n", argv[0]);
return 1;
}
if ((num = atoi(argv[1])) < 0)
num = -num;
if (num == 0)
++num;
mp_init(&prime);
mp_init(&gen);
mp_init(&res);
mp_read_radix(&prime, g_prime, 16);
mp_read_radix(&gen, g_gen, 16);
mp_init_size(&expt, USED(&prime) - 1);
s_mp_pad(&expt, USED(&prime) - 1);
printf("Testing %d modular exponentations ... \n", num);
start = now();
for (ix = 0; ix < num; ix++) {
mpp_random(&expt);
mp_exptmod(&gen, &expt, &prime, &res);
}
finish = now();
diff = (finish.sec - start.sec) * 1000000;
diff += finish.usec;
diff -= start.usec;
printf("%d operations took %u usec (%.3f sec)\n",
num, diff, (double)diff / 1000000.0);
printf("That is %.3f sec per operation.\n",
((double)diff / 1000000.0) / num);
mp_clear(&expt);
mp_clear(&res);
mp_clear(&gen);
mp_clear(&prime);
return 0;
}

View file

@ -1,85 +0,0 @@
/*
* Simple test driver for MPI library
*
* Test 5: Other number theoretic functions
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "mpi.h"
int
main(int argc, char *argv[])
{
mp_int a, b, c, x, y;
if (argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]);
return 1;
}
printf("Test 5: Number theoretic functions\n\n");
mp_init(&a);
mp_init(&b);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
printf("a = ");
mp_print(&a, stdout);
fputc('\n', stdout);
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
mp_init(&c);
printf("\nc = (a, b)\n");
mp_gcd(&a, &b, &c);
printf("Euclid: c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
/*
mp_bgcd(&a, &b, &c);
printf("Binary: c = "); mp_print(&c, stdout); fputc('\n', stdout);
*/
mp_init(&x);
mp_init(&y);
printf("\nc = (a, b) = ax + by\n");
mp_xgcd(&a, &b, &c, &x, &y);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("x = ");
mp_print(&x, stdout);
fputc('\n', stdout);
printf("y = ");
mp_print(&y, stdout);
fputc('\n', stdout);
printf("\nc = a^-1 (mod b)\n");
if (mp_invmod(&a, &b, &c) == MP_UNDEF) {
printf("a has no inverse mod b\n");
} else {
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
}
mp_clear(&y);
mp_clear(&x);
mp_clear(&c);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View file

@ -1,147 +0,0 @@
/*
* Simple test driver for MPI library
*
* Test 5a: Greatest common divisor speed test, binary vs. Euclid
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#include <sys/time.h>
#include "mpi.h"
#include "mpprime.h"
typedef struct {
unsigned int sec;
unsigned int usec;
} instant_t;
instant_t
now(void)
{
struct timeval clk;
instant_t res;
res.sec = res.usec = 0;
if (gettimeofday(&clk, NULL) != 0)
return res;
res.sec = clk.tv_sec;
res.usec = clk.tv_usec;
return res;
}
#define PRECISION 16
int
main(int argc, char *argv[])
{
int ix, num, prec = PRECISION;
mp_int a, b, c, d;
instant_t start, finish;
time_t seed;
unsigned int d1, d2;
seed = time(NULL);
if (argc < 2) {
fprintf(stderr, "Usage: %s <num-tests>\n", argv[0]);
return 1;
}
if ((num = atoi(argv[1])) < 0)
num = -num;
printf("Test 5a: Euclid vs. Binary, a GCD speed test\n\n"
"Number of tests: %d\n"
"Precision: %d digits\n\n",
num, prec);
mp_init_size(&a, prec);
mp_init_size(&b, prec);
mp_init(&c);
mp_init(&d);
printf("Verifying accuracy ... \n");
srand((unsigned int)seed);
for (ix = 0; ix < num; ix++) {
mpp_random_size(&a, prec);
mpp_random_size(&b, prec);
mp_gcd(&a, &b, &c);
mp_bgcd(&a, &b, &d);
if (mp_cmp(&c, &d) != 0) {
printf("Error! Results not accurate:\n");
printf("a = ");
mp_print(&a, stdout);
fputc('\n', stdout);
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("d = ");
mp_print(&d, stdout);
fputc('\n', stdout);
mp_clear(&a);
mp_clear(&b);
mp_clear(&c);
mp_clear(&d);
return 1;
}
}
mp_clear(&d);
printf("Accuracy confirmed for the %d test samples\n", num);
printf("Testing Euclid ... \n");
srand((unsigned int)seed);
start = now();
for (ix = 0; ix < num; ix++) {
mpp_random_size(&a, prec);
mpp_random_size(&b, prec);
mp_gcd(&a, &b, &c);
}
finish = now();
d1 = (finish.sec - start.sec) * 1000000;
d1 -= start.usec;
d1 += finish.usec;
printf("Testing binary ... \n");
srand((unsigned int)seed);
start = now();
for (ix = 0; ix < num; ix++) {
mpp_random_size(&a, prec);
mpp_random_size(&b, prec);
mp_bgcd(&a, &b, &c);
}
finish = now();
d2 = (finish.sec - start.sec) * 1000000;
d2 -= start.usec;
d2 += finish.usec;
printf("Euclidean algorithm time: %u usec\n", d1);
printf("Binary algorithm time: %u usec\n", d2);
printf("Improvement: %.2f%%\n",
(1.0 - ((double)d2 / (double)d1)) * 100.0);
mp_clear(&c);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View file

@ -1,78 +0,0 @@
/*
* Simple test driver for MPI library
*
* Test 6: Output functions
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "mpi.h"
void
print_buf(FILE *ofp, char *buf, int len)
{
int ix, brk = 0;
for (ix = 0; ix < len; ix++) {
fprintf(ofp, "%02X ", buf[ix]);
brk = (brk + 1) & 0xF;
if (!brk)
fputc('\n', ofp);
}
if (brk)
fputc('\n', ofp);
}
int
main(int argc, char *argv[])
{
int ix, size;
mp_int a;
char *buf;
if (argc < 2) {
fprintf(stderr, "Usage: %s <a>\n", argv[0]);
return 1;
}
printf("Test 6: Output functions\n\n");
mp_init(&a);
mp_read_radix(&a, argv[1], 10);
printf("\nConverting to a string:\n");
printf("Rx Size Representation\n");
for (ix = 2; ix <= MAX_RADIX; ix++) {
size = mp_radix_size(&a, ix);
buf = calloc(size, sizeof(char));
mp_toradix(&a, buf, ix);
printf("%2d: %3d: %s\n", ix, size, buf);
free(buf);
}
printf("\nRaw output:\n");
size = mp_raw_size(&a);
buf = calloc(size, sizeof(char));
printf("Size: %d bytes\n", size);
mp_toraw(&a, buf);
print_buf(stdout, buf, size);
free(buf);
mp_clear(&a);
return 0;
}

View file

@ -1,85 +0,0 @@
/*
* Simple test driver for MPI library
*
* Test 7: Random and divisibility tests
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#define MP_IOFUNC 1
#include "mpi.h"
#include "mpprime.h"
int
main(int argc, char *argv[])
{
mp_digit num;
mp_int a, b;
srand(time(NULL));
if (argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]);
return 1;
}
printf("Test 7: Random & divisibility tests\n\n");
mp_init(&a);
mp_init(&b);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
printf("a = ");
mp_print(&a, stdout);
fputc('\n', stdout);
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
if (mpp_divis(&a, &b) == MP_YES)
printf("a is divisible by b\n");
else
printf("a is not divisible by b\n");
if (mpp_divis(&b, &a) == MP_YES)
printf("b is divisible by a\n");
else
printf("b is not divisible by a\n");
printf("\nb = mpp_random()\n");
mpp_random(&b);
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
mpp_random(&b);
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
mpp_random(&b);
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
printf("\nTesting a for divisibility by first 170 primes\n");
num = 170;
if (mpp_divis_primes(&a, &num) == MP_YES)
printf("It is divisible by at least one of them\n");
else
printf("It is not divisible by any of them\n");
mp_clear(&b);
mp_clear(&a);
return 0;
}

View file

@ -1,68 +0,0 @@
/*
* Simple test driver for MPI library
*
* Test 8: Probabilistic primality tester
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#define MP_IOFUNC 1
#include "mpi.h"
#include "mpprime.h"
int
main(int argc, char *argv[])
{
int ix;
mp_digit num;
mp_int a;
srand(time(NULL));
if (argc < 2) {
fprintf(stderr, "Usage: %s <a>\n", argv[0]);
return 1;
}
printf("Test 8: Probabilistic primality testing\n\n");
mp_init(&a);
mp_read_radix(&a, argv[1], 10);
printf("a = ");
mp_print(&a, stdout);
fputc('\n', stdout);
printf("\nChecking for divisibility by small primes ... \n");
num = 170;
if (mpp_divis_primes(&a, &num) == MP_YES) {
printf("it is not prime\n");
goto CLEANUP;
}
printf("Passed that test (not divisible by any small primes).\n");
for (ix = 0; ix < 10; ix++) {
printf("\nPerforming Rabin-Miller test, iteration %d\n", ix + 1);
if (mpp_pprime(&a, 5) == MP_NO) {
printf("it is not prime\n");
goto CLEANUP;
}
}
printf("All tests passed; a is probably prime\n");
CLEANUP:
mp_clear(&a);
return 0;
}

View file

@ -1,109 +0,0 @@
/*
* mptest-9.c
*
* Test logical functions
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include <time.h>
#include "mpi.h"
#include "mplogic.h"
int
main(int argc, char *argv[])
{
mp_int a, b, c;
int pco;
mp_err res;
printf("Test 9: Logical functions\n\n");
if (argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", argv[0]);
return 1;
}
mp_init(&a);
mp_init(&b);
mp_init(&c);
mp_read_radix(&a, argv[1], 16);
mp_read_radix(&b, argv[2], 16);
printf("a = ");
mp_print(&a, stdout);
fputc('\n', stdout);
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
mpl_not(&a, &c);
printf("~a = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mpl_and(&a, &b, &c);
printf("a & b = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mpl_or(&a, &b, &c);
printf("a | b = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mpl_xor(&a, &b, &c);
printf("a ^ b = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mpl_rsh(&a, &c, 1);
printf("a >> 1 = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mpl_rsh(&a, &c, 5);
printf("a >> 5 = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mpl_rsh(&a, &c, 16);
printf("a >> 16 = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mpl_lsh(&a, &c, 1);
printf("a << 1 = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mpl_lsh(&a, &c, 5);
printf("a << 5 = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mpl_lsh(&a, &c, 16);
printf("a << 16 = ");
mp_print(&c, stdout);
fputc('\n', stdout);
mpl_num_set(&a, &pco);
printf("population(a) = %d\n", pco);
mpl_num_set(&b, &pco);
printf("population(b) = %d\n", pco);
res = mpl_parity(&a);
if (res == MP_EVEN)
printf("a has even parity\n");
else
printf("a has odd parity\n");
mp_clear(&c);
mp_clear(&b);
mp_clear(&a);
return 0;
}

View file

@ -1,230 +0,0 @@
/*
* Simple test driver for MPI library
*
* Test GF2m: Binary Polynomial Arithmetic
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <limits.h>
#include "mp_gf2m.h"
int
main(int argc, char *argv[])
{
int ix;
mp_int pp, a, b, x, y, order;
mp_int c, d, e;
mp_digit r;
mp_err res;
unsigned int p[] = { 163, 7, 6, 3, 0 };
unsigned int ptemp[10];
printf("Test b: Binary Polynomial Arithmetic\n\n");
mp_init(&pp);
mp_init(&a);
mp_init(&b);
mp_init(&x);
mp_init(&y);
mp_init(&order);
mp_read_radix(&pp, "0800000000000000000000000000000000000000C9", 16);
mp_read_radix(&a, "1", 16);
mp_read_radix(&b, "020A601907B8C953CA1481EB10512F78744A3205FD", 16);
mp_read_radix(&x, "03F0EBA16286A2D57EA0991168D4994637E8343E36", 16);
mp_read_radix(&y, "00D51FBC6C71A0094FA2CDD545B11C5C0C797324F1", 16);
mp_read_radix(&order, "040000000000000000000292FE77E70C12A4234C33", 16);
printf("pp = ");
mp_print(&pp, stdout);
fputc('\n', stdout);
printf("a = ");
mp_print(&a, stdout);
fputc('\n', stdout);
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
printf("x = ");
mp_print(&x, stdout);
fputc('\n', stdout);
printf("y = ");
mp_print(&y, stdout);
fputc('\n', stdout);
printf("order = ");
mp_print(&order, stdout);
fputc('\n', stdout);
mp_init(&c);
mp_init(&d);
mp_init(&e);
/* Test polynomial conversion */
ix = mp_bpoly2arr(&pp, ptemp, 10);
if (
(ix != 5) ||
(ptemp[0] != p[0]) ||
(ptemp[1] != p[1]) ||
(ptemp[2] != p[2]) ||
(ptemp[3] != p[3]) ||
(ptemp[4] != p[4])) {
printf("Polynomial to array conversion not correct\n");
return -1;
}
printf("Polynomial conversion test #1 successful.\n");
MP_CHECKOK(mp_barr2poly(p, &c));
if (mp_cmp(&pp, &c) != 0) {
printf("Array to polynomial conversion not correct\n");
return -1;
}
printf("Polynomial conversion test #2 successful.\n");
/* Test addition */
MP_CHECKOK(mp_badd(&a, &a, &c));
if (mp_cmp_z(&c) != 0) {
printf("a+a should equal zero\n");
return -1;
}
printf("Addition test #1 successful.\n");
MP_CHECKOK(mp_badd(&a, &b, &c));
MP_CHECKOK(mp_badd(&b, &c, &c));
if (mp_cmp(&c, &a) != 0) {
printf("c = (a + b) + b should equal a\n");
printf("a = ");
mp_print(&a, stdout);
fputc('\n', stdout);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
return -1;
}
printf("Addition test #2 successful.\n");
/* Test multiplication */
mp_set(&c, 2);
MP_CHECKOK(mp_bmul(&b, &c, &c));
MP_CHECKOK(mp_badd(&b, &c, &c));
mp_set(&d, 3);
MP_CHECKOK(mp_bmul(&b, &d, &d));
if (mp_cmp(&c, &d) != 0) {
printf("c = (2 * b) + b should equal c = 3 * b\n");
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("d = ");
mp_print(&d, stdout);
fputc('\n', stdout);
return -1;
}
printf("Multiplication test #1 successful.\n");
/* Test modular reduction */
MP_CHECKOK(mp_bmod(&b, p, &c));
if (mp_cmp(&b, &c) != 0) {
printf("c = b mod p should equal b\n");
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
return -1;
}
printf("Modular reduction test #1 successful.\n");
MP_CHECKOK(mp_badd(&b, &pp, &c));
MP_CHECKOK(mp_bmod(&c, p, &c));
if (mp_cmp(&b, &c) != 0) {
printf("c = (b + p) mod p should equal b\n");
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
return -1;
}
printf("Modular reduction test #2 successful.\n");
MP_CHECKOK(mp_bmul(&b, &pp, &c));
MP_CHECKOK(mp_bmod(&c, p, &c));
if (mp_cmp_z(&c) != 0) {
printf("c = (b * p) mod p should equal 0\n");
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
return -1;
}
printf("Modular reduction test #3 successful.\n");
/* Test modular multiplication */
MP_CHECKOK(mp_bmulmod(&b, &pp, p, &c));
if (mp_cmp_z(&c) != 0) {
printf("c = (b * p) mod p should equal 0\n");
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
return -1;
}
printf("Modular multiplication test #1 successful.\n");
mp_set(&c, 1);
MP_CHECKOK(mp_badd(&pp, &c, &c));
MP_CHECKOK(mp_bmulmod(&b, &c, p, &c));
if (mp_cmp(&b, &c) != 0) {
printf("c = (b * (p + 1)) mod p should equal b\n");
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
return -1;
}
printf("Modular multiplication test #2 successful.\n");
/* Test modular squaring */
MP_CHECKOK(mp_copy(&b, &c));
MP_CHECKOK(mp_bmulmod(&b, &c, p, &c));
MP_CHECKOK(mp_bsqrmod(&b, p, &d));
if (mp_cmp(&c, &d) != 0) {
printf("c = (b * b) mod p should equal d = b^2 mod p\n");
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
printf("d = ");
mp_print(&d, stdout);
fputc('\n', stdout);
return -1;
}
printf("Modular squaring test #1 successful.\n");
/* Test modular division */
MP_CHECKOK(mp_bdivmod(&b, &x, &pp, p, &c));
MP_CHECKOK(mp_bmulmod(&c, &x, p, &c));
if (mp_cmp(&b, &c) != 0) {
printf("c = (b / x) * x mod p should equal b\n");
printf("b = ");
mp_print(&b, stdout);
fputc('\n', stdout);
printf("c = ");
mp_print(&c, stdout);
fputc('\n', stdout);
return -1;
}
printf("Modular division test #1 successful.\n");
CLEANUP:
mp_clear(&order);
mp_clear(&y);
mp_clear(&x);
mp_clear(&b);
mp_clear(&a);
mp_clear(&pp);
return 0;
}

View file

@ -1 +0,0 @@
31415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303819644288109756659334461284756482337867831652712019091456485669234603486104543266482133936072602491412737245870066063155881748815209209628292540917153643678925903600113305305488204665213841469519415116094330572703657595919530921861173819326117931051185480744623799627495673518857527248912279381830119491298336733624406566430860213949463952247371907021798609437027705392171762931767523846748184676694051320005681271452635608277857713427577896091736371787214684409012249534301465495853710507922796892589235420199561121290219608640344181598136297747713099605187072113499999983729780499510597317328160963185950244594553469083026425223082533446850352619311881710100031378387528865875332083814206171776691473035982534904287554687311595628638823537875937519577818577805321712268066130019278766111959092164201989

View file

@ -1 +0,0 @@
314159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912983367336244065664308602139494639522473719070217986094370277053921717629317675238467481846766940513200056812714526356082778577134275778960917363717872146844090122495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859502445945534690830264252230825334468503526193118817101000313783875288658753320838142061717766914730359825349042875546873115956286388235378759375195778185778053217122680661300192787661119590921642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151557485724245415069595082953311686172785588907509838175463746493931925506040092770167113900984882401285836160356370766010471018194295559619894676783744944825537977472684710404753464620804668425906949129331367702898915210475216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992458631503028618297455570674983850549458858692699569092721079750930295532116534498720275596023648066549911988183479775356636980742654252786255181841757467289097777279380008164706001614524919217321721477235014144197356854816136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179049460165346680498862723279178608578438382796797668145410095388378636095068006422512520511739298489608412848862694560424196528502221066118630674427862203919494504712371378696095636437191728746776465757396241389086583264599581339047802759010

File diff suppressed because one or more lines are too long

View file

@ -1,99 +0,0 @@
#!/bin/sh
# Simple timing test for the MPI library. Basically, we use prime
# generation as a timing test, since it exercises most of the pathways
# of the library fairly heavily. The 'primegen' tool outputs a line
# summarizing timing results. We gather these and process them for
# statistical information, which is collected into a file.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# Avoid using built-in shell echoes
ECHO=/bin/echo
MAKE=gmake
PERL=perl
# Use a fixed seed so timings will be more consistent
# This one is the 11th-18th decimal digits of 'e'
#export SEED=45904523
SEED=45904523; export SEED
#------------------------------------------------------------------------
$ECHO "\n** Running timing tests for MPI library\n"
$ECHO "Bringing 'metime' up to date ... "
if $MAKE metime ; then
:
else
$ECHO "\nMake failed to build metime.\n"
exit 1
fi
if [ ! -x ./metime ] ; then
$ECHO "\nCannot find 'metime' program, testing cannot continue.\n"
exit 1
fi
#------------------------------------------------------------------------
$ECHO "Bringing 'primegen' up to date ... "
if $MAKE primegen ; then
:
else
$ECHO "\nMake failed to build primegen.\n"
exit 1
fi
if [ ! -x ./primegen ] ; then
$ECHO "\nCannot find 'primegen' program, testing cannot continue.\n"
exit 1
fi
#------------------------------------------------------------------------
rm -f timing-results.txt
touch timing-results.txt
sizes="256 512 1024 2048"
ntests=10
trap 'echo "oop!";rm -f tt*.tmp timing-results.txt;exit 0' INT HUP
$ECHO "\n-- Modular exponentiation\n"
$ECHO "Modular exponentiation:" >> timing-results.txt
$ECHO "Running $ntests modular exponentiations per test:"
for size in $sizes ; do
$ECHO "- Gathering statistics for $size bits ... "
secs=`./metime $ntests $size | tail -1 | awk '{print $2}'`
$ECHO "$size: " $secs " seconds per op" >> timing-results.txt
tail -1 timing-results.txt
done
$ECHO "<done>";
sizes="256 512 1024"
ntests=1
$ECHO "\n-- Prime generation\n"
$ECHO "Prime generation:" >> timing-results.txt
$ECHO "Generating $ntests prime values per test:"
for size in $sizes ; do
$ECHO "- Gathering statistics for $size bits ... "
./primegen $size $ntests | grep ticks | awk '{print $7}' | tr -d '(' > tt$$.tmp
$ECHO "$size:" >> timing-results.txt
$PERL stats tt$$.tmp >> timing-results.txt
tail -1 timing-results.txt
rm -f tt$$.tmp
done
$ECHO "<done>"
trap 'rm -f tt*.tmp timing-results.txt' INT HUP
exit 0

View file

@ -1,127 +0,0 @@
#!/usr/bin/perl
#
# types.pl - find recommended type definitions for digits and words
#
# This script scans the Makefile for the C compiler and compilation
# flags currently in use, and using this combination, attempts to
# compile a simple test program that outputs the sizes of the various
# unsigned integer types, in bytes. Armed with these, it finds all
# the "viable" type combinations for mp_digit and mp_word, where
# viability is defined by the requirement that mp_word be at least two
# times the precision of mp_digit.
#
# Of these, the one with the largest digit size is chosen, and
# appropriate typedef statements are written to standard output.
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
@_=split(/\//,$0);chomp($prog=pop(@_));
# The array of integer types to be considered...
@TYPES = (
"unsigned char",
"unsigned short",
"unsigned int",
"unsigned long"
);
# Macro names for the maximum unsigned value of each type
%TMAX = (
"unsigned char" => "UCHAR_MAX",
"unsigned short" => "USHRT_MAX",
"unsigned int" => "UINT_MAX",
"unsigned long" => "ULONG_MAX"
);
# Read the Makefile to find out which C compiler to use
open(MFP, "<Makefile") or die "$prog: Makefile: $!\n";
while(<MFP>) {
chomp;
if(/^CC=(.*)$/) {
$cc = $1;
last if $cflags;
} elsif(/^CFLAGS=(.*)$/) {
$cflags = $1;
last if $cc;
}
}
close(MFP);
# If we couldn't find that, use 'cc' by default
$cc = "cc" unless $cc;
printf STDERR "Using '%s' as the C compiler.\n", $cc;
print STDERR "Determining type sizes ... \n";
open(OFP, ">tc$$.c") or die "$prog: tc$$.c: $!\n";
print OFP "#include <stdio.h>\n\nint main(void)\n{\n";
foreach $type (@TYPES) {
printf OFP "\tprintf(\"%%d\\n\", (int)sizeof(%s));\n", $type;
}
print OFP "\n\treturn 0;\n}\n";
close(OFP);
system("$cc $cflags -o tc$$ tc$$.c");
die "$prog: unable to build test program\n" unless(-x "tc$$");
open(IFP, "./tc$$|") or die "$prog: can't execute test program\n";
$ix = 0;
while(<IFP>) {
chomp;
$size{$TYPES[$ix++]} = $_;
}
close(IFP);
unlink("tc$$");
unlink("tc$$.c");
print STDERR "Selecting viable combinations ... \n";
while(($type, $size) = each(%size)) {
push(@ts, [ $size, $type ]);
}
# Sort them ascending by size
@ts = sort { $a->[0] <=> $b->[0] } @ts;
# Try all possible combinations, finding pairs in which the word size
# is twice the digit size. The number of possible pairs is too small
# to bother doing this more efficiently than by brute force
for($ix = 0; $ix <= $#ts; $ix++) {
$w = $ts[$ix];
for($jx = 0; $jx <= $#ts; $jx++) {
$d = $ts[$jx];
if($w->[0] == 2 * $d->[0]) {
push(@valid, [ $d, $w ]);
}
}
}
# Sort descending by digit size
@valid = sort { $b->[0]->[0] <=> $a->[0]->[0] } @valid;
# Select the maximum as the recommended combination
$rec = shift(@valid);
printf("typedef %-18s mp_sign;\n", "char");
printf("typedef %-18s mp_digit; /* %d byte type */\n",
$rec->[0]->[1], $rec->[0]->[0]);
printf("typedef %-18s mp_word; /* %d byte type */\n",
$rec->[1]->[1], $rec->[1]->[0]);
printf("typedef %-18s mp_size;\n", "unsigned int");
printf("typedef %-18s mp_err;\n\n", "int");
printf("#define %-18s (CHAR_BIT*sizeof(mp_digit))\n", "DIGIT_BIT");
printf("#define %-18s %s\n", "DIGIT_MAX", $TMAX{$rec->[0]->[1]});
printf("#define %-18s (CHAR_BIT*sizeof(mp_word))\n", "MP_WORD_BIT");
printf("#define %-18s %s\n\n", "MP_WORD_MAX", $TMAX{$rec->[1]->[1]});
printf("#define %-18s (DIGIT_MAX+1)\n\n", "RADIX");
printf("#define %-18s \"%%0%dX\"\n", "DIGIT_FMT", (2 * $rec->[0]->[0]));
exit 0;

View file

@ -1,4 +0,0 @@
Within this directory, each of the file listed below is licensed under
the terms given in the file LICENSE-MPL, also in this directory.
PRIMES

View file

@ -1,3 +0,0 @@
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.

View file

@ -1,41 +0,0 @@
Probable primes (sorted by number of significant bits)
128: 81386202757205669562183851789305348631
128: 180241813863264101444573802809858694397
128: 245274683055224433281596312431122059021
128: 187522309397665259809392608791686659539
256: 83252422946206411852330647237287722547866360773229941071371588246436\
513990159
256: 79132571131322331023736933767063051273085304521895229780914612117520\
058517909
256: 72081815425552909748220041100909735706208853818662000557743644603407\
965465527
256: 87504602391905701494845474079163412737334477797316409702279059573654\
274811271
512: 12233064210800062190450937494718705259777386009095453001870729392786\
63450255179083524798507997690270500580265258111668148238355016411719\
9168737693316468563
512: 12003639081420725322369909586347545220275253633035565716386136197501\
88208318984400479275215620499883521216480724155582768193682335576385\
2069481074929084063
1024: 16467877625718912296741904171202513097057724053648819680815842057593\
20371835940722471475475803725455063836431454757000451907612224427007\
63984592414360595161051906727075047683803534852982766542661204179549\
77327573530800542562611753617736693359790119074768292178493884576587\
0230450429880021317876149636714743053
1024: 16602953991090311275234291158294516471009930684624948451178742895360\
86073703307475884280944414508444679430090561246728195735962931545473\
40743240318558456247740186704660778277799687988031119436541068736925\
20563780233711166724859277827382391527748470939542560819625727876091\
5372193745283891895989104479029844957

View file

@ -1,206 +0,0 @@
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
Additional MPI utilities
------------------------
The files 'mpprime.h' and 'mpprime.c' define some useful extensions to
the MPI library for dealing with prime numbers (in particular, testing
for divisbility, and the Rabin-Miller probabilistic primality test).
The files 'mplogic.h' and 'mplogic.c' define extensions to the MPI
library for doing bitwise logical operations and shifting.
This document assumes you have read the help file for the MPI library
and understand its conventions.
Divisibility (mpprime.h)
------------
To test a number for divisibility by another number:
mpp_divis(a, b) - test if b|a
mpp_divis_d(a, d) - test if d|a
Each of these functions returns MP_YES if its initial argument is
divisible by its second, or MP_NO if it is not. Other errors may be
returned as appropriate (such as MP_RANGE if you try to test for
divisibility by zero).
Randomness (mpprime.h)
----------
To generate random data:
mpp_random(a) - fill a with random data
mpp_random_size(a, p) - fill a with p digits of random data
The mpp_random_size() function increases the precision of a to at
least p, then fills all those digits randomly. The mp_random()
function fills a to its current precision (as determined by the number
of significant digits, USED(a))
Note that these functions simply use the C library's rand() function
to fill a with random digits up to its precision. This should be
adequate for primality testing, but should not be used for
cryptographic applications where truly random values are required for
security.
You should call srand() in your driver program in order to seed the
random generator; this function doesn't call it.
Primality Testing (mpprime.h)
-----------------
mpp_divis_vector(a, v, s, w) - is a divisible by any of the s values
in v, and if so, w = which.
mpp_divis_primes(a, np) - is a divisible by any of the first np primes?
mpp_fermat(a, w) - is a pseudoprime with respect to witness w?
mpp_pprime(a, nt) - run nt iterations of Rabin-Miller on a.
The mpp_divis_vector() function tests a for divisibility by each
member of an array of digits. The array is v, the size of that array
is s. Returns MP_YES if a is divisible, and stores the index of the
offending digit in w. Returns MP_NO if a is not divisible by any of
the digits in the array.
A small table of primes is compiled into the library (typically the
first 128 primes, although you can change this by editing the file
'primes.c' before you build). The global variable prime_tab_size
contains the number of primes in the table, and the values themselves
are in the array prime_tab[], which is an array of mp_digit.
The mpp_divis_primes() function is basically just a wrapper around
mpp_divis_vector() that uses prime_tab[] as the test vector. The np
parameter is a pointer to an mp_digit -- on input, it should specify
the number of primes to be tested against. If a is divisible by any
of the primes, MP_YES is returned and np is given the prime value that
divided a (you can use this if you're factoring, for example).
Otherwise, MP_NO is returned and np is untouched.
The function mpp_fermat() performs Fermat's test, using w as a
witness. This test basically relies on the fact that if a is prime,
and w is relatively prime to a, then:
w^a = w (mod a)
That is,
w^(a - 1) = 1 (mod a)
The function returns MP_YES if the test passes, MP_NO if it fails. If
w is relatively prime to a, and the test fails, a is definitely
composite. If w is relatively prime to a and the test passes, then a
is either prime, or w is a false witness (the probability of this
happening depends on the choice of w and of a ... consult a number
theory textbook for more information about this).
Note: If (w, a) != 1, the output of this test is meaningless.
----
The function mpp_pprime() performs the Rabin-Miller probabilistic
primality test for nt rounds. If all the tests pass, MP_YES is
returned, and a is probably prime. The probability that an answer of
MP_YES is incorrect is no greater than 1 in 4^nt, and in fact is
usually much less than that (this is a pessimistic estimate). If any
test fails, MP_NO is returned, and a is definitely composite.
Bruce Schneier recommends at least 5 iterations of this test for most
cryptographic applications; Knuth suggests that 25 are reasonable.
Run it as many times as you feel are necessary.
See the programs 'makeprime.c' and 'isprime.c' for reasonable examples
of how to use these functions for primality testing.
Bitwise Logic (mplogic.c)
-------------
The four commonest logical operations are implemented as:
mpl_not(a, b) - Compute bitwise (one's) complement, b = ~a
mpl_and(a, b, c) - Compute bitwise AND, c = a & b
mpl_or(a, b, c) - Compute bitwise OR, c = a | b
mpl_xor(a, b, c) - Compute bitwise XOR, c = a ^ b
Left and right shifts are available as well. These take a number to
shift, a destination, and a shift amount. The shift amount must be a
digit value between 0 and DIGIT_BIT inclusive; if it is not, MP_RANGE
will be returned and the shift will not happen.
mpl_rsh(a, b, d) - Compute logical right shift, b = a >> d
mpl_lsh(a, b, d) - Compute logical left shift, b = a << d
Since these are logical shifts, they fill with zeroes (the library
uses a signed magnitude representation, so there are no sign bits to
extend anyway).
Command-line Utilities
----------------------
A handful of interesting command-line utilities are provided. These
are:
lap.c - Find the order of a mod m. Usage is 'lap <a> <m>'.
This uses a dumb algorithm, so don't use it for
a really big modulus.
invmod.c - Find the inverse of a mod m, if it exists. Usage
is 'invmod <a> <m>'
sieve.c - A simple bitmap-based implementation of the Sieve
of Eratosthenes. Used to generate the table of
primes in primes.c. Usage is 'sieve <nbits>'
prng.c - Uses the routines in bbs_rand.{h,c} to generate
one or more 32-bit pseudo-random integers. This
is mainly an example, not intended for use in a
cryptographic application (the system time is
the only source of entropy used)
dec2hex.c - Convert decimal to hexadecimal
hex2dec.c - Convert hexadecimal to decimal
basecvt.c - General radix conversion tool (supports 2-64)
isprime.c - Probabilistically test an integer for primality
using the Rabin-Miller pseudoprime test combined
with division by small primes.
primegen.c - Generate primes at random.
exptmod.c - Perform modular exponentiation
ptab.pl - A Perl script to munge the output of the sieve
program into a compilable C structure.
Other Files
-----------
PRIMES - Some randomly generated numbers which are prime with
extremely high probability.
README - You're reading me already.
About the Author
----------------
This software was written by Michael J. Fromberger. You can contact
the author as follows:
E-mail: <sting@linguist.dartmouth.edu>
Postal: 8000 Cummings Hall, Thayer School of Engineering
Dartmouth College, Hanover, New Hampshire, USA
PGP key: http://linguist.dartmouth.edu/~sting/keys/mjf.html
9736 188B 5AFA 23D6 D6AA BE0D 5856 4525 289D 9907

View file

@ -1,68 +0,0 @@
/*
* basecvt.c
*
* Convert integer values specified on the command line from one input
* base to another. Accepts input and output bases between 2 and 36
* inclusive.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
#define IBASE 10
#define OBASE 16
#define USAGE "Usage: %s ibase obase [value]\n"
#define MAXBASE 64
#define MINBASE 2
int
main(int argc, char *argv[])
{
int ix, ibase = IBASE, obase = OBASE;
mp_int val;
ix = 1;
if (ix < argc) {
ibase = atoi(argv[ix++]);
if (ibase < MINBASE || ibase > MAXBASE) {
fprintf(stderr, "%s: input radix must be between %d and %d inclusive\n",
argv[0], MINBASE, MAXBASE);
return 1;
}
}
if (ix < argc) {
obase = atoi(argv[ix++]);
if (obase < MINBASE || obase > MAXBASE) {
fprintf(stderr, "%s: output radix must be between %d and %d inclusive\n",
argv[0], MINBASE, MAXBASE);
return 1;
}
}
mp_init(&val);
while (ix < argc) {
char *out;
int outlen;
mp_read_radix(&val, argv[ix++], ibase);
outlen = mp_radix_size(&val, obase);
out = calloc(outlen, sizeof(char));
mp_toradix(&val, out, obase);
printf("%s\n", out);
free(out);
}
mp_clear(&val);
return 0;
}

View file

@ -1,65 +0,0 @@
/*
* Blum, Blum & Shub PRNG using the MPI library
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "bbs_rand.h"
#define SEED 1
#define MODULUS 2
/* This modulus is the product of two randomly generated 512-bit
prime integers, each of which is congruent to 3 (mod 4). */
static char *bbs_modulus =
"75A2A6E1D27393B86562B9CE7279A8403CB4258A637DAB5233465373E37837383EDC"
"332282B8575927BC4172CE8C147B4894050EE9D2BDEED355C121037270CA2570D127"
"7D2390CD1002263326635CC6B259148DE3A1A03201980A925E395E646A5E9164B0EC"
"28559EBA58C87447245ADD0651EDA507056A1129E3A3E16E903D64B437";
static int bbs_init = 0; /* flag set when library is initialized */
static mp_int bbs_state; /* the current state of the generator */
/* Suggested size of random seed data */
int bbs_seed_size = (sizeof(bbs_modulus) / 2);
void
bbs_srand(unsigned char *data, int len)
{
if ((bbs_init & SEED) == 0) {
mp_init(&bbs_state);
bbs_init |= SEED;
}
mp_read_raw(&bbs_state, (char *)data, len);
} /* end bbs_srand() */
unsigned int
bbs_rand(void)
{
static mp_int modulus;
unsigned int result = 0, ix;
if ((bbs_init & MODULUS) == 0) {
mp_init(&modulus);
mp_read_radix(&modulus, bbs_modulus, 16);
bbs_init |= MODULUS;
}
for (ix = 0; ix < sizeof(unsigned int); ix++) {
mp_digit d;
mp_sqrmod(&bbs_state, &modulus, &bbs_state);
d = DIGIT(&bbs_state, 0);
result = (result << CHAR_BIT) | (d & UCHAR_MAX);
}
return result;
} /* end bbs_rand() */
/*------------------------------------------------------------------------*/
/* HERE THERE BE DRAGONS */

View file

@ -1,24 +0,0 @@
/*
* bbs_rand.h
*
* Blum, Blum & Shub PRNG using the MPI library
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef _H_BBSRAND_
#define _H_BBSRAND_
#include <limits.h>
#include "mpi.h"
#define BBS_RAND_MAX UINT_MAX
/* Suggested length of seed data */
extern int bbs_seed_size;
void bbs_srand(unsigned char *data, int len);
unsigned int bbs_rand(void);
#endif /* end _H_BBSRAND_ */

View file

@ -1,35 +0,0 @@
/*
* bbsrand.c
*
* Test driver for routines in bbs_rand.h
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <limits.h>
#include "bbs_rand.h"
#define NUM_TESTS 100
int
main(void)
{
unsigned int seed, result, ix;
seed = time(NULL);
bbs_srand((unsigned char *)&seed, sizeof(seed));
for (ix = 0; ix < NUM_TESTS; ix++) {
result = bbs_rand();
printf("Test %3u: %08X\n", ix + 1, result);
}
return 0;
}

View file

@ -1,40 +0,0 @@
/*
* dec2hex.c
*
* Convert decimal integers into hexadecimal
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
int
main(int argc, char *argv[])
{
mp_int a;
char *buf;
int len;
if (argc < 2) {
fprintf(stderr, "Usage: %s <a>\n", argv[0]);
return 1;
}
mp_init(&a);
mp_read_radix(&a, argv[1], 10);
len = mp_radix_size(&a, 16);
buf = malloc(len);
mp_toradix(&a, buf, 16);
printf("%s\n", buf);
free(buf);
mp_clear(&a);
return 0;
}

View file

@ -1,55 +0,0 @@
/*
* exptmod.c
*
* Command line tool to perform modular exponentiation on arbitrary
* precision integers.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
int
main(int argc, char *argv[])
{
mp_int a, b, m;
mp_err res;
char *str;
int len, rval = 0;
if (argc < 3) {
fprintf(stderr, "Usage: %s <a> <b> <m>\n", argv[0]);
return 1;
}
mp_init(&a);
mp_init(&b);
mp_init(&m);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&b, argv[2], 10);
mp_read_radix(&m, argv[3], 10);
if ((res = mp_exptmod(&a, &b, &m, &a)) != MP_OKAY) {
fprintf(stderr, "%s: error: %s\n", argv[0], mp_strerror(res));
rval = 1;
} else {
len = mp_radix_size(&a, 10);
str = calloc(len, sizeof(char));
mp_toradix(&a, str, 10);
printf("%s\n", str);
free(str);
}
mp_clear(&a);
mp_clear(&b);
mp_clear(&m);
return rval;
}

View file

@ -1,84 +0,0 @@
/*
* fact.c
*
* Compute factorial of input integer
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
mp_err mp_fact(mp_int *a, mp_int *b);
int
main(int argc, char *argv[])
{
mp_int a;
mp_err res;
if (argc < 2) {
fprintf(stderr, "Usage: %s <number>\n", argv[0]);
return 1;
}
mp_init(&a);
mp_read_radix(&a, argv[1], 10);
if ((res = mp_fact(&a, &a)) != MP_OKAY) {
fprintf(stderr, "%s: error: %s\n", argv[0],
mp_strerror(res));
mp_clear(&a);
return 1;
}
{
char *buf;
int len;
len = mp_radix_size(&a, 10);
buf = malloc(len);
mp_todecimal(&a, buf);
puts(buf);
free(buf);
}
mp_clear(&a);
return 0;
}
mp_err
mp_fact(mp_int *a, mp_int *b)
{
mp_int ix, s;
mp_err res = MP_OKAY;
if (mp_cmp_z(a) < 0)
return MP_UNDEF;
mp_init(&s);
mp_add_d(&s, 1, &s); /* s = 1 */
mp_init(&ix);
mp_add_d(&ix, 1, &ix); /* ix = 1 */
for (/* */; mp_cmp(&ix, a) <= 0; mp_add_d(&ix, 1, &ix)) {
if ((res = mp_mul(&s, &ix, &s)) != MP_OKAY)
break;
}
mp_clear(&ix);
/* Copy out results if we got them */
if (res == MP_OKAY)
mp_copy(&s, b);
mp_clear(&s);
return res;
}

View file

@ -1,95 +0,0 @@
/*
* gcd.c
*
* Greatest common divisor
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
char *g_prog = NULL;
void print_mp_int(mp_int *mp, FILE *ofp);
int
main(int argc, char *argv[])
{
mp_int a, b, x, y;
mp_err res;
int ext = 0;
g_prog = argv[0];
if (argc < 3) {
fprintf(stderr, "Usage: %s <a> <b>\n", g_prog);
return 1;
}
mp_init(&a);
mp_read_radix(&a, argv[1], 10);
mp_init(&b);
mp_read_radix(&b, argv[2], 10);
/* If we were called 'xgcd', compute x, y so that g = ax + by */
if (strcmp(g_prog, "xgcd") == 0) {
ext = 1;
mp_init(&x);
mp_init(&y);
}
if (ext) {
if ((res = mp_xgcd(&a, &b, &a, &x, &y)) != MP_OKAY) {
fprintf(stderr, "%s: error: %s\n", g_prog, mp_strerror(res));
mp_clear(&a);
mp_clear(&b);
mp_clear(&x);
mp_clear(&y);
return 1;
}
} else {
if ((res = mp_gcd(&a, &b, &a)) != MP_OKAY) {
fprintf(stderr, "%s: error: %s\n", g_prog,
mp_strerror(res));
mp_clear(&a);
mp_clear(&b);
return 1;
}
}
print_mp_int(&a, stdout);
if (ext) {
fputs("x = ", stdout);
print_mp_int(&x, stdout);
fputs("y = ", stdout);
print_mp_int(&y, stdout);
}
mp_clear(&a);
mp_clear(&b);
if (ext) {
mp_clear(&x);
mp_clear(&y);
}
return 0;
}
void
print_mp_int(mp_int *mp, FILE *ofp)
{
char *buf;
int len;
len = mp_radix_size(mp, 10);
buf = calloc(len, sizeof(char));
mp_todecimal(mp, buf);
fprintf(ofp, "%s\n", buf);
free(buf);
}

View file

@ -1,40 +0,0 @@
/*
* hex2dec.c
*
* Convert decimal integers into hexadecimal
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
int
main(int argc, char *argv[])
{
mp_int a;
char *buf;
int len;
if (argc < 2) {
fprintf(stderr, "Usage: %s <a>\n", argv[0]);
return 1;
}
mp_init(&a);
mp_read_radix(&a, argv[1], 16);
len = mp_radix_size(&a, 10);
buf = malloc(len);
mp_toradix(&a, buf, 10);
printf("%s\n", buf);
free(buf);
mp_clear(&a);
return 0;
}

View file

@ -1,84 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
#include "mpprime.h"
#include <sys/types.h>
#include <time.h>
#define MAX_PREC (4096 / MP_DIGIT_BIT)
mp_err
identity_test(void)
{
mp_size preca, precb;
mp_err res;
mp_int a, b;
mp_int t1, t2, t3, t4, t5;
preca = (rand() % MAX_PREC) + 1;
precb = (rand() % MAX_PREC) + 1;
MP_DIGITS(&a) = 0;
MP_DIGITS(&b) = 0;
MP_DIGITS(&t1) = 0;
MP_DIGITS(&t2) = 0;
MP_DIGITS(&t3) = 0;
MP_DIGITS(&t4) = 0;
MP_DIGITS(&t5) = 0;
MP_CHECKOK(mp_init(&a));
MP_CHECKOK(mp_init(&b));
MP_CHECKOK(mp_init(&t1));
MP_CHECKOK(mp_init(&t2));
MP_CHECKOK(mp_init(&t3));
MP_CHECKOK(mp_init(&t4));
MP_CHECKOK(mp_init(&t5));
MP_CHECKOK(mpp_random_size(&a, preca));
MP_CHECKOK(mpp_random_size(&b, precb));
if (mp_cmp(&a, &b) < 0)
mp_exch(&a, &b);
MP_CHECKOK(mp_mod(&a, &b, &t1)); /* t1 = a%b */
MP_CHECKOK(mp_div(&a, &b, &t2, NULL)); /* t2 = a/b */
MP_CHECKOK(mp_mul(&b, &t2, &t3)); /* t3 = (a/b)*b */
MP_CHECKOK(mp_add(&t1, &t3, &t4)); /* t4 = a%b + (a/b)*b */
MP_CHECKOK(mp_sub(&t4, &a, &t5)); /* t5 = a%b + (a/b)*b - a */
if (mp_cmp_z(&t5) != 0) {
res = MP_UNDEF;
goto CLEANUP;
}
CLEANUP:
mp_clear(&t5);
mp_clear(&t4);
mp_clear(&t3);
mp_clear(&t2);
mp_clear(&t1);
mp_clear(&b);
mp_clear(&a);
return res;
}
int
main(void)
{
unsigned int seed = (unsigned int)time(NULL);
unsigned long count = 0;
mp_err res;
srand(seed);
while (MP_OKAY == (res = identity_test())) {
if ((++count % 100) == 0)
fputc('.', stderr);
}
fprintf(stderr, "\ntest failed, err %d\n", res);
return res;
}

View file

@ -1,61 +0,0 @@
/*
* invmod.c
*
* Compute modular inverses
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include "mpi.h"
int
main(int argc, char *argv[])
{
mp_int a, m;
mp_err res;
char *buf;
int len, out = 0;
if (argc < 3) {
fprintf(stderr, "Usage: %s <a> <m>\n", argv[0]);
return 1;
}
mp_init(&a);
mp_init(&m);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&m, argv[2], 10);
if (mp_cmp(&a, &m) > 0)
mp_mod(&a, &m, &a);
switch ((res = mp_invmod(&a, &m, &a))) {
case MP_OKAY:
len = mp_radix_size(&a, 10);
buf = malloc(len);
mp_toradix(&a, buf, 10);
printf("%s\n", buf);
free(buf);
break;
case MP_UNDEF:
printf("No inverse\n");
out = 1;
break;
default:
printf("error: %s (%d)\n", mp_strerror(res), res);
out = 2;
break;
}
mp_clear(&a);
mp_clear(&m);
return out;
}

View file

@ -1,89 +0,0 @@
/*
* isprime.c
*
* Probabilistic primality tester command-line tool
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "mpi.h"
#include "mpprime.h"
#define RM_TESTS 15 /* how many iterations of Rabin-Miller? */
#define MINIMUM 1024 /* don't bother us with a < this */
int g_tests = RM_TESTS;
char *g_prog = NULL;
int
main(int argc, char *argv[])
{
mp_int a;
mp_digit np = prime_tab_size; /* from mpprime.h */
int res = 0;
g_prog = argv[0];
if (argc < 2) {
fprintf(stderr, "Usage: %s <a>, where <a> is a decimal integer\n"
"Use '0x' prefix for a hexadecimal value\n",
g_prog);
return 1;
}
/* Read number of tests from environment, if present */
{
char *tmp;
if ((tmp = PR_GetEnvSecure("RM_TESTS")) != NULL) {
if ((g_tests = atoi(tmp)) <= 0)
g_tests = RM_TESTS;
}
}
mp_init(&a);
if (argv[1][0] == '0' && argv[1][1] == 'x')
mp_read_radix(&a, argv[1] + 2, 16);
else
mp_read_radix(&a, argv[1], 10);
if (mp_cmp_d(&a, MINIMUM) <= 0) {
fprintf(stderr, "%s: please use a value greater than %d\n",
g_prog, MINIMUM);
mp_clear(&a);
return 1;
}
/* Test for divisibility by small primes */
if (mpp_divis_primes(&a, &np) != MP_NO) {
printf("Not prime (divisible by small prime %d)\n", np);
res = 2;
goto CLEANUP;
}
/* Test with Fermat's test, using 2 as a witness */
if (mpp_fermat(&a, 2) != MP_YES) {
printf("Not prime (failed Fermat test)\n");
res = 2;
goto CLEANUP;
}
/* Test with Rabin-Miller probabilistic test */
if (mpp_pprime(&a, g_tests) == MP_NO) {
printf("Not prime (failed pseudoprime test)\n");
res = 2;
goto CLEANUP;
}
printf("Probably prime, 1 in 4^%d chance of false positive\n", g_tests);
CLEANUP:
mp_clear(&a);
return res;
}

View file

@ -1,90 +0,0 @@
/*
* lap.c
*
* Find least annihilating power of a mod m
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include "mpi.h"
void sig_catch(int ign);
int g_quit = 0;
int
main(int argc, char *argv[])
{
mp_int a, m, p, k;
if (argc < 3) {
fprintf(stderr, "Usage: %s <a> <m>\n", argv[0]);
return 1;
}
mp_init(&a);
mp_init(&m);
mp_init(&p);
mp_add_d(&p, 1, &p);
mp_read_radix(&a, argv[1], 10);
mp_read_radix(&m, argv[2], 10);
mp_init_copy(&k, &a);
signal(SIGINT, sig_catch);
#ifndef __OS2__
signal(SIGHUP, sig_catch);
#endif
signal(SIGTERM, sig_catch);
while (mp_cmp(&p, &m) < 0) {
if (g_quit) {
int len;
char *buf;
len = mp_radix_size(&p, 10);
buf = malloc(len);
mp_toradix(&p, buf, 10);
fprintf(stderr, "Terminated at: %s\n", buf);
free(buf);
return 1;
}
if (mp_cmp_d(&k, 1) == 0) {
int len;
char *buf;
len = mp_radix_size(&p, 10);
buf = malloc(len);
mp_toradix(&p, buf, 10);
printf("%s\n", buf);
free(buf);
break;
}
mp_mulmod(&k, &a, &m, &k);
mp_add_d(&p, 1, &p);
}
if (mp_cmp(&p, &m) >= 0)
printf("No annihilating power.\n");
mp_clear(&p);
mp_clear(&m);
mp_clear(&a);
return 0;
}
void
sig_catch(int ign)
{
g_quit = 1;
}

Some files were not shown because too many files have changed in this diff Show more