/* * 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 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>= 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, k, LA; DIGIT result; LA = LB + LC; for ( i=LB-1; i>=0; i-- ) { result = 0; for ( j=LC-1; j>=0; j-- ) { k = i+j+1; result = (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 = 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; unsigned long tMSx; int underflow; tx = x; tn = n; /* point to the MSD of n */ for ( i=0, lgth_n=lenn; i 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] = 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= 0) ) { accum += A[tL]; A[tL--] = (BYTE)(accum & 0xff); accum = 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 += A[indexA]; accum += B[indexB--]; A[indexA--] = (BYTE)(accum & 0xff); accum = accum >> 8; } if ( LA > LB ) while ( accum && (indexA >= 0) ) { accum += A[indexA]; A[indexA--] = (BYTE)(accum & 0xff); accum = accum >> 8; } return (BYTE)accum; } void prettyprintBstr(char *S, BYTE *A, int L) { int i, extra, ctrb, ctrl; if ( L == 0 ) printf("%s ", 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> 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 'F' ) nibble -= 0x20; if ( nibble > '9' ) nibble -= 7; nibble -= '0'; p_binary[i] = nibble << 4; nibble = ascii_hex[i * 2 + 1]; if ( nibble > 'F' ) nibble -= 0x20; if ( nibble > '9' ) nibble -= 7; nibble -= '0'; p_binary[i] += nibble; } }