Files
Linux_Drivers/fsbl/lib/BigDigits/spExtras.c
forum_service 88cce7a8a2 fsbl: weekly update 2023-03-25
1. update release func

Change-Id: I221476630ce4f2f6a01e8f89fd96d9ac9701a270
2023-03-27 00:22:46 +08:00

304 lines
5.8 KiB
C

/* spExtras.c */
/***** BEGIN LICENSE BLOCK *****
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*
* Copyright (c) 2001-15 David Ireland, D.I. Management Services Pty Limited
* <http://www.di-mgt.com.au/bigdigits.html>. All rights reserved.
*
***** END LICENSE BLOCK *****/
/*
* Last updated:
* $Date: 2015-10-22 10:23:00 $
* $Revision: 2.5.0 $
* $Author: dai $
*/
#include <assert.h>
#include "bigdigits.h"
#include "spExtras.h"
int spModMult(DIGIT_T *a, DIGIT_T x, DIGIT_T y, DIGIT_T m)
{ /* Computes a = (x * y) mod m */
/* Calc p[2] = x * y */
DIGIT_T p[2];
spMultiply(p, x, y);
/* Then modulo */
*a = mpShortMod(p, m, 2);
return 0;
}
DIGIT_T spGcd_old(DIGIT_T x, DIGIT_T y)
{ /* Returns gcd(x, y) */
/* Ref: Schneier 2nd ed, p245 */
DIGIT_T g;
if (x + y == 0)
return 0; /* Error */
g = y;
while (x > 0)
{
g = x;
x = y % x;
y = g;
}
return g;
}
DIGIT_T spGcd(DIGIT_T a, DIGIT_T b)
{ /* Returns gcd(a, b) */
/* Ref: Cohen, Algorithm 1.3.5 (Binary GCD)
and Menezes, Algorithm 14.54 */
DIGIT_T r, t;
unsigned int k;
/* 1. [Reduce size once] */
if (a < b)
{ /* exchange a and b */
t = a;
a = b;
b = t;
}
if (0 == b)
{
return a;
}
r = a % b;
a = b;
b = r;
if (0 == b)
{
return a;
}
/* 2. [Compute power of 2] */
k = 0;
while (ISEVEN(a) && ISEVEN(b))
{
a >>= 1; /* a <-- a/2 */
b >>= 1; /* b <-- b/2 */
k++; /* g <-- 2g */
}
while (a != 0)
{
while (ISEVEN(a))
{
a >>= 1; /* a <-- a/2 until a is odd */
}
while (ISEVEN(b))
{
b >>= 1; /* b <-- a/2 until b is odd */
}
/* t <-- |a-b|/2 */
if (b > a)
t = (b - a) >> 1;
else
t = (a - b) >> 1;
/* If a >= b then a = t, otherwise b = t */
if (a >= b)
a = t;
else
b = t;
}
/* Output (2^k.b) */
return (b << k);
}
/* spIsPrime */
static DIGIT_T SMALL_PRIMES[] = { 2, 3, 5, 7, 11, 13, 17, 19 };
#define N_SMALL_PRIMES sizeof(SMALL_PRIMES)/sizeof(DIGIT_T)
int spIsPrime(DIGIT_T w, size_t t)
{ /* Returns true if w is a probable prime
Carries out t iterations
(Use t = 50 for DSS Standard)
*/
/* Uses Rabin-Miller Probabilistic Primality Test,
Ref: FIPS-186-2 Appendix 2.
Also Schneier 2nd ed p 260 & Knuth Vol 2, p 379
and ANSI 9.42-2003 Annex B.1.1.
*/
unsigned int i, j;
DIGIT_T m, a, b, z;
int failed;
/* First check for small primes */
for (i = 0; i < N_SMALL_PRIMES; i++)
{
if (w % SMALL_PRIMES[i] == 0)
return 0; /* Failed */
}
/* Now do Rabin-Miller */
/* Step 2. Find a and m where w = 1 + (2^a)m
m is odd and 2^a is largest power of 2 dividing w - 1 */
m = w - 1;
for (a = 0; ISEVEN(m); a++)
m >>= 1; /* Divide by 2 until m is odd */
/*
assert((1 << a) * m + 1 == w);
*/
for (i = 0; i < t; i++)
{
failed = 1; /* Assume fail unless passed in loop */
/* Step 3. Generate a random integer 1 < b < w */
/* [v2.1] changed to 1 < b < w-1 */
b = spSimpleRand(2, w - 2);
/*
assert(1 < b && b < w-1);
*/
/* Step 4. Set j = 0 and z = b^m mod w */
j = 0;
spModExp(&z, b, m, w);
do
{
/* Step 5. If j = 0 and z = 1, or if z = w - 1 */
if ((j == 0 && z == 1) || (z == w - 1))
{ /* Passes on this loop - go to Step 9 */
failed = 0;
break;
}
/* Step 6. If j > 0 and z = 1 */
if (j > 0 && z == 1)
{ /* Fails - go to Step 8 */
failed = 1;
break;
}
/* Step 7. j = j + 1. If j < a set z = z^2 mod w */
j++;
if (j < a)
spModMult(&z, z, z, w);
/* Loop: if j < a go to Step 5 */
} while (j < a);
if (failed)
{ /* Step 8. Not a prime - stop */
return 0;
}
} /* Step 9. Go to Step 3 until i >= n */
/* If got here, probably prime => success */
return 1;
}
/* spModExp */
/* Two alternative functions for spModExp */
int spModExpK(DIGIT_T *exp, DIGIT_T x,
DIGIT_T n, DIGIT_T d)
{ /* Computes exp = x^n mod d */
/* Ref: Knuth Vol 2 Ch 4.6.3 p 462 Algorithm A
*/
DIGIT_T y = 1; /* Step A1. Initialise */
while (n > 0)
{ /* Step A2. Halve N */
if (n & 0x1) /* If odd */
spModMult(&y, y, x, d); /* Step A3. Multiply Y by Z */
n >>= 1; /* Halve N */
if (n > 0) /* Step A4. N = 0? Y is answer */
spModMult(&x, x, x, d); /* Step A5. Square Z */
}
*exp = y;
return 0;
}
int spModExpB(DIGIT_T *exp, DIGIT_T x,
DIGIT_T e, DIGIT_T m)
{ /* Computes exp = x^e mod m */
/* Binary left-to-right method
*/
DIGIT_T mask;
DIGIT_T y; /* Temp variable */
/* Find most significant bit in e */
for (mask = HIBITMASK; mask > 0; mask >>= 1)
{
if (e & mask)
break;
}
y = x;
/* For j = k-2 downto 0 step -1 */
for (mask >>= 1; mask > 0; mask >>= 1)
{
spModMult(&y, y, y, m); /* Square */
if (e & mask)
spModMult(&y, y, x, m); /* Multiply */
}
*exp = y;
return 0;
}
int spModInv(DIGIT_T *inv, DIGIT_T u, DIGIT_T v)
{ /* Computes inv = u^(-1) mod v */
/* Ref: Knuth Algorithm X Vol 2 p 342
ignoring u2, v2, t2
and avoiding negative numbers
*/
DIGIT_T u1, u3, v1, v3, t1, t3, q, w;
int bIterations = 1;
int result;
/* Step X1. Initialise */
u1 = 1;
u3 = u;
v1 = 0;
v3 = v;
while (v3 != 0) /* Step X2. */
{ /* Step X3. */
q = u3 / v3; /* Divide and */
t3 = u3 % v3;
w = q * v1; /* "Subtract" */
t1 = u1 + w;
/* Swap */
u1 = v1;
v1 = t1;
u3 = v3;
v3 = t3;
bIterations = -bIterations;
}
if (bIterations < 0)
*inv = v - u1;
else
*inv = u1;
/* Make sure u3 = gcd(u,v) == 1 */
if (u3 != 1)
{
result = 1;
*inv = 0;
}
else
result = 0;
return result;
}