kerneltest/e32utils/nistsecurerng/src/genutils.cpp
author Mike Kinghan <mikek@symbian.org>
Tue, 16 Nov 2010 14:39:21 +0000
branchGCC_SURGE
changeset 303 9b85206a602c
parent 152 657f875b013e
permissions -rw-r--r--
We need a way to pass flags to rombuilds in Raptor via extension flm interfaces, so that the CPP pass of the rom input files can be informed what toolchain we are building with and conditionally include or exclude files depending on whether the toolchain could build them.

/*
* Portions Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
* The original NIST Statistical Test Suite code is placed in public domain.
* (http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html) 
* 
* This software was developed at the National Institute of Standards and Technology by 
* employees of the Federal Government in the course of their official duties. Pursuant
* to title 17 Section 105 of the United States Code this software is not subject to 
* copyright protection and is in the public domain. The NIST Statistical Test Suite is
* an experimental system. NIST assumes no responsibility whatsoever for its use by other 
* parties, and makes no guarantees, expressed or implied, about its quality, reliability, 
* or any other characteristic. We would appreciate acknowledgment if the software is used.
*/

/*
 * file: mp.c
 *
 * DESCRIPTION
 *
 * These functions comprise a multi-precision integer arithmetic
 * and discrete function package.
 */

#include	"../include/genutils.h"

#define	MAXPLEN		384


/*****************************************
** greater - Test if x > y               *
**                                       *
** Returns TRUE (1) if x greater than y, *
** otherwise FALSE (0).                  *
**                                       *
** Parameters:                           *
**                                       *
**  x      Address of array x            *
**  y      Address of array y            *
**  l      Length both x and y in bytes  *
**                                       *
******************************************/ 
int greater(BYTE *x, BYTE *y, int l)
{
	int		i;

	for ( i=0; i<l; i++ )
		if ( x[i] != y[i] )
			break;

	if ( i == l )
		return 0;

	if ( x[i] > y[i] )
		return 1;

	return 0;
}


/*****************************************
** less - Test if x < y                  *
**                                       *
** Returns TRUE (1) if x less than y,    *
** otherwise FALSE (0).                  *
**                                       *
** Parameters:                           *
**                                       *
**  x      Address of array x            *
**  y      Address of array y            *
**  l      Length both x and y in bytes  *
**                                       *
******************************************/ 
int less(BYTE *x, BYTE *y, int l)
{
	int		i;

	for ( i=0; i<l; i++ )
		if ( x[i] != y[i] )
			break;

	if ( i == l ) {
		return 0;
	}

	if ( x[i] < y[i] ) {
		return 1;
	}

	return 0;
}


/*****************************************
** bshl - shifts array left              *
**                  by one bit.          *
**                                       *	
** x = x * 2                             *
**                                       *
** Parameters:                           *	
**                                       *
**  x      Address of array x            *
**  l      Length array x in bytes       *
**                                       *
******************************************/ 
BYTE bshl(BYTE *x, int l)
{
	BYTE	*p;
	int		c1, c2;

	p = x + l - 1;
	c1 = 0;
	c2 = 0;
	while ( p != x ) {
		if ( *p & 0x80 )
			c2 = 1;
		*p <<= 1;  /* shift the word left once (ls bit = 0) */
		if ( c1 )
			*p |= 1;
		c1 = c2;
		c2 = 0;
		p--;
	}

	if ( *p & 0x80 )
		c2 = 1;
	*p <<= 1;  /* shift the word left once (ls bit = 0) */
	if ( c1 )
		*p |= (DIGIT)1;

	return (BYTE)c2;
}


/*****************************************
** bshr - shifts array right             *
**                   by one bit.         *
**                                       *	
** x = x / 2                             *
**                                       *
** Parameters:                           *	
**                                       *
**  x      Address of array x            *
**  l      Length array x in bytes       *	
**                                       *
******************************************/
void bshr(BYTE *x, int l)	
{
	BYTE	*p;
	int		c1,c2;

	p = x;
	c1 = 0;
	c2 = 0;
	while ( p != x+l-1 ) {
		if ( *p & 0x01 )
			c2 = 1;
		*p >>= 1;  /* shift the word right once (ms bit = 0) */
		if ( c1 )
			*p |= 0x80;
		c1 = c2;
		c2 = 0;
		p++;
	}

	*p >>= 1;  /* shift the word right once (ms bit = 0) */
	if ( c1 )
		*p |= 0x80;
}


/*****************************************
** Mult - Multiply two integers          *
**                                       *
** A = B * C                             *
**                                       *
** Parameters:                           *	
**                                       *
**  A      Address of the result         *
**  B      Address of the multiplier     *
**  C      Address of the multiplicand   *
**  LB      Length of B in bytes         *
**  LC      Length of C in bytes         *
**                                       *
**  NOTE:  A MUST be LB+LC in length     *
**                                       *
******************************************/
int Mult(BYTE *A, BYTE *B, int LB, BYTE *C, int LC)
{
	int    i, j;
	int    k = 0;
	DIGIT	result;


	for ( i=LB-1; i>=0; i-- ) {
		result = 0;
		for ( j=LC-1; j>=0; j-- ) {
			k = i+j+1;
			result = (DIGIT)((DIGIT)A[k] + ((DIGIT)(B[i] * C[j])) + (result >> 8));
			A[k] = (BYTE)result;
			}
		A[--k] = (BYTE)(result >> 8);
	}

	return 0;
}


void ModSqr(BYTE *A, BYTE *B, int LB, BYTE *M, int LM)
{

	Square(A, B, LB);
	Mod(A, 2*LB, M, LM);
}

void ModMult(BYTE *A, BYTE *B, int LB, BYTE *C, int LC, BYTE *M, int LM)
{
	Mult(A, B, LB, C, LC);
	Mod(A, (LB+LC), M, LM);
}


/*****************************************
** smult - Multiply array by a scalar.   *
**                                       *
** A = b * C                             *
**                                       *
** Parameters:                           *	
**                                       *
**  A      Address of the result         *
**  b      Scalar (1 BYTE)               *
**  C      Address of the multiplicand   *
**  L      Length of C in bytes          *
**                                       *
**  NOTE:  A MUST be L+1 in length       *
**                                       *
******************************************/
void smult(BYTE *A, BYTE b, BYTE *C, int L)
{
	int		i;
	DIGIT	result;

	result = 0;
	for ( i=L-1; i>0; i-- ) {
		result = (DIGIT)(A[i] + ((DIGIT)b * C[i]) + (result >> 8));
		A[i] = (BYTE)(result & 0xff);
		A[i-1] = (BYTE)(result >> 8);
	}
}

/*****************************************
** Square() - Square an integer          *
**                                       *
** A = B^2                               *
**                                       *
** Parameters:                           *
**                                       *
**  A      Address of the result         *
**  B      Address of the operand        *
**  L      Length of B in bytes          *
**                                       *
**  NOTE:  A MUST be 2*L in length       *
**                                       *
******************************************/
void Square(BYTE *A, BYTE *B, int L)
{
	Mult(A, B, L, B, L);
}

/*****************************************
** ModExp - Modular Exponentiation       *
**                                       *
** A = B ** C (MOD M)                    *
**                                       *	
** Parameters:                           *	
**                                       *
**  A      Address of result             *
**  B      Address of mantissa           *
**  C      Address of exponent           *
**  M      Address of modulus            *
**  LB     Length of B in bytes          *
**  LC     Length of C in bytes          *
**  LM     Length of M in bytes          *
**                                       *
**  NOTE: The integer B must be less     *
**        than the modulus M.      	 *
**  NOTE: A must be at least 3*LM        *
**        bytes long.  However, the      *
**        result stored in A will be     *
**        only LM bytes long.            *
******************************************/
void ModExp(BYTE *A, BYTE *B, int LB, BYTE *C, int LC, BYTE *M, int LM)
{
	BYTE	wmask;
	int		bits;

	bits = LC*8;
	wmask = 0x80;

	A[LM-1] = 1;

	while ( !sniff_bit(C,wmask) ) {
		wmask >>= 1;
		bits--;
		if ( !wmask ) {
			wmask = 0x80;
			C++;
		}
	}

	while ( bits-- ) {
		memset(A+LM, 0x00, LM*2);

		/* temp = A*A (MOD M) */
		ModSqr(A+LM, A,LM,  M,LM);

		/* A = lower L bytes of temp */
		memcpy(A, A+LM*2, LM);
		memset(A+LM, 0x00, 2*LM);

		if ( sniff_bit(C,wmask) ) {
			memset(A+LM, 0x00, (LM+LB));
			ModMult(A+LM, B,LB, A,LM,  M,LM);       /* temp = B * A (MOD M) */
			memcpy(A, A+LM+(LM+LB)-LM, LM);  /* A = lower LM bytes of temp */
			memset(A+LM, 0x00, 2*LM);
		}
 
		wmask >>= 1;
		if ( !wmask ) {
			wmask = 0x80;
			C++;
		}
	}
}


/* DivMod:
 *
 *   computes:
 *         quot = x / n
 *         rem = x % n
 *   returns:
 *         length of "quot"
 *
 *  len of rem is lenx+1
 */
int DivMod(BYTE *x, int lenx, BYTE *n, int lenn, BYTE *quot, BYTE *rem)
{
	BYTE	*tx, *tn, *ttx, *ts, bmult[1];
	int		i, shift, lgth_x, lgth_n, t_len, lenq;
	DIGIT	tMSn, mult;
	ULONG	tMSx;
	int		underflow;

	tx = x;
	tn = n;
	
	/* point to the MSD of n  */
	for ( i=0, lgth_n=lenn; i<lenn; i++, lgth_n-- ) {
		if ( *tn )
			break;
		tn++;
	}
	if ( !lgth_n )
		return 0;
	
	/* point to the MSD of x  */
	for ( i=0, lgth_x=lenx; i<lenx; i++, lgth_x-- ) {
		if ( *tx )
			break;
		tx++;
	}
	if ( !lgth_x )
		return 0;

	if ( lgth_x < lgth_n )
		lenq = 1;
	else
		lenq = lgth_x - lgth_n + 1;
	memset(quot, 0x00, lenq);
	
	/* Loop while x > n,  WATCH OUT if lgth_x == lgth_n */
	while ( (lgth_x > lgth_n) || ((lgth_x == lgth_n) && !less(tx, tn, lgth_n)) ) {
		shift = 1;
		if ( lgth_n == 1 ) {
			if ( *tx < *tn ) {
				tMSx = (DIGIT) (((*tx) << 8) | *(tx+1));
				tMSn = *tn;
				shift = 0;
			}
			else {
				tMSx = *tx;
				tMSn = *tn;
			}
		}
		else if ( lgth_n > 1 ) {
			tMSx = (DIGIT) (((*tx) << 8) | *(tx+1));
			tMSn = (DIGIT) (((*tn) << 8) | *(tn+1));
			if ( (tMSx < tMSn) || ((tMSx == tMSn) && less(tx, tn, lgth_n)) ) {
				tMSx = (tMSx << 8) | *(tx+2);
				shift = 0;
			}
		}
		else {
			tMSx = (DIGIT) (((*tx) << 8) | *(tx+1));
			tMSn = *tn;
			shift = 0;
		}

		mult = (DIGIT) (tMSx / tMSn);
		if ( mult > 0xff )
			mult = 0xff;
		bmult[0] = (BYTE)(mult & 0xff);

		ts = rem;
		do {
			memset(ts, 0x00, lgth_x+1);
			Mult(ts, tn, lgth_n, bmult, 1);

			underflow = 0;
			if ( shift ) {
				if ( ts[0] != 0 )
					underflow = 1;
				else {
					for ( i=0; i<lgth_x; i++ )
						ts[i] = ts[i+1];
					ts[lgth_x] = 0x00;
				}
			}
			if ( greater(ts, tx, lgth_x) || underflow ) {
				bmult[0]--;
				underflow = 1;
			}
			else
				underflow = 0;
		} while ( underflow );
		sub(tx, lgth_x, ts, lgth_x);
		if ( shift )
			quot[lenq - (lgth_x - lgth_n) - 1] = bmult[0];
		else
			quot[lenq - (lgth_x - lgth_n)] = bmult[0];
		
		ttx = tx;
		t_len = lgth_x;
		for ( i=0, lgth_x=t_len; i<t_len; i++, lgth_x-- ) {
			if ( *ttx )
				break;
			ttx++;
		}
		tx = ttx;
	}
	memset(rem, 0x00, lenn);
	if ( lgth_x )
		memcpy(rem+lenn-lgth_x, tx, lgth_x);

	return lenq;
}


/* 
 * Mod - Computes an integer modulo another integer
 *
 * x = x (mod n)
 *
 */
void Mod(BYTE *x, int lenx, BYTE *n, int lenn)
{
	BYTE	quot[MAXPLEN+1], rem[2*MAXPLEN+1];

	memset(quot, 0x00, sizeof(quot));
	memset(rem, 0x00, sizeof(rem));
	if ( DivMod(x, lenx, n, lenn, quot, rem) ) {
		memset(x, 0x00, lenx);
		memcpy(x+lenx-lenn, rem, lenn);
	}
}

/* 
 * Div - Computes the integer division of two numbers
 *
 * x = x / n
 *
 */
void Div(BYTE *x, int lenx, BYTE *n, int lenn)
{
	BYTE	quot[MAXPLEN+1], rem[2*MAXPLEN+1];
	int		lenq;

	memset(quot, 0x00, sizeof(quot));
	memset(rem, 0x00, sizeof(rem));
	if ( (lenq = DivMod(x, lenx, n, lenn, quot, rem)) != 0 ) {
		memset(x, 0x00, lenx);
		memcpy(x+lenx-lenq, quot, lenq);
	}
}


/*****************************************
** sub - Subtract two integers           *
**                                       *
** A = A - B                             *
**                                       *
**                                       *
** Parameters:                           *	
**                                       *
**  A      Address of subtrahend integer *
**  B      Address of subtractor integer *
**  L      Length of A and B in bytes    *
**                                       *
**  NOTE: In order to save RAM, B is     *
**        two's complemented twice,      *
**        rather than using a copy of B  *
**                                       *
******************************************/
void sub(BYTE *A, int LA, BYTE *B, int LB)
{
	BYTE	*tb;

	tb = (BYTE *)calloc(LA, 1);
	memcpy(tb, B, LB);
	negate(tb, LB);
	add(A, LA, tb, LA);

	FREE(tb);
}


/*****************************************
** negate - Negate an integer            *
**                                       *
** A = -A                                *
**                                       *
**                                       *
** Parameters:                           *	
**                                       *
**  A      Address of integer to negate  *
**  L      Length of A in bytes          *
**                                       *
******************************************/
int negate(BYTE *A, int L)
{
	int		i, tL;
	DIGIT	accum;

	/* Take one's complement of A */
	for ( i=0; i<L; i++ )
		A[i] = (BYTE)(~(A[i]));

	/* Add one to get two's complement of A */
	accum = 1;
	tL = L-1;
	while ( accum && (tL >= 0) ) {
		accum = (DIGIT)(accum + A[tL]);
		A[tL--] = (BYTE)(accum & 0xff);
		accum = (DIGIT)(accum >> 8);
	}

	return accum;
}


/*
 * add()
 *
 * A = A + B
 *
 * LB must be <= LA
 *
 */
BYTE add(BYTE *A, int LA, BYTE *B, int LB)
{
	int		i, indexA, indexB;
	DIGIT	accum;

	indexA = LA - 1; 	/* LSD of result */
	indexB = LB - 1; 	/* LSD of B */

	accum = 0;
	for ( i = 0; i < LB; i++ ) {
		accum = (DIGIT)(accum + A[indexA]);
		accum = (DIGIT)(accum + B[indexB--]);
		A[indexA--] = (BYTE)(accum & 0xff);
		accum = (DIGIT)(accum >> 8);
	}

	if ( LA > LB )
		while ( accum  && (indexA >= 0) ) {
			accum = (DIGIT)(accum + A[indexA]);
			A[indexA--] = (BYTE)(accum & 0xff);
			accum = (DIGIT)(accum >> 8);
		}

	return (BYTE)accum;
}


void prettyprintBstr(char *S, BYTE *A, int L)
{
	int		i, extra, ctrb, ctrl;

	if ( L == 0 )
		printf("%s <empty>", S);
	else
		printf("%s\n\t", S);
	extra = L % 24;
	if ( extra ) {
		ctrb = 0;
		for ( i=0; i<24-extra; i++ ) {
			printf("  ");
			if ( ++ctrb == 4) {
				printf(" ");
				ctrb = 0;
			}
		}

		for ( i=0; i<extra; i++ ) {
			printf("%02X", A[i]);
			if ( ++ctrb == 4) {
				printf(" ");
				ctrb = 0;
			}
		}
		printf("\n\t");
	}

	ctrb = ctrl = 0;
	for ( i=extra; i<L; i++ ) {
		printf("%02X", A[i]);
		if ( ++ctrb == 4) {
			ctrl++;
			if ( ctrl == 6 ) {
				printf("\n\t");
				ctrl = 0;
			}
			else
				printf(" ");
			ctrb = 0;
		}
	}
	printf("\n\n");
}


/**********************************************************************/
/*  Performs byte reverse for PC based implementation (little endian) */
/**********************************************************************/
void byteReverse(ULONG *buffer, int byteCount)
{
	ULONG value;
	int count;

	byteCount /= sizeof( ULONG );
	for( count = 0; count < byteCount; count++ ) {
		value = ( buffer[ count ] << 16 ) | ( buffer[ count ] >> 16 );
		buffer[ count ] = ( ( value & 0xFF00FF00L ) >> 8 ) | ( ( value & 0x00FF00FFL ) << 8 );
	}
}

void
ahtopb (char *ascii_hex, BYTE *p_binary, int bin_len)
{
	BYTE    nibble;
	int     i; 
	
	for ( i=0; i<bin_len; i++ ) {
        nibble = ascii_hex[i * 2];
	    if ( nibble > 'F' )
	        nibble -= 0x20;   
	    if ( nibble > '9' )
	        nibble -= 7;      
	    nibble -= '0';   
	    p_binary[i] = (BYTE)(nibble << 4);
		
	    nibble = ascii_hex[i * 2 + 1];
	    if ( nibble > 'F' )
			nibble -= 0x20;
        if ( nibble > '9' )
            nibble -= 7;   
        nibble -= '0';
		p_binary[i] = (BYTE)(p_binary[i] + nibble);
	}
}