function old new delta pstm_mul_comba 439 447 +8 pstm_sqr_comba 475 478 +3 pstm_montgomery_reduce 399 381 -18 ------------------------------------------------------------------------------ (add/remove: 0/0 grow/shrink: 2/1 up/down: 11/-18) Total: -7 bytes Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
		
			
				
	
	
		
			2264 lines
		
	
	
		
			49 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			2264 lines
		
	
	
		
			49 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/*
 | 
						|
 * Copyright (C) 2017 Denys Vlasenko
 | 
						|
 *
 | 
						|
 * Licensed under GPLv2, see file LICENSE in this source tree.
 | 
						|
 */
 | 
						|
#include "tls.h"
 | 
						|
 | 
						|
/* The file is taken almost verbatim from matrixssl-3-7-2b-open/crypto/math/.
 | 
						|
 * Changes are flagged with //bbox
 | 
						|
 */
 | 
						|
 | 
						|
/**
 | 
						|
 *	@file    pstm.c
 | 
						|
 *	@version 33ef80f (HEAD, tag: MATRIXSSL-3-7-2-OPEN, tag: MATRIXSSL-3-7-2-COMM, origin/master, origin/HEAD, master)
 | 
						|
 *
 | 
						|
 *	Multiprecision number implementation.
 | 
						|
 */
 | 
						|
/*
 | 
						|
 *	Copyright (c) 2013-2015 INSIDE Secure Corporation
 | 
						|
 *	Copyright (c) PeerSec Networks, 2002-2011
 | 
						|
 *	All Rights Reserved
 | 
						|
 *
 | 
						|
 *	The latest version of this code is available at http://www.matrixssl.org
 | 
						|
 *
 | 
						|
 *	This software is open source; you can redistribute it and/or modify
 | 
						|
 *	it under the terms of the GNU General Public License as published by
 | 
						|
 *	the Free Software Foundation; either version 2 of the License, or
 | 
						|
 *	(at your option) any later version.
 | 
						|
 *
 | 
						|
 *	This General Public License does NOT permit incorporating this software
 | 
						|
 *	into proprietary programs.  If you are unable to comply with the GPL, a
 | 
						|
 *	commercial license for this software may be purchased from INSIDE at
 | 
						|
 *	http://www.insidesecure.com/eng/Company/Locations
 | 
						|
 *
 | 
						|
 *	This program is distributed in WITHOUT ANY WARRANTY; without even the
 | 
						|
 *	implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 | 
						|
 *	See the GNU General Public License for more details.
 | 
						|
 *
 | 
						|
 *	You should have received a copy of the GNU General Public License
 | 
						|
 *	along with this program; if not, write to the Free Software
 | 
						|
 *	Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 | 
						|
 *	http://www.gnu.org/copyleft/gpl.html
 | 
						|
 */
 | 
						|
/******************************************************************************/
 | 
						|
 | 
						|
//bbox
 | 
						|
//#include "../cryptoApi.h"
 | 
						|
#ifndef DISABLE_PSTM
 | 
						|
 | 
						|
static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c); //bbox: was int16 b
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	init an pstm_int for a given size
 | 
						|
 */
 | 
						|
int32 pstm_init_size(psPool_t *pool, pstm_int * a, uint32 size)
 | 
						|
{
 | 
						|
//bbox
 | 
						|
//	uint16		x;
 | 
						|
 | 
						|
/*
 | 
						|
	alloc mem
 | 
						|
 */
 | 
						|
	a->dp = xzalloc(sizeof (pstm_digit) * size);//bbox
 | 
						|
//bbox	a->pool = pool;
 | 
						|
	a->used  = 0;
 | 
						|
	a->alloc = size;
 | 
						|
	a->sign  = PSTM_ZPOS;
 | 
						|
/*
 | 
						|
	zero the digits
 | 
						|
 */
 | 
						|
//bbox
 | 
						|
//	for (x = 0; x < size; x++) {
 | 
						|
//		a->dp[x] = 0;
 | 
						|
//	}
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	Init a new pstm_int.
 | 
						|
*/
 | 
						|
int32 pstm_init(psPool_t *pool, pstm_int * a)
 | 
						|
{
 | 
						|
//bbox
 | 
						|
//	int32		i;
 | 
						|
/*
 | 
						|
	allocate memory required and clear it
 | 
						|
 */
 | 
						|
	a->dp = xzalloc(sizeof (pstm_digit) * PSTM_DEFAULT_INIT);//bbox
 | 
						|
/*
 | 
						|
	set the digits to zero
 | 
						|
 */
 | 
						|
//bbox
 | 
						|
//	for (i = 0; i < PSTM_DEFAULT_INIT; i++) {
 | 
						|
//		a->dp[i] = 0;
 | 
						|
//	}
 | 
						|
/*
 | 
						|
	set the used to zero, allocated digits to the default precision and sign
 | 
						|
	to positive
 | 
						|
 */
 | 
						|
//bbox	a->pool = pool;
 | 
						|
	a->used  = 0;
 | 
						|
	a->alloc = PSTM_DEFAULT_INIT;
 | 
						|
	a->sign  = PSTM_ZPOS;
 | 
						|
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	Grow as required
 | 
						|
 */
 | 
						|
int32 pstm_grow(pstm_int * a, int size)
 | 
						|
{
 | 
						|
	int			i; //bbox: was int16
 | 
						|
	pstm_digit		*tmp;
 | 
						|
 | 
						|
/*
 | 
						|
	If the alloc size is smaller alloc more ram.
 | 
						|
 */
 | 
						|
	if (a->alloc < size) {
 | 
						|
/*
 | 
						|
		Reallocate the array a->dp
 | 
						|
 | 
						|
		We store the return in a temporary variable in case the operation
 | 
						|
		failed we don't want to overwrite the dp member of a.
 | 
						|
*/
 | 
						|
		tmp = xrealloc(a->dp, sizeof (pstm_digit) * size);//bbox
 | 
						|
/*
 | 
						|
		reallocation succeeded so set a->dp
 | 
						|
 */
 | 
						|
		a->dp = tmp;
 | 
						|
/*
 | 
						|
		zero excess digits
 | 
						|
 */
 | 
						|
		i			= a->alloc;
 | 
						|
		a->alloc	= size;
 | 
						|
		for (; i < a->alloc; i++) {
 | 
						|
			a->dp[i] = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	copy, b = a (b must be pre-allocated)
 | 
						|
 */
 | 
						|
int32 pstm_copy(pstm_int * a, pstm_int * b)
 | 
						|
{
 | 
						|
	int32	res, n;
 | 
						|
 | 
						|
/*
 | 
						|
	If dst == src do nothing
 | 
						|
 */
 | 
						|
	if (a == b) {
 | 
						|
		return PSTM_OKAY;
 | 
						|
	}
 | 
						|
/*
 | 
						|
	Grow dest
 | 
						|
 */
 | 
						|
	if (b->alloc < a->used) {
 | 
						|
		if ((res = pstm_grow (b, a->used)) != PSTM_OKAY) {
 | 
						|
			return res;
 | 
						|
		}
 | 
						|
	}
 | 
						|
/*
 | 
						|
	Zero b and copy the parameters over
 | 
						|
 */
 | 
						|
	{
 | 
						|
		register pstm_digit *tmpa, *tmpb;
 | 
						|
 | 
						|
		/* pointer aliases */
 | 
						|
		/* source */
 | 
						|
		tmpa = a->dp;
 | 
						|
 | 
						|
		/* destination */
 | 
						|
		tmpb = b->dp;
 | 
						|
 | 
						|
		/* copy all the digits */
 | 
						|
		for (n = 0; n < a->used; n++) {
 | 
						|
			*tmpb++ = *tmpa++;
 | 
						|
		}
 | 
						|
 | 
						|
		/* clear high digits */
 | 
						|
		for (; n < b->used; n++) {
 | 
						|
			*tmpb++ = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
/*
 | 
						|
	copy used count and sign
 | 
						|
 */
 | 
						|
	b->used = a->used;
 | 
						|
	b->sign = a->sign;
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	Trim unused digits
 | 
						|
 | 
						|
	This is used to ensure that leading zero digits are trimed and the
 | 
						|
	leading "used" digit will be non-zero. Typically very fast.  Also fixes
 | 
						|
	the sign if there are no more leading digits
 | 
						|
*/
 | 
						|
void pstm_clamp(pstm_int * a)
 | 
						|
{
 | 
						|
/*	decrease used while the most significant digit is zero. */
 | 
						|
	while (a->used > 0 && a->dp[a->used - 1] == 0) {
 | 
						|
		--(a->used);
 | 
						|
	}
 | 
						|
/*	reset the sign flag if used == 0 */
 | 
						|
	if (a->used == 0) {
 | 
						|
		a->sign = PSTM_ZPOS;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	clear one (frees).
 | 
						|
 */
 | 
						|
void pstm_clear(pstm_int * a)
 | 
						|
{
 | 
						|
	int32		i;
 | 
						|
/*
 | 
						|
	only do anything if a hasn't been freed previously
 | 
						|
 */
 | 
						|
	if (a != NULL && a->dp != NULL) {
 | 
						|
/*
 | 
						|
		first zero the digits
 | 
						|
 */
 | 
						|
		for (i = 0; i < a->used; i++) {
 | 
						|
			a->dp[i] = 0;
 | 
						|
		}
 | 
						|
 | 
						|
		psFree (a->dp, a->pool);
 | 
						|
/*
 | 
						|
		reset members to make debugging easier
 | 
						|
 */
 | 
						|
		a->dp		= NULL;
 | 
						|
		a->alloc	= a->used = 0;
 | 
						|
		a->sign		= PSTM_ZPOS;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	clear many (frees).
 | 
						|
 */
 | 
						|
void pstm_clear_multi(pstm_int *mp0, pstm_int *mp1, pstm_int *mp2,
 | 
						|
					pstm_int *mp3, pstm_int *mp4, pstm_int *mp5,
 | 
						|
					pstm_int *mp6, pstm_int *mp7)
 | 
						|
{
 | 
						|
	int32		n;		/* Number of ok inits */
 | 
						|
 | 
						|
	pstm_int	*tempArray[9];
 | 
						|
 | 
						|
	tempArray[0] = mp0;
 | 
						|
	tempArray[1] = mp1;
 | 
						|
	tempArray[2] = mp2;
 | 
						|
	tempArray[3] = mp3;
 | 
						|
	tempArray[4] = mp4;
 | 
						|
	tempArray[5] = mp5;
 | 
						|
	tempArray[6] = mp6;
 | 
						|
	tempArray[7] = mp7;
 | 
						|
	tempArray[8] = NULL;
 | 
						|
 | 
						|
	for (n = 0; tempArray[n] != NULL; n++) {
 | 
						|
		if ((tempArray[n] != NULL) && (tempArray[n]->dp != NULL)) {
 | 
						|
			pstm_clear(tempArray[n]);
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	Set to zero.
 | 
						|
 */
 | 
						|
void pstm_zero(pstm_int * a)
 | 
						|
{
 | 
						|
	int32		n;
 | 
						|
	pstm_digit	*tmp;
 | 
						|
 | 
						|
	a->sign = PSTM_ZPOS;
 | 
						|
	a->used = 0;
 | 
						|
 | 
						|
	tmp = a->dp;
 | 
						|
	for (n = 0; n < a->alloc; n++) {
 | 
						|
		*tmp++ = 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	Compare maginitude of two ints (unsigned).
 | 
						|
 */
 | 
						|
int32 pstm_cmp_mag(pstm_int * a, pstm_int * b)
 | 
						|
{
 | 
						|
	int		n; //bbox: was int16
 | 
						|
	pstm_digit	*tmpa, *tmpb;
 | 
						|
 | 
						|
/*
 | 
						|
	compare based on # of non-zero digits
 | 
						|
 */
 | 
						|
	if (a->used > b->used) {
 | 
						|
		return PSTM_GT;
 | 
						|
	}
 | 
						|
 | 
						|
	if (a->used < b->used) {
 | 
						|
		return PSTM_LT;
 | 
						|
	}
 | 
						|
 | 
						|
	/* alias for a */
 | 
						|
	tmpa = a->dp + (a->used - 1);
 | 
						|
 | 
						|
	/* alias for b */
 | 
						|
	tmpb = b->dp + (a->used - 1);
 | 
						|
 | 
						|
/*
 | 
						|
	compare based on digits
 | 
						|
 */
 | 
						|
	for (n = 0; n < a->used; ++n, --tmpa, --tmpb) {
 | 
						|
		if (*tmpa > *tmpb) {
 | 
						|
			return PSTM_GT;
 | 
						|
		}
 | 
						|
		if (*tmpa < *tmpb) {
 | 
						|
			return PSTM_LT;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return PSTM_EQ;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	Compare two ints (signed)
 | 
						|
 */
 | 
						|
int32 pstm_cmp(pstm_int * a, pstm_int * b)
 | 
						|
{
 | 
						|
/*
 | 
						|
	compare based on sign
 | 
						|
 */
 | 
						|
	if (a->sign != b->sign) {
 | 
						|
		if (a->sign == PSTM_NEG) {
 | 
						|
			return PSTM_LT;
 | 
						|
		} else {
 | 
						|
			return PSTM_GT;
 | 
						|
		}
 | 
						|
	}
 | 
						|
/*
 | 
						|
	compare digits
 | 
						|
 */
 | 
						|
	if (a->sign == PSTM_NEG) {
 | 
						|
		/* if negative compare opposite direction */
 | 
						|
		return pstm_cmp_mag(b, a);
 | 
						|
	} else {
 | 
						|
		return pstm_cmp_mag(a, b);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	pstm_ints can be initialized more precisely when they will populated
 | 
						|
	using pstm_read_unsigned_bin since the length of the byte stream is known
 | 
						|
*/
 | 
						|
int32 pstm_init_for_read_unsigned_bin(psPool_t *pool, pstm_int *a, uint32 len)
 | 
						|
{
 | 
						|
	int32 size;
 | 
						|
/*
 | 
						|
	Need to set this based on how many words max it will take to store the bin.
 | 
						|
	The magic + 2:
 | 
						|
		1 to round up for the remainder of this integer math
 | 
						|
		1 for the initial carry of '1' bits that fall between DIGIT_BIT and 8
 | 
						|
*/
 | 
						|
	size = (((len / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT))
 | 
						|
		/ DIGIT_BIT) + 2;
 | 
						|
	return pstm_init_size(pool, a, size);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	Reads a unsigned char array into pstm_int format.  User should have
 | 
						|
	called pstm_init_for_read_unsigned_bin first.  There is some grow logic
 | 
						|
	here if the default pstm_init was used but we don't really want to hit it.
 | 
						|
*/
 | 
						|
int32 pstm_read_unsigned_bin(pstm_int *a, unsigned char *b, int32 c)
 | 
						|
{
 | 
						|
	/* zero the int */
 | 
						|
	pstm_zero (a);
 | 
						|
 | 
						|
/*
 | 
						|
	If we know the endianness of this architecture, and we're using
 | 
						|
	32-bit pstm_digits, we can optimize this
 | 
						|
*/
 | 
						|
#if (defined(ENDIAN_LITTLE) || defined(ENDIAN_BIG)) && !defined(PSTM_64BIT)
 | 
						|
  /* But not for both simultaneously */
 | 
						|
#if defined(ENDIAN_LITTLE) && defined(ENDIAN_BIG)
 | 
						|
#error Both ENDIAN_LITTLE and ENDIAN_BIG defined.
 | 
						|
#endif
 | 
						|
	{
 | 
						|
		unsigned char *pd;
 | 
						|
		if ((unsigned)c > (PSTM_MAX_SIZE * sizeof(pstm_digit))) {
 | 
						|
			uint32 excess = c - (PSTM_MAX_SIZE * sizeof(pstm_digit));
 | 
						|
			c -= excess;
 | 
						|
			b += excess;
 | 
						|
		}
 | 
						|
		a->used = ((c + sizeof(pstm_digit) - 1)/sizeof(pstm_digit));
 | 
						|
		if (a->alloc < a->used) {
 | 
						|
			if (pstm_grow(a, a->used) != PSTM_OKAY) {
 | 
						|
				return PSTM_MEM;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		pd = (unsigned char *)a->dp;
 | 
						|
		/* read the bytes in */
 | 
						|
#ifdef ENDIAN_BIG
 | 
						|
		{
 | 
						|
			/* Use Duff's device to unroll the loop. */
 | 
						|
			int32 idx = (c - 1) & ~3;
 | 
						|
			switch (c % 4) {
 | 
						|
				case 0:	do { pd[idx+0] = *b++;
 | 
						|
					case 3:	     pd[idx+1] = *b++;
 | 
						|
					case 2:	     pd[idx+2] = *b++;
 | 
						|
					case 1:	     pd[idx+3] = *b++;
 | 
						|
					idx -= 4;
 | 
						|
				} while ((c -= 4) > 0);
 | 
						|
			}
 | 
						|
		}
 | 
						|
#else
 | 
						|
		for (c -= 1; c >= 0; c -= 1) {
 | 
						|
			pd[c] = *b++;
 | 
						|
		}
 | 
						|
#endif
 | 
						|
	}
 | 
						|
#else
 | 
						|
	/* Big enough based on the len? */
 | 
						|
	a->used = (((c / sizeof(pstm_digit)) * (sizeof(pstm_digit) * CHAR_BIT))
 | 
						|
		/ DIGIT_BIT) + 2;
 | 
						|
 | 
						|
	if (a->alloc < a->used) {
 | 
						|
		if (pstm_grow(a, a->used) != PSTM_OKAY) {
 | 
						|
			return PSTM_MEM;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	/* read the bytes in */
 | 
						|
	for (; c > 0; c--) {
 | 
						|
		if (pstm_mul_2d (a, 8, a) != PSTM_OKAY) {
 | 
						|
			return PS_MEM_FAIL;
 | 
						|
		}
 | 
						|
		a->dp[0] |= *b++;
 | 
						|
		a->used += 1;
 | 
						|
	}
 | 
						|
#endif
 | 
						|
 | 
						|
	pstm_clamp (a);
 | 
						|
	return PS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
*/
 | 
						|
int pstm_count_bits (pstm_int * a)
 | 
						|
{
 | 
						|
	int     r; //bbox: was int16
 | 
						|
	pstm_digit q;
 | 
						|
 | 
						|
	if (a->used == 0) {
 | 
						|
		return 0;
 | 
						|
	}
 | 
						|
 | 
						|
	/* get number of digits and add that */
 | 
						|
	r = (a->used - 1) * DIGIT_BIT;
 | 
						|
 | 
						|
	/* take the last digit and count the bits in it */
 | 
						|
	q = a->dp[a->used - 1];
 | 
						|
	while (q > ((pstm_digit) 0)) {
 | 
						|
		++r;
 | 
						|
		q >>= ((pstm_digit) 1);
 | 
						|
	}
 | 
						|
	return r;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
int32 pstm_unsigned_bin_size(pstm_int *a)
 | 
						|
{
 | 
						|
	int32     size = pstm_count_bits (a);
 | 
						|
	return (size / 8 + ((size & 7) != 0 ? 1 : 0));
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
void pstm_set(pstm_int *a, pstm_digit b)
 | 
						|
{
 | 
						|
   pstm_zero(a);
 | 
						|
   a->dp[0] = b;
 | 
						|
   a->used  = a->dp[0] ? 1 : 0;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	Right shift
 | 
						|
*/
 | 
						|
void pstm_rshd(pstm_int *a, int x)
 | 
						|
{
 | 
						|
	int y; //bbox: was int16
 | 
						|
 | 
						|
	/* too many digits just zero and return */
 | 
						|
	if (x >= a->used) {
 | 
						|
		pstm_zero(a);
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	/* shift */
 | 
						|
	for (y = 0; y < a->used - x; y++) {
 | 
						|
		a->dp[y] = a->dp[y+x];
 | 
						|
	}
 | 
						|
 | 
						|
	/* zero rest */
 | 
						|
	for (; y < a->used; y++) {
 | 
						|
		a->dp[y] = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	/* decrement count */
 | 
						|
	a->used -= x;
 | 
						|
	pstm_clamp(a);
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	Shift left a certain amount of digits.
 | 
						|
 */
 | 
						|
int32 pstm_lshd(pstm_int * a, int b)
 | 
						|
{
 | 
						|
	int	x; //bbox: was int16
 | 
						|
	int32	res;
 | 
						|
 | 
						|
/*
 | 
						|
	If its less than zero return.
 | 
						|
 */
 | 
						|
	if (b <= 0) {
 | 
						|
		return PSTM_OKAY;
 | 
						|
	}
 | 
						|
/*
 | 
						|
	Grow to fit the new digits.
 | 
						|
 */
 | 
						|
	if (a->alloc < a->used + b) {
 | 
						|
		if ((res = pstm_grow (a, a->used + b)) != PSTM_OKAY) {
 | 
						|
			return res;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	{
 | 
						|
		register pstm_digit *top, *bottom;
 | 
						|
/*
 | 
						|
		Increment the used by the shift amount then copy upwards.
 | 
						|
 */
 | 
						|
		a->used += b;
 | 
						|
 | 
						|
		/* top */
 | 
						|
		top = a->dp + a->used - 1;
 | 
						|
 | 
						|
		/* base */
 | 
						|
		bottom = a->dp + a->used - 1 - b;
 | 
						|
/*
 | 
						|
		This is implemented using a sliding window except the window goes the
 | 
						|
		other way around.  Copying from the bottom to the top.
 | 
						|
 */
 | 
						|
		for (x = a->used - 1; x >= b; x--) {
 | 
						|
			*top-- = *bottom--;
 | 
						|
		}
 | 
						|
 | 
						|
		/* zero the lower digits */
 | 
						|
		top = a->dp;
 | 
						|
		for (x = 0; x < b; x++) {
 | 
						|
			*top++ = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	computes a = 2**b
 | 
						|
*/
 | 
						|
int32 pstm_2expt(pstm_int *a, int b)
 | 
						|
{
 | 
						|
	int     z; //bbox: was int16
 | 
						|
 | 
						|
   /* zero a as per default */
 | 
						|
	pstm_zero (a);
 | 
						|
 | 
						|
	if (b < 0) {
 | 
						|
		return PSTM_OKAY;
 | 
						|
	}
 | 
						|
 | 
						|
	z = b / DIGIT_BIT;
 | 
						|
	if (z >= PSTM_MAX_SIZE) {
 | 
						|
		return PS_LIMIT_FAIL;
 | 
						|
	}
 | 
						|
 | 
						|
	/* set the used count of where the bit will go */
 | 
						|
	a->used = z + 1;
 | 
						|
 | 
						|
	if (a->used > a->alloc) {
 | 
						|
		if (pstm_grow(a, a->used) != PSTM_OKAY) {
 | 
						|
			return PS_MEM_FAIL;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* put the single bit in its place */
 | 
						|
	a->dp[z] = ((pstm_digit)1) << (b % DIGIT_BIT);
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
 | 
						|
*/
 | 
						|
int32 pstm_mul_2(pstm_int * a, pstm_int * b)
 | 
						|
{
 | 
						|
	int32	res;
 | 
						|
	int	x, oldused; //bbox: was int16
 | 
						|
 | 
						|
/*
 | 
						|
	grow to accomodate result
 | 
						|
 */
 | 
						|
	if (b->alloc < a->used + 1) {
 | 
						|
		if ((res = pstm_grow (b, a->used + 1)) != PSTM_OKAY) {
 | 
						|
			return res;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	oldused = b->used;
 | 
						|
	b->used = a->used;
 | 
						|
 | 
						|
	{
 | 
						|
		register pstm_digit r, rr, *tmpa, *tmpb;
 | 
						|
 | 
						|
		/* alias for source */
 | 
						|
		tmpa = a->dp;
 | 
						|
 | 
						|
		/* alias for dest */
 | 
						|
		tmpb = b->dp;
 | 
						|
 | 
						|
		/* carry */
 | 
						|
		r = 0;
 | 
						|
		for (x = 0; x < a->used; x++) {
 | 
						|
/*
 | 
						|
			get what will be the *next* carry bit from the
 | 
						|
			MSB of the current digit
 | 
						|
*/
 | 
						|
			rr = *tmpa >> ((pstm_digit)(DIGIT_BIT - 1));
 | 
						|
/*
 | 
						|
			now shift up this digit, add in the carry [from the previous]
 | 
						|
*/
 | 
						|
			*tmpb++ = ((*tmpa++ << ((pstm_digit)1)) | r);
 | 
						|
/*
 | 
						|
			copy the carry that would be from the source
 | 
						|
			digit into the next iteration
 | 
						|
*/
 | 
						|
			r = rr;
 | 
						|
		}
 | 
						|
 | 
						|
		/* new leading digit? */
 | 
						|
		if (r != 0 && b->used != (PSTM_MAX_SIZE-1)) {
 | 
						|
			/* add a MSB which is always 1 at this point */
 | 
						|
			*tmpb = 1;
 | 
						|
			++(b->used);
 | 
						|
		}
 | 
						|
/*
 | 
						|
		now zero any excess digits on the destination that we didn't write to
 | 
						|
*/
 | 
						|
		tmpb = b->dp + b->used;
 | 
						|
		for (x = b->used; x < oldused; x++) {
 | 
						|
			*tmpb++ = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	b->sign = a->sign;
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	unsigned subtraction ||a|| >= ||b|| ALWAYS!
 | 
						|
*/
 | 
						|
int32 s_pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
 | 
						|
{
 | 
						|
	int		oldbused, oldused; //bbox: was int16
 | 
						|
	int32		x;
 | 
						|
	pstm_word	t;
 | 
						|
 | 
						|
	if (b->used > a->used) {
 | 
						|
		return PS_LIMIT_FAIL;
 | 
						|
	}
 | 
						|
	if (c->alloc < a->used) {
 | 
						|
		if ((x = pstm_grow (c, a->used)) != PSTM_OKAY) {
 | 
						|
			return x;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	oldused  = c->used;
 | 
						|
	oldbused = b->used;
 | 
						|
	c->used  = a->used;
 | 
						|
	t = 0;
 | 
						|
 | 
						|
	for (x = 0; x < oldbused; x++) {
 | 
						|
		t = ((pstm_word)a->dp[x]) - (((pstm_word)b->dp[x]) + t);
 | 
						|
		c->dp[x] = (pstm_digit)t;
 | 
						|
		t = (t >> DIGIT_BIT)&1;
 | 
						|
	}
 | 
						|
	for (; x < a->used; x++) {
 | 
						|
		t = ((pstm_word)a->dp[x]) - t;
 | 
						|
		c->dp[x] = (pstm_digit)t;
 | 
						|
		t = (t >> DIGIT_BIT);
 | 
						|
	}
 | 
						|
	for (; x < oldused; x++) {
 | 
						|
		c->dp[x] = 0;
 | 
						|
	}
 | 
						|
	pstm_clamp(c);
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	unsigned addition
 | 
						|
*/
 | 
						|
static int32 s_pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
 | 
						|
{
 | 
						|
	int				x, y, oldused; //bbox: was int16
 | 
						|
	register pstm_word	t, adp, bdp;
 | 
						|
 | 
						|
	y = a->used;
 | 
						|
	if (b->used > y) {
 | 
						|
		y = b->used;
 | 
						|
	}
 | 
						|
	oldused = c->used;
 | 
						|
	c->used = y;
 | 
						|
 | 
						|
	if (c->used > c->alloc) {
 | 
						|
		if (pstm_grow(c, c->used) != PSTM_OKAY) {
 | 
						|
			return PS_MEM_FAIL;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	t = 0;
 | 
						|
	for (x = 0; x < y; x++) {
 | 
						|
		if (a->used < x) {
 | 
						|
			adp = 0;
 | 
						|
		} else {
 | 
						|
			adp = (pstm_word)a->dp[x];
 | 
						|
		}
 | 
						|
		if (b->used < x) {
 | 
						|
			bdp = 0;
 | 
						|
		} else {
 | 
						|
			bdp = (pstm_word)b->dp[x];
 | 
						|
		}
 | 
						|
		t         += (adp) + (bdp);
 | 
						|
		c->dp[x]   = (pstm_digit)t;
 | 
						|
		t        >>= DIGIT_BIT;
 | 
						|
	}
 | 
						|
	if (t != 0 && x < PSTM_MAX_SIZE) {
 | 
						|
		if (c->used == c->alloc) {
 | 
						|
			if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) {
 | 
						|
				return PS_MEM_FAIL;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		c->dp[c->used++] = (pstm_digit)t;
 | 
						|
		++x;
 | 
						|
	}
 | 
						|
 | 
						|
	c->used = x;
 | 
						|
	for (; x < oldused; x++) {
 | 
						|
		c->dp[x] = 0;
 | 
						|
	}
 | 
						|
	pstm_clamp(c);
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
 | 
						|
*/
 | 
						|
int32 pstm_sub(pstm_int *a, pstm_int *b, pstm_int *c)
 | 
						|
{
 | 
						|
	int32	res;
 | 
						|
	int	sa, sb; //bbox: was int16
 | 
						|
 | 
						|
	sa = a->sign;
 | 
						|
	sb = b->sign;
 | 
						|
 | 
						|
	if (sa != sb) {
 | 
						|
/*
 | 
						|
		subtract a negative from a positive, OR a positive from a negative.
 | 
						|
		For both, ADD their magnitudes, and use the sign of the first number.
 | 
						|
 */
 | 
						|
		c->sign = sa;
 | 
						|
		if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) {
 | 
						|
			return res;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
/*
 | 
						|
		subtract a positive from a positive, OR a negative from a negative.
 | 
						|
		First, take the difference between their magnitudes, then...
 | 
						|
 */
 | 
						|
		if (pstm_cmp_mag (a, b) != PSTM_LT) {
 | 
						|
			/* Copy the sign from the first */
 | 
						|
			c->sign = sa;
 | 
						|
			/* The first has a larger or equal magnitude */
 | 
						|
			if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) {
 | 
						|
				return res;
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			/* The result has the _opposite_ sign from the first number. */
 | 
						|
			c->sign = (sa == PSTM_ZPOS) ? PSTM_NEG : PSTM_ZPOS;
 | 
						|
			/* The second has a larger magnitude */
 | 
						|
			if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) {
 | 
						|
				return res;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return PS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	c = a - b
 | 
						|
*/
 | 
						|
int32 pstm_sub_d(psPool_t *pool, pstm_int *a, pstm_digit b, pstm_int *c)
 | 
						|
{
 | 
						|
	pstm_int	tmp;
 | 
						|
	int32		res;
 | 
						|
 | 
						|
	if (pstm_init_size(pool, &tmp, sizeof(pstm_digit)) != PSTM_OKAY) {
 | 
						|
		return PS_MEM_FAIL;
 | 
						|
	}
 | 
						|
	pstm_set(&tmp, b);
 | 
						|
	res = pstm_sub(a, &tmp, c);
 | 
						|
	pstm_clear(&tmp);
 | 
						|
	return res;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	setups the montgomery reduction
 | 
						|
*/
 | 
						|
int32 pstm_montgomery_setup(pstm_int *a, pstm_digit *rho)
 | 
						|
{
 | 
						|
	pstm_digit x, b;
 | 
						|
 | 
						|
/*
 | 
						|
	fast inversion mod 2**k
 | 
						|
	Based on the fact that
 | 
						|
	XA = 1 (mod 2**n)	=>  (X(2-XA)) A = 1 (mod 2**2n)
 | 
						|
						=>  2*X*A - X*X*A*A = 1
 | 
						|
						=>  2*(1) - (1)     = 1
 | 
						|
 */
 | 
						|
	b = a->dp[0];
 | 
						|
 | 
						|
	if ((b & 1) == 0) {
 | 
						|
		psTraceCrypto("pstm_montogomery_setup failure\n");
 | 
						|
		return PS_ARG_FAIL;
 | 
						|
	}
 | 
						|
 | 
						|
	x = (((b + 2) & 4) << 1) + b; /* here x*a==1 mod 2**4 */
 | 
						|
	x *= 2 - b * x;               /* here x*a==1 mod 2**8 */
 | 
						|
	x *= 2 - b * x;               /* here x*a==1 mod 2**16 */
 | 
						|
	x *= 2 - b * x;               /* here x*a==1 mod 2**32 */
 | 
						|
#ifdef PSTM_64BIT
 | 
						|
	x *= 2 - b * x;               /* here x*a==1 mod 2**64 */
 | 
						|
#endif
 | 
						|
	/* rho = -1/m mod b */
 | 
						|
	*rho = (pstm_digit)(((pstm_word) 1 << ((pstm_word) DIGIT_BIT)) -
 | 
						|
		((pstm_word)x));
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
 *	computes a = B**n mod b without division or multiplication useful for
 | 
						|
 *	normalizing numbers in a Montgomery system.
 | 
						|
 */
 | 
						|
int32 pstm_montgomery_calc_normalization(pstm_int *a, pstm_int *b)
 | 
						|
{
 | 
						|
	int32     x;
 | 
						|
	int	bits; //bbox: was int16
 | 
						|
 | 
						|
	/* how many bits of last digit does b use */
 | 
						|
	bits = pstm_count_bits (b) % DIGIT_BIT;
 | 
						|
	if (!bits) bits = DIGIT_BIT;
 | 
						|
 | 
						|
	/* compute A = B^(n-1) * 2^(bits-1) */
 | 
						|
	if (b->used > 1) {
 | 
						|
		if ((x = pstm_2expt (a, (b->used - 1) * DIGIT_BIT + bits - 1)) !=
 | 
						|
				PSTM_OKAY) {
 | 
						|
			return x;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		pstm_set(a, 1);
 | 
						|
		bits = 1;
 | 
						|
	}
 | 
						|
 | 
						|
	/* now compute C = A * B mod b */
 | 
						|
	for (x = bits - 1; x < (int32)DIGIT_BIT; x++) {
 | 
						|
		if (pstm_mul_2 (a, a) != PSTM_OKAY) {
 | 
						|
			return PS_MEM_FAIL;
 | 
						|
		}
 | 
						|
		if (pstm_cmp_mag (a, b) != PSTM_LT) {
 | 
						|
			if (s_pstm_sub (a, b, a) != PSTM_OKAY) {
 | 
						|
				return PS_MEM_FAIL;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	c = a * 2**d
 | 
						|
*/
 | 
						|
static int32 pstm_mul_2d(pstm_int *a, int b, pstm_int *c)
 | 
						|
{
 | 
						|
	pstm_digit	carry, carrytmp, shift;
 | 
						|
	int		x; //bbox: was int16
 | 
						|
 | 
						|
	/* copy it */
 | 
						|
	if (pstm_copy(a, c) != PSTM_OKAY) {
 | 
						|
		return PS_MEM_FAIL;
 | 
						|
	}
 | 
						|
 | 
						|
	/* handle whole digits */
 | 
						|
	if (b >= DIGIT_BIT) {
 | 
						|
		if (pstm_lshd(c, b/DIGIT_BIT) != PSTM_OKAY) {
 | 
						|
			return PS_MEM_FAIL;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	b %= DIGIT_BIT;
 | 
						|
 | 
						|
	/* shift the digits */
 | 
						|
	if (b != 0) {
 | 
						|
		carry = 0;
 | 
						|
		shift = DIGIT_BIT - b;
 | 
						|
		for (x = 0; x < c->used; x++) {
 | 
						|
			carrytmp = c->dp[x] >> shift;
 | 
						|
			c->dp[x] = (c->dp[x] << b) + carry;
 | 
						|
			carry = carrytmp;
 | 
						|
		}
 | 
						|
		/* store last carry if room */
 | 
						|
		if (carry && x < PSTM_MAX_SIZE) {
 | 
						|
			if (c->used == c->alloc) {
 | 
						|
				if (pstm_grow(c, c->alloc + 1) != PSTM_OKAY) {
 | 
						|
					return PS_MEM_FAIL;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			c->dp[c->used++] = carry;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	pstm_clamp(c);
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	c = a mod 2**d
 | 
						|
*/
 | 
						|
static int32 pstm_mod_2d(pstm_int *a, int b, pstm_int *c) //bbox: was int16 b
 | 
						|
{
 | 
						|
	int	x; //bbox: was int16
 | 
						|
 | 
						|
	/* zero if count less than or equal to zero */
 | 
						|
	if (b <= 0) {
 | 
						|
		pstm_zero(c);
 | 
						|
		return PSTM_OKAY;
 | 
						|
	}
 | 
						|
 | 
						|
	/* get copy of input */
 | 
						|
	if (pstm_copy(a, c) != PSTM_OKAY) {
 | 
						|
		return PS_MEM_FAIL;
 | 
						|
	}
 | 
						|
 | 
						|
	/* if 2**d is larger than we just return */
 | 
						|
	if (b >= (DIGIT_BIT * a->used)) {
 | 
						|
		return PSTM_OKAY;
 | 
						|
	}
 | 
						|
 | 
						|
	/* zero digits above the last digit of the modulus */
 | 
						|
	for (x = (b / DIGIT_BIT) + ((b % DIGIT_BIT) == 0 ? 0 : 1); x < c->used; x++)
 | 
						|
	{
 | 
						|
		c->dp[x] = 0;
 | 
						|
	}
 | 
						|
	/* clear the digit that is not completely outside/inside the modulus */
 | 
						|
	c->dp[b / DIGIT_BIT] &= ~((pstm_digit)0) >> (DIGIT_BIT - b);
 | 
						|
	pstm_clamp (c);
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	c = a * b
 | 
						|
*/
 | 
						|
int32 pstm_mul_d(pstm_int *a, pstm_digit b, pstm_int *c)
 | 
						|
{
 | 
						|
	pstm_word	w;
 | 
						|
	int32		res;
 | 
						|
	int		x, oldused; //bbox: was int16
 | 
						|
 | 
						|
	if (c->alloc < a->used + 1) {
 | 
						|
		if ((res = pstm_grow (c, a->used + 1)) != PSTM_OKAY) {
 | 
						|
			return res;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	oldused = c->used;
 | 
						|
	c->used = a->used;
 | 
						|
	c->sign = a->sign;
 | 
						|
	w       = 0;
 | 
						|
	for (x = 0; x < a->used; x++) {
 | 
						|
		w         = ((pstm_word)a->dp[x]) * ((pstm_word)b) + w;
 | 
						|
		c->dp[x]  = (pstm_digit)w;
 | 
						|
		w         = w >> DIGIT_BIT;
 | 
						|
	}
 | 
						|
	if (w != 0 && (a->used != PSTM_MAX_SIZE)) {
 | 
						|
		c->dp[c->used++] = (pstm_digit)w;
 | 
						|
		++x;
 | 
						|
	}
 | 
						|
	for (; x < oldused; x++) {
 | 
						|
		c->dp[x] = 0;
 | 
						|
	}
 | 
						|
	pstm_clamp(c);
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	c = a / 2**b
 | 
						|
*/
 | 
						|
int32 pstm_div_2d(psPool_t *pool, pstm_int *a, int b, pstm_int *c,
 | 
						|
					pstm_int *d)
 | 
						|
{
 | 
						|
	pstm_digit	D, r, rr;
 | 
						|
	int32		res;
 | 
						|
	int		x; //bbox: was int16
 | 
						|
	pstm_int	t;
 | 
						|
 | 
						|
	/* if the shift count is <= 0 then we do no work */
 | 
						|
	if (b <= 0) {
 | 
						|
		if (pstm_copy (a, c) != PSTM_OKAY) {
 | 
						|
			return PS_MEM_FAIL;
 | 
						|
		}
 | 
						|
		if (d != NULL) {
 | 
						|
			pstm_zero (d);
 | 
						|
		}
 | 
						|
		return PSTM_OKAY;
 | 
						|
	}
 | 
						|
 | 
						|
	/* get the remainder */
 | 
						|
	if (d != NULL) {
 | 
						|
		if (pstm_init(pool, &t) != PSTM_OKAY) {
 | 
						|
			return PS_MEM_FAIL;
 | 
						|
		}
 | 
						|
		if (pstm_mod_2d (a, b, &t) != PSTM_OKAY) {
 | 
						|
			res = PS_MEM_FAIL;
 | 
						|
			goto LBL_DONE;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* copy */
 | 
						|
	if (pstm_copy(a, c) != PSTM_OKAY) {
 | 
						|
		res = PS_MEM_FAIL;
 | 
						|
		goto LBL_DONE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* shift by as many digits in the bit count */
 | 
						|
	if (b >= (int32)DIGIT_BIT) {
 | 
						|
		pstm_rshd (c, b / DIGIT_BIT);
 | 
						|
	}
 | 
						|
 | 
						|
	/* shift any bit count < DIGIT_BIT */
 | 
						|
	D = (pstm_digit) (b % DIGIT_BIT);
 | 
						|
	if (D != 0) {
 | 
						|
		register pstm_digit *tmpc, mask, shift;
 | 
						|
 | 
						|
		/* mask */
 | 
						|
		mask = (((pstm_digit)1) << D) - 1;
 | 
						|
 | 
						|
		/* shift for lsb */
 | 
						|
		shift = DIGIT_BIT - D;
 | 
						|
 | 
						|
		/* alias */
 | 
						|
		tmpc = c->dp + (c->used - 1);
 | 
						|
 | 
						|
		/* carry */
 | 
						|
		r = 0;
 | 
						|
		for (x = c->used - 1; x >= 0; x--) {
 | 
						|
			/* get the lower  bits of this word in a temp */
 | 
						|
			rr = *tmpc & mask;
 | 
						|
 | 
						|
			/* shift the current word and mix in the carry bits from previous */
 | 
						|
			*tmpc = (*tmpc >> D) | (r << shift);
 | 
						|
			--tmpc;
 | 
						|
 | 
						|
			/* set the carry to the carry bits of the current word above */
 | 
						|
			r = rr;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	pstm_clamp (c);
 | 
						|
 | 
						|
	res = PSTM_OKAY;
 | 
						|
LBL_DONE:
 | 
						|
	if (d != NULL) {
 | 
						|
		if (pstm_copy(&t, d) != PSTM_OKAY) {
 | 
						|
			res = PS_MEM_FAIL;
 | 
						|
		}
 | 
						|
		pstm_clear(&t);
 | 
						|
	}
 | 
						|
	return res;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	b = a/2
 | 
						|
*/
 | 
						|
int32 pstm_div_2(pstm_int * a, pstm_int * b)
 | 
						|
{
 | 
						|
	int	x, oldused; //bbox: was int16
 | 
						|
 | 
						|
	if (b->alloc < a->used) {
 | 
						|
		if (pstm_grow(b, a->used) != PSTM_OKAY) {
 | 
						|
			return PS_MEM_FAIL;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	oldused = b->used;
 | 
						|
	b->used = a->used;
 | 
						|
	{
 | 
						|
		register pstm_digit r, rr, *tmpa, *tmpb;
 | 
						|
 | 
						|
		/* source alias */
 | 
						|
		tmpa = a->dp + b->used - 1;
 | 
						|
 | 
						|
		/* dest alias */
 | 
						|
		tmpb = b->dp + b->used - 1;
 | 
						|
 | 
						|
		/* carry */
 | 
						|
		r = 0;
 | 
						|
		for (x = b->used - 1; x >= 0; x--) {
 | 
						|
			/* get the carry for the next iteration */
 | 
						|
			rr = *tmpa & 1;
 | 
						|
 | 
						|
			/* shift the current digit, add in carry and store */
 | 
						|
			*tmpb-- = (*tmpa-- >> 1) | (r << (DIGIT_BIT - 1));
 | 
						|
 | 
						|
			/* forward carry to next iteration */
 | 
						|
			r = rr;
 | 
						|
		}
 | 
						|
 | 
						|
		/* zero excess digits */
 | 
						|
		tmpb = b->dp + b->used;
 | 
						|
		for (x = b->used; x < oldused; x++) {
 | 
						|
			*tmpb++ = 0;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	b->sign = a->sign;
 | 
						|
	pstm_clamp (b);
 | 
						|
	return PSTM_OKAY;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	Creates "a" then copies b into it
 | 
						|
 */
 | 
						|
int32 pstm_init_copy(psPool_t *pool, pstm_int * a, pstm_int * b, int toSqr)
 | 
						|
{
 | 
						|
	int	x; //bbox: was int16
 | 
						|
	int32	res;
 | 
						|
 | 
						|
	if (a == b) {
 | 
						|
		return PSTM_OKAY;
 | 
						|
	}
 | 
						|
	x = b->alloc;
 | 
						|
 | 
						|
	if (toSqr) {
 | 
						|
/*
 | 
						|
		Smart-size:  Increasing size of a if b->used is roughly half
 | 
						|
		of b->alloc because usage has shown that a lot of these copies
 | 
						|
		go on to be squared and need these extra digits
 | 
						|
*/
 | 
						|
		if ((b->used * 2) + 2 >= x) {
 | 
						|
			x = (b->used * 2) + 3;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if ((res = pstm_init_size(pool, a, x)) != PSTM_OKAY) {
 | 
						|
		return res;
 | 
						|
	}
 | 
						|
	return pstm_copy(b, a);
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	With some compilers, we have seen issues linking with the builtin
 | 
						|
	64 bit division routine. The issues with either manifest in a failure
 | 
						|
	to find 'udivdi3' at link time, or a runtime invalid instruction fault
 | 
						|
	during an RSA operation.
 | 
						|
	The routine below divides a 64 bit unsigned int by a 32 bit unsigned int
 | 
						|
	explicitly, rather than using the division operation
 | 
						|
		The 64 bit result is placed in the 'numerator' parameter
 | 
						|
		The 32 bit mod (remainder) of the division is the return parameter
 | 
						|
	Based on implementations by:
 | 
						|
		Copyright (C) 2003 Bernardo Innocenti <bernie@develer.com>
 | 
						|
		Copyright (C) 1999 Hewlett-Packard Co
 | 
						|
		Copyright (C) 1999 David Mosberger-Tang <davidm@hpl.hp.com>
 | 
						|
*/
 | 
						|
#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT)
 | 
						|
static uint32 psDiv64(uint64 *numerator, uint32 denominator)
 | 
						|
{
 | 
						|
	uint64	rem = *numerator;
 | 
						|
	uint64	b = denominator;
 | 
						|
	uint64	res = 0;
 | 
						|
	uint64	d = 1;
 | 
						|
	uint32	high = rem >> 32;
 | 
						|
 | 
						|
	if (high >= denominator) {
 | 
						|
		high /= denominator;
 | 
						|
		res = (uint64) high << 32;
 | 
						|
		rem -= (uint64) (high * denominator) << 32;
 | 
						|
	}
 | 
						|
	while ((int64)b > 0 && b < rem) {
 | 
						|
		b = b+b;
 | 
						|
		d = d+d;
 | 
						|
	}
 | 
						|
	do {
 | 
						|
		if (rem >= b) {
 | 
						|
			rem -= b;
 | 
						|
			res += d;
 | 
						|
		}
 | 
						|
		b >>= 1;
 | 
						|
		d >>= 1;
 | 
						|
	} while (d);
 | 
						|
	*numerator = res;
 | 
						|
	return rem;
 | 
						|
}
 | 
						|
#endif /* USE_MATRIX_DIV64 */
 | 
						|
 | 
						|
#if defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT)
 | 
						|
typedef unsigned long	uint128 __attribute__ ((mode(TI)));
 | 
						|
static uint64 psDiv128(uint128 *numerator, uint64 denominator)
 | 
						|
{
 | 
						|
	uint128	rem = *numerator;
 | 
						|
	uint128	b = denominator;
 | 
						|
	uint128	res = 0;
 | 
						|
	uint128	d = 1;
 | 
						|
	uint64	high = rem >> 64;
 | 
						|
 | 
						|
	if (high >= denominator) {
 | 
						|
		high /= denominator;
 | 
						|
		res = (uint128) high << 64;
 | 
						|
		rem -= (uint128) (high * denominator) << 64;
 | 
						|
	}
 | 
						|
	while ((uint128)b > 0 && b < rem) {
 | 
						|
		b = b+b;
 | 
						|
		d = d+d;
 | 
						|
	}
 | 
						|
	do {
 | 
						|
		if (rem >= b) {
 | 
						|
			rem -= b;
 | 
						|
			res += d;
 | 
						|
		}
 | 
						|
		b >>= 1;
 | 
						|
		d >>= 1;
 | 
						|
	} while (d);
 | 
						|
	*numerator = res;
 | 
						|
	return rem;
 | 
						|
}
 | 
						|
#endif /* USE_MATRIX_DIV128 */
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	a/b => cb + d == a
 | 
						|
*/
 | 
						|
int32 pstm_div(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
 | 
						|
				pstm_int *d)
 | 
						|
{
 | 
						|
	pstm_int	q, x, y, t1, t2;
 | 
						|
	int32		res;
 | 
						|
	int		n, t, i, norm, neg; //bbox: was int16
 | 
						|
 | 
						|
	/* is divisor zero ? */
 | 
						|
	if (pstm_iszero (b) == 1) {
 | 
						|
		return PS_LIMIT_FAIL;
 | 
						|
	}
 | 
						|
 | 
						|
	/* if a < b then q=0, r = a */
 | 
						|
	if (pstm_cmp_mag (a, b) == PSTM_LT) {
 | 
						|
		if (d != NULL) {
 | 
						|
			if (pstm_copy(a, d) != PSTM_OKAY) {
 | 
						|
				return PS_MEM_FAIL;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		if (c != NULL) {
 | 
						|
			pstm_zero (c);
 | 
						|
		}
 | 
						|
		return PSTM_OKAY;
 | 
						|
	}
 | 
						|
/*
 | 
						|
	Smart-size inits
 | 
						|
*/
 | 
						|
	if ((res = pstm_init_size(pool, &t1, a->alloc)) != PSTM_OKAY) {
 | 
						|
		return res;
 | 
						|
	}
 | 
						|
	if ((res = pstm_init_size(pool, &t2, 3)) != PSTM_OKAY) {
 | 
						|
		goto LBL_T1;
 | 
						|
	}
 | 
						|
	if ((res = pstm_init_copy(pool, &x, a, 0)) != PSTM_OKAY) {
 | 
						|
		goto LBL_T2;
 | 
						|
	}
 | 
						|
/*
 | 
						|
	Used to be an init_copy on b but pstm_grow was always hit with triple size
 | 
						|
*/
 | 
						|
	if ((res = pstm_init_size(pool, &y, b->used * 3)) != PSTM_OKAY) {
 | 
						|
		goto LBL_X;
 | 
						|
	}
 | 
						|
	if ((res = pstm_copy(b, &y)) != PSTM_OKAY) {
 | 
						|
		goto LBL_Y;
 | 
						|
	}
 | 
						|
 | 
						|
	/* fix the sign */
 | 
						|
	neg = (a->sign == b->sign) ? PSTM_ZPOS : PSTM_NEG;
 | 
						|
	x.sign = y.sign = PSTM_ZPOS;
 | 
						|
 | 
						|
	/* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */
 | 
						|
	norm = pstm_count_bits(&y) % DIGIT_BIT;
 | 
						|
	if (norm < (int32)(DIGIT_BIT-1)) {
 | 
						|
		norm = (DIGIT_BIT-1) - norm;
 | 
						|
		if ((res = pstm_mul_2d(&x, norm, &x)) != PSTM_OKAY) {
 | 
						|
			goto LBL_Y;
 | 
						|
		}
 | 
						|
		if ((res = pstm_mul_2d(&y, norm, &y)) != PSTM_OKAY) {
 | 
						|
			goto LBL_Y;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		norm = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	/* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */
 | 
						|
	n = x.used - 1;
 | 
						|
	t = y.used - 1;
 | 
						|
 | 
						|
	if ((res = pstm_init_size(pool, &q, n - t + 1)) != PSTM_OKAY) {
 | 
						|
		goto LBL_Y;
 | 
						|
	}
 | 
						|
	q.used = n - t + 1;
 | 
						|
 | 
						|
	/* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */
 | 
						|
	if ((res = pstm_lshd(&y, n - t)) != PSTM_OKAY) { /* y = y*b**{n-t} */
 | 
						|
		goto LBL_Q;
 | 
						|
	}
 | 
						|
 | 
						|
	while (pstm_cmp (&x, &y) != PSTM_LT) {
 | 
						|
		++(q.dp[n - t]);
 | 
						|
		if ((res = pstm_sub(&x, &y, &x)) != PSTM_OKAY) {
 | 
						|
			goto LBL_Q;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* reset y by shifting it back down */
 | 
						|
	pstm_rshd (&y, n - t);
 | 
						|
 | 
						|
	/* step 3. for i from n down to (t + 1) */
 | 
						|
	for (i = n; i >= (t + 1); i--) {
 | 
						|
		if (i > x.used) {
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		/* step 3.1 if xi == yt then set q{i-t-1} to b-1,
 | 
						|
		 * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */
 | 
						|
		if (x.dp[i] == y.dp[t]) {
 | 
						|
			q.dp[i - t - 1] = (pstm_digit)((((pstm_word)1) << DIGIT_BIT) - 1);
 | 
						|
		} else {
 | 
						|
			pstm_word tmp;
 | 
						|
			tmp = ((pstm_word) x.dp[i]) << ((pstm_word) DIGIT_BIT);
 | 
						|
			tmp |= ((pstm_word) x.dp[i - 1]);
 | 
						|
#if defined(USE_MATRIX_DIV64) && defined(PSTM_32BIT)
 | 
						|
			psDiv64(&tmp, y.dp[t]);
 | 
						|
#elif defined(USE_MATRIX_DIV128) && defined(PSTM_64BIT)
 | 
						|
			psDiv128(&tmp, y.dp[t]);
 | 
						|
#else
 | 
						|
			tmp /= ((pstm_word) y.dp[t]);
 | 
						|
#endif /* USE_MATRIX_DIV64 */
 | 
						|
			q.dp[i - t - 1] = (pstm_digit) (tmp);
 | 
						|
		}
 | 
						|
 | 
						|
		/* while (q{i-t-1} * (yt * b + y{t-1})) >
 | 
						|
			 xi * b**2 + xi-1 * b + xi-2
 | 
						|
 | 
						|
			do q{i-t-1} -= 1;
 | 
						|
		*/
 | 
						|
		q.dp[i - t - 1] = (q.dp[i - t - 1] + 1);
 | 
						|
		do {
 | 
						|
			q.dp[i - t - 1] = (q.dp[i - t - 1] - 1);
 | 
						|
 | 
						|
			/* find left hand */
 | 
						|
			pstm_zero (&t1);
 | 
						|
			t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];
 | 
						|
			t1.dp[1] = y.dp[t];
 | 
						|
			t1.used = 2;
 | 
						|
			if ((res = pstm_mul_d (&t1, q.dp[i - t - 1], &t1)) != PSTM_OKAY) {
 | 
						|
				goto LBL_Q;
 | 
						|
			}
 | 
						|
 | 
						|
			/* find right hand */
 | 
						|
			t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];
 | 
						|
			t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];
 | 
						|
			t2.dp[2] = x.dp[i];
 | 
						|
			t2.used = 3;
 | 
						|
		} while (pstm_cmp_mag(&t1, &t2) == PSTM_GT);
 | 
						|
 | 
						|
		/* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */
 | 
						|
		if ((res = pstm_mul_d(&y, q.dp[i - t - 1], &t1)) != PSTM_OKAY) {
 | 
						|
			goto LBL_Q;
 | 
						|
		}
 | 
						|
 | 
						|
		if ((res = pstm_lshd(&t1, i - t - 1)) != PSTM_OKAY) {
 | 
						|
			goto LBL_Q;
 | 
						|
		}
 | 
						|
 | 
						|
		if ((res = pstm_sub(&x, &t1, &x)) != PSTM_OKAY) {
 | 
						|
			goto LBL_Q;
 | 
						|
		}
 | 
						|
 | 
						|
		/* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */
 | 
						|
		if (x.sign == PSTM_NEG) {
 | 
						|
			if ((res = pstm_copy(&y, &t1)) != PSTM_OKAY) {
 | 
						|
				goto LBL_Q;
 | 
						|
			}
 | 
						|
			if ((res = pstm_lshd (&t1, i - t - 1)) != PSTM_OKAY) {
 | 
						|
				goto LBL_Q;
 | 
						|
			}
 | 
						|
			if ((res = pstm_add (&x, &t1, &x)) != PSTM_OKAY) {
 | 
						|
				goto LBL_Q;
 | 
						|
			}
 | 
						|
			q.dp[i - t - 1] = q.dp[i - t - 1] - 1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
/*
 | 
						|
	now q is the quotient and x is the remainder (which we have to normalize)
 | 
						|
*/
 | 
						|
	/* get sign before writing to c */
 | 
						|
	x.sign = x.used == 0 ? PSTM_ZPOS : a->sign;
 | 
						|
 | 
						|
	if (c != NULL) {
 | 
						|
		pstm_clamp (&q);
 | 
						|
		if (pstm_copy (&q, c) != PSTM_OKAY) {
 | 
						|
			res = PS_MEM_FAIL;
 | 
						|
			goto LBL_Q;
 | 
						|
		}
 | 
						|
		c->sign = neg;
 | 
						|
	}
 | 
						|
 | 
						|
	if (d != NULL) {
 | 
						|
		if ((res = pstm_div_2d (pool, &x, norm, &x, NULL)) != PSTM_OKAY) {
 | 
						|
			goto LBL_Q;
 | 
						|
		}
 | 
						|
/*
 | 
						|
		the following is a kludge, essentially we were seeing the right
 | 
						|
		remainder but with excess digits that should have been zero
 | 
						|
 */
 | 
						|
		for (i = b->used; i < x.used; i++) {
 | 
						|
			x.dp[i] = 0;
 | 
						|
		}
 | 
						|
		pstm_clamp(&x);
 | 
						|
		if (pstm_copy (&x, d) != PSTM_OKAY) {
 | 
						|
			res = PS_MEM_FAIL;
 | 
						|
			goto LBL_Q;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	res = PSTM_OKAY;
 | 
						|
 | 
						|
LBL_Q:pstm_clear (&q);
 | 
						|
LBL_Y:pstm_clear (&y);
 | 
						|
LBL_X:pstm_clear (&x);
 | 
						|
LBL_T2:pstm_clear (&t2);
 | 
						|
LBL_T1:pstm_clear (&t1);
 | 
						|
 | 
						|
	return res;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	Swap the elements of two integers, for cases where you can't simply swap
 | 
						|
	the pstm_int pointers around
 | 
						|
*/
 | 
						|
void pstm_exch(pstm_int * a, pstm_int * b)
 | 
						|
{
 | 
						|
	pstm_int		t;
 | 
						|
 | 
						|
	t	= *a;
 | 
						|
	*a	= *b;
 | 
						|
	*b	= t;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	c = a mod b, 0 <= c < b
 | 
						|
*/
 | 
						|
int32 pstm_mod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c)
 | 
						|
{
 | 
						|
	pstm_int	t;
 | 
						|
	int32		err;
 | 
						|
/*
 | 
						|
	Smart-size
 | 
						|
*/
 | 
						|
	if ((err = pstm_init_size(pool, &t, b->alloc)) != PSTM_OKAY) {
 | 
						|
		return err;
 | 
						|
	}
 | 
						|
	if ((err = pstm_div(pool, a, b, NULL, &t)) != PSTM_OKAY) {
 | 
						|
		pstm_clear (&t);
 | 
						|
		return err;
 | 
						|
	}
 | 
						|
	if (t.sign != b->sign) {
 | 
						|
		err = pstm_add(&t, b, c);
 | 
						|
	} else {
 | 
						|
		pstm_exch (&t, c);
 | 
						|
	}
 | 
						|
	pstm_clear (&t);
 | 
						|
	return err;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	d = a * b (mod c)
 | 
						|
*/
 | 
						|
int32 pstm_mulmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c,
 | 
						|
			pstm_int *d)
 | 
						|
{
 | 
						|
	int32		res;
 | 
						|
	int		size; //bbox: was int16
 | 
						|
	pstm_int	tmp;
 | 
						|
 | 
						|
/*
 | 
						|
	Smart-size pstm_inits.  d is an output that is influenced by this local 't'
 | 
						|
	so don't shrink 'd' if it wants to becuase this will lead to an pstm_grow
 | 
						|
	in RSA operations
 | 
						|
*/
 | 
						|
	size = a->used + b->used + 1;
 | 
						|
	if ((a == d) && (size < a->alloc)) {
 | 
						|
		size = a->alloc;
 | 
						|
	}
 | 
						|
	if ((res = pstm_init_size(pool, &tmp, size)) != PSTM_OKAY) {
 | 
						|
		return res;
 | 
						|
	}
 | 
						|
	if ((res = pstm_mul_comba(pool, a, b, &tmp, NULL, 0)) != PSTM_OKAY) {
 | 
						|
		pstm_clear(&tmp);
 | 
						|
		return res;
 | 
						|
	}
 | 
						|
	res = pstm_mod(pool, &tmp, c, d);
 | 
						|
	pstm_clear(&tmp);
 | 
						|
	return res;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
 *	y = g**x (mod b)
 | 
						|
 *	Some restrictions... x must be positive and < b
 | 
						|
 */
 | 
						|
int32 pstm_exptmod(psPool_t *pool, pstm_int *G, pstm_int *X, pstm_int *P,
 | 
						|
			pstm_int *Y)
 | 
						|
{
 | 
						|
	pstm_int	M[32], res; /* Keep this winsize based: (1 << max_winsize) */
 | 
						|
	pstm_digit	buf, mp;
 | 
						|
	pstm_digit	*paD;
 | 
						|
	int32		err, bitbuf;
 | 
						|
	int		bitcpy, bitcnt, mode, digidx, x, y, winsize; //bbox: was int16
 | 
						|
	uint32		paDlen;
 | 
						|
 | 
						|
	/* set window size from what user set as optimization */
 | 
						|
	x = pstm_count_bits(X);
 | 
						|
	if (x < 50) {
 | 
						|
		winsize = 2;
 | 
						|
	} else {
 | 
						|
		winsize = PS_EXPTMOD_WINSIZE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* now setup montgomery  */
 | 
						|
	if ((err = pstm_montgomery_setup (P, &mp)) != PSTM_OKAY) {
 | 
						|
		return err;
 | 
						|
	}
 | 
						|
 | 
						|
	/* setup result */
 | 
						|
	if ((err = pstm_init_size(pool, &res, (P->used * 2) + 1)) != PSTM_OKAY) {
 | 
						|
		return err;
 | 
						|
	}
 | 
						|
/*
 | 
						|
	create M table
 | 
						|
	The M table contains powers of the input base, e.g. M[x] = G^x mod P
 | 
						|
	The first half of the table is not computed though except for M[0] and M[1]
 | 
						|
 */
 | 
						|
	/* now we need R mod m */
 | 
						|
	if ((err = pstm_montgomery_calc_normalization (&res, P)) != PSTM_OKAY) {
 | 
						|
		goto LBL_RES;
 | 
						|
	}
 | 
						|
/*
 | 
						|
	init M array
 | 
						|
	init first cell
 | 
						|
 */
 | 
						|
	if ((err = pstm_init_size(pool, &M[1], res.used)) != PSTM_OKAY) {
 | 
						|
		goto LBL_RES;
 | 
						|
	}
 | 
						|
 | 
						|
	/* now set M[1] to G * R mod m */
 | 
						|
	if (pstm_cmp_mag(P, G) != PSTM_GT) {
 | 
						|
		/* G > P so we reduce it first */
 | 
						|
		if ((err = pstm_mod(pool, G, P, &M[1])) != PSTM_OKAY) {
 | 
						|
			goto LBL_M;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if ((err = pstm_copy(G, &M[1])) != PSTM_OKAY) {
 | 
						|
			goto LBL_M;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if ((err = pstm_mulmod (pool, &M[1], &res, P, &M[1])) != PSTM_OKAY) {
 | 
						|
		goto LBL_M;
 | 
						|
	}
 | 
						|
/*
 | 
						|
	Pre-allocated digit.  Used for mul, sqr, AND reduce
 | 
						|
*/
 | 
						|
	paDlen = ((M[1].used + 3) * 2) * sizeof(pstm_digit);
 | 
						|
	paD = xzalloc(paDlen);//bbox
 | 
						|
/*
 | 
						|
	compute the value at M[1<<(winsize-1)] by squaring M[1] (winsize-1) times
 | 
						|
 */
 | 
						|
	if (pstm_init_copy(pool, &M[1 << (winsize - 1)], &M[1], 1) != PSTM_OKAY) {
 | 
						|
		err = PS_MEM_FAIL;
 | 
						|
		goto LBL_PAD;
 | 
						|
	}
 | 
						|
	for (x = 0; x < (winsize - 1); x++) {
 | 
						|
		if ((err = pstm_sqr_comba (pool, &M[1 << (winsize - 1)],
 | 
						|
				&M[1 << (winsize - 1)], paD, paDlen)) != PSTM_OKAY) {
 | 
						|
			goto LBL_PAD;
 | 
						|
		}
 | 
						|
		if ((err = pstm_montgomery_reduce(pool, &M[1 << (winsize - 1)], P, mp,
 | 
						|
				paD, paDlen)) != PSTM_OKAY) {
 | 
						|
			goto LBL_PAD;
 | 
						|
		}
 | 
						|
	}
 | 
						|
/*
 | 
						|
	now init the second half of the array
 | 
						|
*/
 | 
						|
	for (x = (1<<(winsize-1)) + 1; x < (1 << winsize); x++) {
 | 
						|
		if ((err = pstm_init_size(pool, &M[x], M[1<<(winsize-1)].alloc + 1))
 | 
						|
				!= PSTM_OKAY) {
 | 
						|
			for (y = 1<<(winsize-1); y < x; y++) {
 | 
						|
				pstm_clear(&M[y]);
 | 
						|
			}
 | 
						|
			goto LBL_PAD;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* create upper table */
 | 
						|
	for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {
 | 
						|
		if ((err = pstm_mul_comba(pool, &M[x - 1], &M[1], &M[x], paD, paDlen))
 | 
						|
				!= PSTM_OKAY) {
 | 
						|
			goto LBL_MARRAY;
 | 
						|
		}
 | 
						|
		if ((err = pstm_montgomery_reduce(pool, &M[x], P, mp, paD, paDlen)) !=
 | 
						|
				PSTM_OKAY) {
 | 
						|
			goto LBL_MARRAY;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* set initial mode and bit cnt */
 | 
						|
	mode   = 0;
 | 
						|
	bitcnt = 1;
 | 
						|
	buf    = 0;
 | 
						|
	digidx = X->used - 1;
 | 
						|
	bitcpy = 0;
 | 
						|
	bitbuf = 0;
 | 
						|
 | 
						|
	for (;;) {
 | 
						|
		/* grab next digit as required */
 | 
						|
		if (--bitcnt == 0) {
 | 
						|
			/* if digidx == -1 we are out of digits so break */
 | 
						|
			if (digidx == -1) {
 | 
						|
				break;
 | 
						|
			}
 | 
						|
			/* read next digit and reset bitcnt */
 | 
						|
			buf    = X->dp[digidx--];
 | 
						|
			bitcnt = (int32)DIGIT_BIT;
 | 
						|
		}
 | 
						|
 | 
						|
		/* grab the next msb from the exponent */
 | 
						|
		y     = (pstm_digit)(buf >> (DIGIT_BIT - 1)) & 1;
 | 
						|
		buf <<= (pstm_digit)1;
 | 
						|
/*
 | 
						|
		 If the bit is zero and mode == 0 then we ignore it.
 | 
						|
		 These represent the leading zero bits before the first 1 bit
 | 
						|
		 in the exponent.  Technically this opt is not required but it
 | 
						|
		 does lower the # of trivial squaring/reductions used
 | 
						|
*/
 | 
						|
		if (mode == 0 && y == 0) {
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		/* if the bit is zero and mode == 1 then we square */
 | 
						|
		if (mode == 1 && y == 0) {
 | 
						|
			if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
 | 
						|
					PSTM_OKAY) {
 | 
						|
				goto LBL_MARRAY;
 | 
						|
			}
 | 
						|
			if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
 | 
						|
					!= PSTM_OKAY) {
 | 
						|
				goto LBL_MARRAY;
 | 
						|
			}
 | 
						|
			continue;
 | 
						|
		}
 | 
						|
 | 
						|
		/* else we add it to the window */
 | 
						|
		bitbuf |= (y << (winsize - ++bitcpy));
 | 
						|
		mode    = 2;
 | 
						|
 | 
						|
		if (bitcpy == winsize) {
 | 
						|
			/* ok window is filled so square as required and mul square first */
 | 
						|
			for (x = 0; x < winsize; x++) {
 | 
						|
				if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
 | 
						|
						PSTM_OKAY) {
 | 
						|
					goto LBL_MARRAY;
 | 
						|
				}
 | 
						|
				if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD,
 | 
						|
						paDlen)) != PSTM_OKAY) {
 | 
						|
					goto LBL_MARRAY;
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			/* then multiply */
 | 
						|
			if ((err = pstm_mul_comba(pool, &res, &M[bitbuf], &res, paD,
 | 
						|
					paDlen)) != PSTM_OKAY) {
 | 
						|
				goto LBL_MARRAY;
 | 
						|
			}
 | 
						|
			if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
 | 
						|
					!= PSTM_OKAY) {
 | 
						|
				goto LBL_MARRAY;
 | 
						|
			}
 | 
						|
 | 
						|
			/* empty window and reset */
 | 
						|
			bitcpy = 0;
 | 
						|
			bitbuf = 0;
 | 
						|
			mode   = 1;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* if bits remain then square/multiply */
 | 
						|
	if (mode == 2 && bitcpy > 0) {
 | 
						|
		/* square then multiply if the bit is set */
 | 
						|
		for (x = 0; x < bitcpy; x++) {
 | 
						|
			if ((err = pstm_sqr_comba(pool, &res, &res, paD, paDlen)) !=
 | 
						|
					PSTM_OKAY) {
 | 
						|
				goto LBL_MARRAY;
 | 
						|
			}
 | 
						|
			if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen))
 | 
						|
					!= PSTM_OKAY) {
 | 
						|
				goto LBL_MARRAY;
 | 
						|
			}
 | 
						|
 | 
						|
			/* get next bit of the window */
 | 
						|
			bitbuf <<= 1;
 | 
						|
			if ((bitbuf & (1 << winsize)) != 0) {
 | 
						|
			/* then multiply */
 | 
						|
				if ((err = pstm_mul_comba(pool, &res, &M[1], &res, paD, paDlen))
 | 
						|
						!= PSTM_OKAY) {
 | 
						|
					goto LBL_MARRAY;
 | 
						|
				}
 | 
						|
				if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD,
 | 
						|
						paDlen)) != PSTM_OKAY) {
 | 
						|
					goto LBL_MARRAY;
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
/*
 | 
						|
	Fix up result if Montgomery reduction is used recall that any value in a
 | 
						|
	Montgomery system is actually multiplied by R mod n.  So we have to reduce
 | 
						|
	one more time to cancel out the factor of R.
 | 
						|
*/
 | 
						|
	if ((err = pstm_montgomery_reduce(pool, &res, P, mp, paD, paDlen)) !=
 | 
						|
			PSTM_OKAY) {
 | 
						|
		goto LBL_MARRAY;
 | 
						|
	}
 | 
						|
	/* swap res with Y */
 | 
						|
	if ((err = pstm_copy (&res, Y)) != PSTM_OKAY) {
 | 
						|
		goto LBL_MARRAY;
 | 
						|
	}
 | 
						|
	err = PSTM_OKAY;
 | 
						|
LBL_MARRAY:
 | 
						|
	for (x = 1<<(winsize-1); x < (1 << winsize); x++) {
 | 
						|
		pstm_clear(&M[x]);
 | 
						|
	}
 | 
						|
LBL_PAD:psFree(paD, pool);
 | 
						|
LBL_M: pstm_clear(&M[1]);
 | 
						|
LBL_RES:pstm_clear(&res);
 | 
						|
	return err;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
 | 
						|
*/
 | 
						|
int32 pstm_add(pstm_int *a, pstm_int *b, pstm_int *c)
 | 
						|
{
 | 
						|
	int32	res;
 | 
						|
	int	sa, sb; //bbox: was int16
 | 
						|
 | 
						|
	/* get sign of both inputs */
 | 
						|
	sa = a->sign;
 | 
						|
	sb = b->sign;
 | 
						|
 | 
						|
	/* handle two cases, not four */
 | 
						|
	if (sa == sb) {
 | 
						|
		/* both positive or both negative, add their mags, copy the sign */
 | 
						|
		c->sign = sa;
 | 
						|
		if ((res = s_pstm_add (a, b, c)) != PSTM_OKAY) {
 | 
						|
			return res;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
/*
 | 
						|
		one positive, the other negative
 | 
						|
		subtract the one with the greater magnitude from the one of the lesser
 | 
						|
		magnitude. The result gets the sign of the one with the greater mag.
 | 
						|
 */
 | 
						|
		if (pstm_cmp_mag (a, b) == PSTM_LT) {
 | 
						|
			c->sign = sb;
 | 
						|
			if ((res = s_pstm_sub (b, a, c)) != PSTM_OKAY) {
 | 
						|
				return res;
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			c->sign = sa;
 | 
						|
			if ((res = s_pstm_sub (a, b, c)) != PSTM_OKAY) {
 | 
						|
				return res;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return PS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	reverse an array, used for radix code
 | 
						|
*/
 | 
						|
static void pstm_reverse (unsigned char *s, int len) //bbox: was int16 len
 | 
						|
{
 | 
						|
	int32     ix, iy;
 | 
						|
	unsigned char t;
 | 
						|
 | 
						|
	ix = 0;
 | 
						|
	iy = len - 1;
 | 
						|
	while (ix < iy) {
 | 
						|
		t     = s[ix];
 | 
						|
		s[ix] = s[iy];
 | 
						|
		s[iy] = t;
 | 
						|
		++ix;
 | 
						|
		--iy;
 | 
						|
	}
 | 
						|
}
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	No reverse.  Useful in some of the EIP-154 PKA stuff where special byte
 | 
						|
	order seems to come into play more often
 | 
						|
*/
 | 
						|
int32 pstm_to_unsigned_bin_nr(psPool_t *pool, pstm_int *a, unsigned char *b)
 | 
						|
{
 | 
						|
	int32     res;
 | 
						|
	int     x; //bbox: was int16
 | 
						|
	pstm_int  t = { 0 };
 | 
						|
 | 
						|
	if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) {
 | 
						|
		return res;
 | 
						|
	}
 | 
						|
 | 
						|
	x = 0;
 | 
						|
	while (pstm_iszero (&t) == 0) {
 | 
						|
		b[x++] = (unsigned char) (t.dp[0] & 255);
 | 
						|
		if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) {
 | 
						|
			pstm_clear(&t);
 | 
						|
			return res;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	pstm_clear(&t);
 | 
						|
	return PS_SUCCESS;
 | 
						|
}
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
 | 
						|
*/
 | 
						|
int32 pstm_to_unsigned_bin(psPool_t *pool, pstm_int *a, unsigned char *b)
 | 
						|
{
 | 
						|
	int32     res;
 | 
						|
	int	x; //bbox: was int16
 | 
						|
	pstm_int  t = { 0 };
 | 
						|
 | 
						|
	if ((res = pstm_init_copy(pool, &t, a, 0)) != PSTM_OKAY) {
 | 
						|
		return res;
 | 
						|
	}
 | 
						|
 | 
						|
	x = 0;
 | 
						|
	while (pstm_iszero (&t) == 0) {
 | 
						|
		b[x++] = (unsigned char) (t.dp[0] & 255);
 | 
						|
		if ((res = pstm_div_2d (pool, &t, 8, &t, NULL)) != PSTM_OKAY) {
 | 
						|
			pstm_clear(&t);
 | 
						|
			return res;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	pstm_reverse (b, x);
 | 
						|
	pstm_clear(&t);
 | 
						|
	return PS_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************************/
 | 
						|
/*
 | 
						|
	compare against a single digit
 | 
						|
*/
 | 
						|
int32 pstm_cmp_d(pstm_int *a, pstm_digit b)
 | 
						|
{
 | 
						|
	/* compare based on sign */
 | 
						|
	if ((b && a->used == 0) || a->sign == PSTM_NEG) {
 | 
						|
		return PSTM_LT;
 | 
						|
	}
 | 
						|
 | 
						|
	/* compare based on magnitude */
 | 
						|
	if (a->used > 1) {
 | 
						|
		return PSTM_GT;
 | 
						|
	}
 | 
						|
 | 
						|
	/* compare the only digit of a to b */
 | 
						|
	if (a->dp[0] > b) {
 | 
						|
		return PSTM_GT;
 | 
						|
	} else if (a->dp[0] < b) {
 | 
						|
		return PSTM_LT;
 | 
						|
	} else {
 | 
						|
		return PSTM_EQ;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
	Need invmod for ECC and also private key loading for hardware crypto
 | 
						|
	in cases where dQ > dP.  The values must be switched and a new qP must be
 | 
						|
	calculated using this function
 | 
						|
*/
 | 
						|
//bbox: pool unused
 | 
						|
#define pstm_invmod_slow(pool, a, b, c) \
 | 
						|
        pstm_invmod_slow(      a, b, c)
 | 
						|
static int32 pstm_invmod_slow(psPool_t *pool, pstm_int * a, pstm_int * b,
 | 
						|
				pstm_int * c)
 | 
						|
{
 | 
						|
	pstm_int  x, y, u, v, A, B, C, D;
 | 
						|
	int32     res;
 | 
						|
 | 
						|
	/* b cannot be negative */
 | 
						|
	if (b->sign == PSTM_NEG || pstm_iszero(b) == 1) {
 | 
						|
		return PS_LIMIT_FAIL;
 | 
						|
	}
 | 
						|
 | 
						|
	/* init temps */
 | 
						|
	if (pstm_init_size(pool, &x, b->used) != PSTM_OKAY) {
 | 
						|
		return PS_MEM_FAIL;
 | 
						|
	}
 | 
						|
 | 
						|
	/* x = a, y = b */
 | 
						|
	if ((res = pstm_mod(pool, a, b, &x)) != PSTM_OKAY) {
 | 
						|
		goto LBL_X;
 | 
						|
	}
 | 
						|
 | 
						|
	if (pstm_init_copy(pool, &y, b, 0) != PSTM_OKAY) {
 | 
						|
		goto LBL_X;
 | 
						|
	}
 | 
						|
 | 
						|
	/* 2. [modified] if x,y are both even then return an error! */
 | 
						|
	if (pstm_iseven (&x) == 1 && pstm_iseven (&y) == 1) {
 | 
						|
		res = PS_FAILURE;
 | 
						|
		goto LBL_Y;
 | 
						|
	}
 | 
						|
 | 
						|
	/* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
 | 
						|
	if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) {
 | 
						|
		goto LBL_Y;
 | 
						|
	}
 | 
						|
	if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) {
 | 
						|
		goto LBL_U;
 | 
						|
	}
 | 
						|
 | 
						|
	if ((res = pstm_init_size(pool, &A, sizeof(pstm_digit))) != PSTM_OKAY) {
 | 
						|
		goto LBL_V;
 | 
						|
	}
 | 
						|
 | 
						|
	if ((res = pstm_init_size(pool, &D, sizeof(pstm_digit))) != PSTM_OKAY) {
 | 
						|
		goto LBL_A;
 | 
						|
	}
 | 
						|
	pstm_set (&A, 1);
 | 
						|
	pstm_set (&D, 1);
 | 
						|
 | 
						|
	if ((res = pstm_init(pool, &B)) != PSTM_OKAY) {
 | 
						|
		goto LBL_D;
 | 
						|
	}
 | 
						|
	if ((res = pstm_init(pool, &C)) != PSTM_OKAY) {
 | 
						|
		goto LBL_B;
 | 
						|
	}
 | 
						|
 | 
						|
top:
 | 
						|
	/* 4.  while u is even do */
 | 
						|
	while (pstm_iseven (&u) == 1) {
 | 
						|
		/* 4.1 u = u/2 */
 | 
						|
		if ((res = pstm_div_2 (&u, &u)) != PSTM_OKAY) {
 | 
						|
			goto LBL_C;
 | 
						|
		}
 | 
						|
 | 
						|
		/* 4.2 if A or B is odd then */
 | 
						|
		if (pstm_isodd (&A) == 1 || pstm_isodd (&B) == 1) {
 | 
						|
			/* A = (A+y)/2, B = (B-x)/2 */
 | 
						|
			if ((res = pstm_add (&A, &y, &A)) != PSTM_OKAY) {
 | 
						|
				goto LBL_C;
 | 
						|
			}
 | 
						|
			if ((res = pstm_sub (&B, &x, &B)) != PSTM_OKAY) {
 | 
						|
				goto LBL_C;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		/* A = A/2, B = B/2 */
 | 
						|
		if ((res = pstm_div_2 (&A, &A)) != PSTM_OKAY) {
 | 
						|
			goto LBL_C;
 | 
						|
		}
 | 
						|
		if ((res = pstm_div_2 (&B, &B)) != PSTM_OKAY) {
 | 
						|
			goto LBL_C;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* 5.  while v is even do */
 | 
						|
	while (pstm_iseven (&v) == 1) {
 | 
						|
		/* 5.1 v = v/2 */
 | 
						|
		if ((res = pstm_div_2 (&v, &v)) != PSTM_OKAY) {
 | 
						|
			goto LBL_C;
 | 
						|
		}
 | 
						|
 | 
						|
		/* 5.2 if C or D is odd then */
 | 
						|
		if (pstm_isodd (&C) == 1 || pstm_isodd (&D) == 1) {
 | 
						|
			/* C = (C+y)/2, D = (D-x)/2 */
 | 
						|
			if ((res = pstm_add (&C, &y, &C)) != PSTM_OKAY) {
 | 
						|
				goto LBL_C;
 | 
						|
			}
 | 
						|
			if ((res = pstm_sub (&D, &x, &D)) != PSTM_OKAY) {
 | 
						|
				goto LBL_C;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		/* C = C/2, D = D/2 */
 | 
						|
		if ((res = pstm_div_2 (&C, &C)) != PSTM_OKAY) {
 | 
						|
			goto LBL_C;
 | 
						|
		}
 | 
						|
		if ((res = pstm_div_2 (&D, &D)) != PSTM_OKAY) {
 | 
						|
			goto LBL_C;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* 6.  if u >= v then */
 | 
						|
	if (pstm_cmp (&u, &v) != PSTM_LT) {
 | 
						|
		/* u = u - v, A = A - C, B = B - D */
 | 
						|
		if ((res = pstm_sub (&u, &v, &u)) != PSTM_OKAY) {
 | 
						|
				goto LBL_C;
 | 
						|
		}
 | 
						|
		if ((res = pstm_sub (&A, &C, &A)) != PSTM_OKAY) {
 | 
						|
				goto LBL_C;
 | 
						|
		}
 | 
						|
		if ((res = pstm_sub (&B, &D, &B)) != PSTM_OKAY) {
 | 
						|
				goto LBL_C;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		/* v - v - u, C = C - A, D = D - B */
 | 
						|
		if ((res = pstm_sub (&v, &u, &v)) != PSTM_OKAY) {
 | 
						|
				goto LBL_C;
 | 
						|
		}
 | 
						|
		if ((res = pstm_sub (&C, &A, &C)) != PSTM_OKAY) {
 | 
						|
				goto LBL_C;
 | 
						|
		}
 | 
						|
		if ((res = pstm_sub (&D, &B, &D)) != PSTM_OKAY) {
 | 
						|
				goto LBL_C;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* if not zero goto step 4 */
 | 
						|
	if (pstm_iszero (&u) == 0)
 | 
						|
		goto top;
 | 
						|
 | 
						|
	/* now a = C, b = D, gcd == g*v */
 | 
						|
 | 
						|
	/* if v != 1 then there is no inverse */
 | 
						|
	if (pstm_cmp_d (&v, 1) != PSTM_EQ) {
 | 
						|
		res = PS_FAILURE;
 | 
						|
		goto LBL_C;
 | 
						|
	}
 | 
						|
 | 
						|
	/* if its too low */
 | 
						|
	while (pstm_cmp_d(&C, 0) == PSTM_LT) {
 | 
						|
		if ((res = pstm_add(&C, b, &C)) != PSTM_OKAY) {
 | 
						|
			goto LBL_C;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* too big */
 | 
						|
	while (pstm_cmp_mag(&C, b) != PSTM_LT) {
 | 
						|
		if ((res = pstm_sub(&C, b, &C)) != PSTM_OKAY) {
 | 
						|
			goto LBL_C;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* C is now the inverse */
 | 
						|
	if ((res = pstm_copy(&C, c)) != PSTM_OKAY) {
 | 
						|
		goto LBL_C;
 | 
						|
	}
 | 
						|
	res = PSTM_OKAY;
 | 
						|
 | 
						|
LBL_C: pstm_clear(&C);
 | 
						|
LBL_D: pstm_clear(&D);
 | 
						|
LBL_B: pstm_clear(&B);
 | 
						|
LBL_A: pstm_clear(&A);
 | 
						|
LBL_V: pstm_clear(&v);
 | 
						|
LBL_U: pstm_clear(&u);
 | 
						|
LBL_Y: pstm_clear(&y);
 | 
						|
LBL_X: pstm_clear(&x);
 | 
						|
 | 
						|
	return res;
 | 
						|
}
 | 
						|
 | 
						|
/* c = 1/a (mod b) for odd b only */
 | 
						|
int32 pstm_invmod(psPool_t *pool, pstm_int *a, pstm_int *b, pstm_int *c)
 | 
						|
{
 | 
						|
	pstm_int	x, y, u, v, B, D;
 | 
						|
	int32		res;
 | 
						|
	int		neg, sanity; //bbox: was uint16
 | 
						|
 | 
						|
	/* 2. [modified] b must be odd   */
 | 
						|
	if (pstm_iseven (b) == 1) {
 | 
						|
		return pstm_invmod_slow(pool, a,b,c);
 | 
						|
	}
 | 
						|
 | 
						|
	/* x == modulus, y == value to invert */
 | 
						|
	if ((res = pstm_init_copy(pool, &x, b, 0)) != PSTM_OKAY) {
 | 
						|
		return res;
 | 
						|
	}
 | 
						|
 | 
						|
	if ((res = pstm_init_size(pool, &y, a->alloc)) != PSTM_OKAY) {
 | 
						|
		goto LBL_X;
 | 
						|
	}
 | 
						|
 | 
						|
	/* we need y = |a| */
 | 
						|
	pstm_abs(a, &y);
 | 
						|
 | 
						|
	/* 3. u=x, v=y, A=1, B=0, C=0,D=1 */
 | 
						|
	if ((res = pstm_init_copy(pool, &u, &x, 0)) != PSTM_OKAY) {
 | 
						|
		goto LBL_Y;
 | 
						|
	}
 | 
						|
	if ((res = pstm_init_copy(pool, &v, &y, 0)) != PSTM_OKAY) {
 | 
						|
		goto LBL_U;
 | 
						|
	}
 | 
						|
	if ((res = pstm_init(pool, &B)) != PSTM_OKAY) {
 | 
						|
		goto LBL_V;
 | 
						|
	}
 | 
						|
	if ((res = pstm_init(pool, &D)) != PSTM_OKAY) {
 | 
						|
		goto LBL_B;
 | 
						|
	}
 | 
						|
 | 
						|
	pstm_set (&D, 1);
 | 
						|
 | 
						|
	sanity = 0;
 | 
						|
top:
 | 
						|
	/* 4.  while u is even do */
 | 
						|
	while (pstm_iseven (&u) == 1) {
 | 
						|
		/* 4.1 u = u/2 */
 | 
						|
		if ((res = pstm_div_2 (&u, &u)) != PSTM_OKAY) {
 | 
						|
			goto LBL_D;
 | 
						|
		}
 | 
						|
 | 
						|
		/* 4.2 if B is odd then */
 | 
						|
		if (pstm_isodd (&B) == 1) {
 | 
						|
			if ((res = pstm_sub (&B, &x, &B)) != PSTM_OKAY) {
 | 
						|
				goto LBL_D;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		/* B = B/2 */
 | 
						|
		if ((res = pstm_div_2 (&B, &B)) !=  PSTM_OKAY) {
 | 
						|
			goto LBL_D;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* 5.  while v is even do */
 | 
						|
	while (pstm_iseven (&v) == 1) {
 | 
						|
		/* 5.1 v = v/2 */
 | 
						|
		if ((res = pstm_div_2 (&v, &v)) != PSTM_OKAY) {
 | 
						|
			goto LBL_D;
 | 
						|
		}
 | 
						|
		/* 5.2 if D is odd then */
 | 
						|
		if (pstm_isodd (&D) == 1) {
 | 
						|
			/* D = (D-x)/2 */
 | 
						|
			if ((res = pstm_sub (&D, &x, &D)) != PSTM_OKAY) {
 | 
						|
				goto LBL_D;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		/* D = D/2 */
 | 
						|
		if ((res = pstm_div_2 (&D, &D)) !=  PSTM_OKAY) {
 | 
						|
			goto LBL_D;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* 6.  if u >= v then */
 | 
						|
	if (pstm_cmp (&u, &v) != PSTM_LT) {
 | 
						|
		/* u = u - v, B = B - D */
 | 
						|
		if ((res = pstm_sub (&u, &v, &u)) != PSTM_OKAY) {
 | 
						|
				goto LBL_D;
 | 
						|
		}
 | 
						|
		if ((res = pstm_sub (&B, &D, &B)) != PSTM_OKAY) {
 | 
						|
				goto LBL_D;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		/* v - v - u, D = D - B */
 | 
						|
		if ((res = pstm_sub (&v, &u, &v)) != PSTM_OKAY) {
 | 
						|
				goto LBL_D;
 | 
						|
		}
 | 
						|
		if ((res = pstm_sub (&D, &B, &D)) != PSTM_OKAY) {
 | 
						|
				goto LBL_D;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	/* if not zero goto step 4 */
 | 
						|
	if (sanity++ > 1000) {
 | 
						|
		res = PS_LIMIT_FAIL;
 | 
						|
		goto LBL_D;
 | 
						|
	}
 | 
						|
	if (pstm_iszero (&u) == 0) {
 | 
						|
		goto top;
 | 
						|
	}
 | 
						|
 | 
						|
	/* now a = C, b = D, gcd == g*v */
 | 
						|
 | 
						|
	/* if v != 1 then there is no inverse */
 | 
						|
	if (pstm_cmp_d (&v, 1) != PSTM_EQ) {
 | 
						|
		res = PS_FAILURE;
 | 
						|
		goto LBL_D;
 | 
						|
	}
 | 
						|
 | 
						|
	/* b is now the inverse */
 | 
						|
	neg = a->sign;
 | 
						|
	while (D.sign == PSTM_NEG) {
 | 
						|
		if ((res = pstm_add (&D, b, &D)) != PSTM_OKAY) {
 | 
						|
			goto LBL_D;
 | 
						|
		}
 | 
						|
	}
 | 
						|
	if ((res = pstm_copy (&D, c)) != PSTM_OKAY) {
 | 
						|
		goto LBL_D;
 | 
						|
	}
 | 
						|
	c->sign = neg;
 | 
						|
	res = PSTM_OKAY;
 | 
						|
 | 
						|
LBL_D: pstm_clear(&D);
 | 
						|
LBL_B: pstm_clear(&B);
 | 
						|
LBL_V: pstm_clear(&v);
 | 
						|
LBL_U: pstm_clear(&u);
 | 
						|
LBL_Y: pstm_clear(&y);
 | 
						|
LBL_X: pstm_clear(&x);
 | 
						|
	return res;
 | 
						|
}
 | 
						|
#endif /* !DISABLE_PSTM */
 | 
						|
/******************************************************************************/
 |