original files of m241
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,313 @@
|
||||
/* crypto/bn/bn_add.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
/* r can == a or b */
|
||||
int BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
const BIGNUM *tmp;
|
||||
int a_neg = a->neg, ret;
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
|
||||
/*-
|
||||
* a + b a+b
|
||||
* a + -b a-b
|
||||
* -a + b b-a
|
||||
* -a + -b -(a+b)
|
||||
*/
|
||||
if (a_neg ^ b->neg) {
|
||||
/* only one is negative */
|
||||
if (a_neg) {
|
||||
tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
|
||||
/* we are now a - b */
|
||||
|
||||
if (BN_ucmp(a, b) < 0) {
|
||||
if (!BN_usub(r, b, a))
|
||||
return (0);
|
||||
r->neg = 1;
|
||||
} else {
|
||||
if (!BN_usub(r, a, b))
|
||||
return (0);
|
||||
r->neg = 0;
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
|
||||
ret = BN_uadd(r, a, b);
|
||||
r->neg = a_neg;
|
||||
bn_check_top(r);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* unsigned add of b to a */
|
||||
int BN_uadd(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
int max, min, dif;
|
||||
BN_ULONG *ap, *bp, *rp, carry, t1, t2;
|
||||
const BIGNUM *tmp;
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
|
||||
if (a->top < b->top) {
|
||||
tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
}
|
||||
max = a->top;
|
||||
min = b->top;
|
||||
dif = max - min;
|
||||
|
||||
if (bn_wexpand(r, max + 1) == NULL)
|
||||
return 0;
|
||||
|
||||
r->top = max;
|
||||
|
||||
ap = a->d;
|
||||
bp = b->d;
|
||||
rp = r->d;
|
||||
|
||||
carry = bn_add_words(rp, ap, bp, min);
|
||||
rp += min;
|
||||
ap += min;
|
||||
bp += min;
|
||||
|
||||
if (carry) {
|
||||
while (dif) {
|
||||
dif--;
|
||||
t1 = *(ap++);
|
||||
t2 = (t1 + 1) & BN_MASK2;
|
||||
*(rp++) = t2;
|
||||
if (t2) {
|
||||
carry = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (carry) {
|
||||
/* carry != 0 => dif == 0 */
|
||||
*rp = 1;
|
||||
r->top++;
|
||||
}
|
||||
}
|
||||
if (dif && rp != ap)
|
||||
while (dif--)
|
||||
/* copy remaining words if ap != rp */
|
||||
*(rp++) = *(ap++);
|
||||
r->neg = 0;
|
||||
bn_check_top(r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* unsigned subtraction of b from a, a must be larger than b. */
|
||||
int BN_usub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
int max, min, dif;
|
||||
register BN_ULONG t1, t2, *ap, *bp, *rp;
|
||||
int i, carry;
|
||||
#if defined(IRIX_CC_BUG) && !defined(LINT)
|
||||
int dummy;
|
||||
#endif
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
|
||||
max = a->top;
|
||||
min = b->top;
|
||||
dif = max - min;
|
||||
|
||||
if (dif < 0) { /* hmm... should not be happening */
|
||||
BNerr(BN_F_BN_USUB, BN_R_ARG2_LT_ARG3);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (bn_wexpand(r, max) == NULL)
|
||||
return (0);
|
||||
|
||||
ap = a->d;
|
||||
bp = b->d;
|
||||
rp = r->d;
|
||||
|
||||
#if 1
|
||||
carry = 0;
|
||||
for (i = min; i != 0; i--) {
|
||||
t1 = *(ap++);
|
||||
t2 = *(bp++);
|
||||
if (carry) {
|
||||
carry = (t1 <= t2);
|
||||
t1 = (t1 - t2 - 1) & BN_MASK2;
|
||||
} else {
|
||||
carry = (t1 < t2);
|
||||
t1 = (t1 - t2) & BN_MASK2;
|
||||
}
|
||||
# if defined(IRIX_CC_BUG) && !defined(LINT)
|
||||
dummy = t1;
|
||||
# endif
|
||||
*(rp++) = t1 & BN_MASK2;
|
||||
}
|
||||
#else
|
||||
carry = bn_sub_words(rp, ap, bp, min);
|
||||
ap += min;
|
||||
bp += min;
|
||||
rp += min;
|
||||
#endif
|
||||
if (carry) { /* subtracted */
|
||||
if (!dif)
|
||||
/* error: a < b */
|
||||
return 0;
|
||||
while (dif) {
|
||||
dif--;
|
||||
t1 = *(ap++);
|
||||
t2 = (t1 - 1) & BN_MASK2;
|
||||
*(rp++) = t2;
|
||||
if (t1)
|
||||
break;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
memcpy(rp, ap, sizeof(*rp) * (max - i));
|
||||
#else
|
||||
if (rp != ap) {
|
||||
for (;;) {
|
||||
if (!dif--)
|
||||
break;
|
||||
rp[0] = ap[0];
|
||||
if (!dif--)
|
||||
break;
|
||||
rp[1] = ap[1];
|
||||
if (!dif--)
|
||||
break;
|
||||
rp[2] = ap[2];
|
||||
if (!dif--)
|
||||
break;
|
||||
rp[3] = ap[3];
|
||||
rp += 4;
|
||||
ap += 4;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
r->top = max;
|
||||
r->neg = 0;
|
||||
bn_correct_top(r);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
int max;
|
||||
int add = 0, neg = 0;
|
||||
const BIGNUM *tmp;
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
|
||||
/*-
|
||||
* a - b a-b
|
||||
* a - -b a+b
|
||||
* -a - b -(a+b)
|
||||
* -a - -b b-a
|
||||
*/
|
||||
if (a->neg) {
|
||||
if (b->neg) {
|
||||
tmp = a;
|
||||
a = b;
|
||||
b = tmp;
|
||||
} else {
|
||||
add = 1;
|
||||
neg = 1;
|
||||
}
|
||||
} else {
|
||||
if (b->neg) {
|
||||
add = 1;
|
||||
neg = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (add) {
|
||||
if (!BN_uadd(r, a, b))
|
||||
return (0);
|
||||
r->neg = neg;
|
||||
return (1);
|
||||
}
|
||||
|
||||
/* We are actually doing a - b :-) */
|
||||
|
||||
max = (a->top > b->top) ? a->top : b->top;
|
||||
if (bn_wexpand(r, max) == NULL)
|
||||
return (0);
|
||||
if (BN_ucmp(a, b) < 0) {
|
||||
if (!BN_usub(r, b, a))
|
||||
return (0);
|
||||
r->neg = 1;
|
||||
} else {
|
||||
if (!BN_usub(r, a, b))
|
||||
return (0);
|
||||
r->neg = 0;
|
||||
}
|
||||
bn_check_top(r);
|
||||
return (1);
|
||||
}
|
||||
@@ -0,0 +1,920 @@
|
||||
/* crypto/bn/bn_asm.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#ifndef BN_DEBUG
|
||||
# undef NDEBUG /* avoid conflicting definitions */
|
||||
# define NDEBUG
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
#if defined(BN_LLONG) || defined(BN_UMULT_HIGH)
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
|
||||
BN_ULONG w)
|
||||
{
|
||||
BN_ULONG c1 = 0;
|
||||
|
||||
assert(num >= 0);
|
||||
if (num <= 0)
|
||||
return (c1);
|
||||
|
||||
while (num & ~3) {
|
||||
mul_add(rp[0], ap[0], w, c1);
|
||||
mul_add(rp[1], ap[1], w, c1);
|
||||
mul_add(rp[2], ap[2], w, c1);
|
||||
mul_add(rp[3], ap[3], w, c1);
|
||||
ap += 4;
|
||||
rp += 4;
|
||||
num -= 4;
|
||||
}
|
||||
if (num) {
|
||||
mul_add(rp[0], ap[0], w, c1);
|
||||
if (--num == 0)
|
||||
return c1;
|
||||
mul_add(rp[1], ap[1], w, c1);
|
||||
if (--num == 0)
|
||||
return c1;
|
||||
mul_add(rp[2], ap[2], w, c1);
|
||||
return c1;
|
||||
}
|
||||
|
||||
return (c1);
|
||||
}
|
||||
|
||||
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
|
||||
{
|
||||
BN_ULONG c1 = 0;
|
||||
|
||||
assert(num >= 0);
|
||||
if (num <= 0)
|
||||
return (c1);
|
||||
|
||||
while (num & ~3) {
|
||||
mul(rp[0], ap[0], w, c1);
|
||||
mul(rp[1], ap[1], w, c1);
|
||||
mul(rp[2], ap[2], w, c1);
|
||||
mul(rp[3], ap[3], w, c1);
|
||||
ap += 4;
|
||||
rp += 4;
|
||||
num -= 4;
|
||||
}
|
||||
if (num) {
|
||||
mul(rp[0], ap[0], w, c1);
|
||||
if (--num == 0)
|
||||
return c1;
|
||||
mul(rp[1], ap[1], w, c1);
|
||||
if (--num == 0)
|
||||
return c1;
|
||||
mul(rp[2], ap[2], w, c1);
|
||||
}
|
||||
return (c1);
|
||||
}
|
||||
|
||||
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
|
||||
{
|
||||
assert(n >= 0);
|
||||
if (n <= 0)
|
||||
return;
|
||||
while (n & ~3) {
|
||||
sqr(r[0], r[1], a[0]);
|
||||
sqr(r[2], r[3], a[1]);
|
||||
sqr(r[4], r[5], a[2]);
|
||||
sqr(r[6], r[7], a[3]);
|
||||
a += 4;
|
||||
r += 8;
|
||||
n -= 4;
|
||||
}
|
||||
if (n) {
|
||||
sqr(r[0], r[1], a[0]);
|
||||
if (--n == 0)
|
||||
return;
|
||||
sqr(r[2], r[3], a[1]);
|
||||
if (--n == 0)
|
||||
return;
|
||||
sqr(r[4], r[5], a[2]);
|
||||
}
|
||||
}
|
||||
|
||||
#else /* !(defined(BN_LLONG) ||
|
||||
* defined(BN_UMULT_HIGH)) */
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
|
||||
BN_ULONG w)
|
||||
{
|
||||
BN_ULONG c = 0;
|
||||
BN_ULONG bl, bh;
|
||||
|
||||
assert(num >= 0);
|
||||
if (num <= 0)
|
||||
return ((BN_ULONG)0);
|
||||
|
||||
bl = LBITS(w);
|
||||
bh = HBITS(w);
|
||||
|
||||
for (;;) {
|
||||
mul_add(rp[0], ap[0], bl, bh, c);
|
||||
if (--num == 0)
|
||||
break;
|
||||
mul_add(rp[1], ap[1], bl, bh, c);
|
||||
if (--num == 0)
|
||||
break;
|
||||
mul_add(rp[2], ap[2], bl, bh, c);
|
||||
if (--num == 0)
|
||||
break;
|
||||
mul_add(rp[3], ap[3], bl, bh, c);
|
||||
if (--num == 0)
|
||||
break;
|
||||
ap += 4;
|
||||
rp += 4;
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
|
||||
BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
|
||||
{
|
||||
BN_ULONG carry = 0;
|
||||
BN_ULONG bl, bh;
|
||||
|
||||
assert(num >= 0);
|
||||
if (num <= 0)
|
||||
return ((BN_ULONG)0);
|
||||
|
||||
bl = LBITS(w);
|
||||
bh = HBITS(w);
|
||||
|
||||
for (;;) {
|
||||
mul(rp[0], ap[0], bl, bh, carry);
|
||||
if (--num == 0)
|
||||
break;
|
||||
mul(rp[1], ap[1], bl, bh, carry);
|
||||
if (--num == 0)
|
||||
break;
|
||||
mul(rp[2], ap[2], bl, bh, carry);
|
||||
if (--num == 0)
|
||||
break;
|
||||
mul(rp[3], ap[3], bl, bh, carry);
|
||||
if (--num == 0)
|
||||
break;
|
||||
ap += 4;
|
||||
rp += 4;
|
||||
}
|
||||
return (carry);
|
||||
}
|
||||
|
||||
void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
|
||||
{
|
||||
assert(n >= 0);
|
||||
if (n <= 0)
|
||||
return;
|
||||
for (;;) {
|
||||
sqr64(r[0], r[1], a[0]);
|
||||
if (--n == 0)
|
||||
break;
|
||||
|
||||
sqr64(r[2], r[3], a[1]);
|
||||
if (--n == 0)
|
||||
break;
|
||||
|
||||
sqr64(r[4], r[5], a[2]);
|
||||
if (--n == 0)
|
||||
break;
|
||||
|
||||
sqr64(r[6], r[7], a[3]);
|
||||
if (--n == 0)
|
||||
break;
|
||||
|
||||
a += 4;
|
||||
r += 8;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !(defined(BN_LLONG) ||
|
||||
* defined(BN_UMULT_HIGH)) */
|
||||
|
||||
#if defined(BN_LLONG) && defined(BN_DIV2W)
|
||||
|
||||
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
|
||||
{
|
||||
return ((BN_ULONG)(((((BN_ULLONG) h) << BN_BITS2) | l) / (BN_ULLONG) d));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Divide h,l by d and return the result. */
|
||||
/* I need to test this some more :-( */
|
||||
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
|
||||
{
|
||||
BN_ULONG dh, dl, q, ret = 0, th, tl, t;
|
||||
int i, count = 2;
|
||||
|
||||
if (d == 0)
|
||||
return (BN_MASK2);
|
||||
|
||||
i = BN_num_bits_word(d);
|
||||
assert((i == BN_BITS2) || (h <= (BN_ULONG)1 << i));
|
||||
|
||||
i = BN_BITS2 - i;
|
||||
if (h >= d)
|
||||
h -= d;
|
||||
|
||||
if (i) {
|
||||
d <<= i;
|
||||
h = (h << i) | (l >> (BN_BITS2 - i));
|
||||
l <<= i;
|
||||
}
|
||||
dh = (d & BN_MASK2h) >> BN_BITS4;
|
||||
dl = (d & BN_MASK2l);
|
||||
for (;;) {
|
||||
if ((h >> BN_BITS4) == dh)
|
||||
q = BN_MASK2l;
|
||||
else
|
||||
q = h / dh;
|
||||
|
||||
th = q * dh;
|
||||
tl = dl * q;
|
||||
for (;;) {
|
||||
t = h - th;
|
||||
if ((t & BN_MASK2h) ||
|
||||
((tl) <= ((t << BN_BITS4) | ((l & BN_MASK2h) >> BN_BITS4))))
|
||||
break;
|
||||
q--;
|
||||
th -= dh;
|
||||
tl -= dl;
|
||||
}
|
||||
t = (tl >> BN_BITS4);
|
||||
tl = (tl << BN_BITS4) & BN_MASK2h;
|
||||
th += t;
|
||||
|
||||
if (l < tl)
|
||||
th++;
|
||||
l -= tl;
|
||||
if (h < th) {
|
||||
h += d;
|
||||
q--;
|
||||
}
|
||||
h -= th;
|
||||
|
||||
if (--count == 0)
|
||||
break;
|
||||
|
||||
ret = q << BN_BITS4;
|
||||
h = ((h << BN_BITS4) | (l >> BN_BITS4)) & BN_MASK2;
|
||||
l = (l & BN_MASK2l) << BN_BITS4;
|
||||
}
|
||||
ret |= q;
|
||||
return (ret);
|
||||
}
|
||||
#endif /* !defined(BN_LLONG) && defined(BN_DIV2W) */
|
||||
|
||||
#ifdef BN_LLONG
|
||||
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int n)
|
||||
{
|
||||
BN_ULLONG ll = 0;
|
||||
|
||||
assert(n >= 0);
|
||||
if (n <= 0)
|
||||
return ((BN_ULONG)0);
|
||||
|
||||
for (;;) {
|
||||
ll += (BN_ULLONG) a[0] + b[0];
|
||||
r[0] = (BN_ULONG)ll & BN_MASK2;
|
||||
ll >>= BN_BITS2;
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
ll += (BN_ULLONG) a[1] + b[1];
|
||||
r[1] = (BN_ULONG)ll & BN_MASK2;
|
||||
ll >>= BN_BITS2;
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
ll += (BN_ULLONG) a[2] + b[2];
|
||||
r[2] = (BN_ULONG)ll & BN_MASK2;
|
||||
ll >>= BN_BITS2;
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
ll += (BN_ULLONG) a[3] + b[3];
|
||||
r[3] = (BN_ULONG)ll & BN_MASK2;
|
||||
ll >>= BN_BITS2;
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
a += 4;
|
||||
b += 4;
|
||||
r += 4;
|
||||
}
|
||||
return ((BN_ULONG)ll);
|
||||
}
|
||||
#else /* !BN_LLONG */
|
||||
BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int n)
|
||||
{
|
||||
BN_ULONG c, l, t;
|
||||
|
||||
assert(n >= 0);
|
||||
if (n <= 0)
|
||||
return ((BN_ULONG)0);
|
||||
|
||||
c = 0;
|
||||
for (;;) {
|
||||
t = a[0];
|
||||
t = (t + c) & BN_MASK2;
|
||||
c = (t < c);
|
||||
l = (t + b[0]) & BN_MASK2;
|
||||
c += (l < t);
|
||||
r[0] = l;
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
t = a[1];
|
||||
t = (t + c) & BN_MASK2;
|
||||
c = (t < c);
|
||||
l = (t + b[1]) & BN_MASK2;
|
||||
c += (l < t);
|
||||
r[1] = l;
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
t = a[2];
|
||||
t = (t + c) & BN_MASK2;
|
||||
c = (t < c);
|
||||
l = (t + b[2]) & BN_MASK2;
|
||||
c += (l < t);
|
||||
r[2] = l;
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
t = a[3];
|
||||
t = (t + c) & BN_MASK2;
|
||||
c = (t < c);
|
||||
l = (t + b[3]) & BN_MASK2;
|
||||
c += (l < t);
|
||||
r[3] = l;
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
a += 4;
|
||||
b += 4;
|
||||
r += 4;
|
||||
}
|
||||
return ((BN_ULONG)c);
|
||||
}
|
||||
#endif /* !BN_LLONG */
|
||||
|
||||
BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int n)
|
||||
{
|
||||
BN_ULONG t1, t2;
|
||||
int c = 0;
|
||||
|
||||
assert(n >= 0);
|
||||
if (n <= 0)
|
||||
return ((BN_ULONG)0);
|
||||
|
||||
for (;;) {
|
||||
t1 = a[0];
|
||||
t2 = b[0];
|
||||
r[0] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2)
|
||||
c = (t1 < t2);
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
t1 = a[1];
|
||||
t2 = b[1];
|
||||
r[1] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2)
|
||||
c = (t1 < t2);
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
t1 = a[2];
|
||||
t2 = b[2];
|
||||
r[2] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2)
|
||||
c = (t1 < t2);
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
t1 = a[3];
|
||||
t2 = b[3];
|
||||
r[3] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2)
|
||||
c = (t1 < t2);
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
a += 4;
|
||||
b += 4;
|
||||
r += 4;
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
|
||||
#ifdef BN_MUL_COMBA
|
||||
|
||||
# undef bn_mul_comba8
|
||||
# undef bn_mul_comba4
|
||||
# undef bn_sqr_comba8
|
||||
# undef bn_sqr_comba4
|
||||
|
||||
/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */
|
||||
/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
|
||||
/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
|
||||
/*
|
||||
* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number
|
||||
* c=(c2,c1,c0)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Keep in mind that carrying into high part of multiplication result
|
||||
* can not overflow, because it cannot be all-ones.
|
||||
*/
|
||||
# ifdef BN_LLONG
|
||||
# define mul_add_c(a,b,c0,c1,c2) \
|
||||
t=(BN_ULLONG)a*b; \
|
||||
t1=(BN_ULONG)Lw(t); \
|
||||
t2=(BN_ULONG)Hw(t); \
|
||||
c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
|
||||
c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
|
||||
|
||||
# define mul_add_c2(a,b,c0,c1,c2) \
|
||||
t=(BN_ULLONG)a*b; \
|
||||
tt=(t+t)&BN_MASK; \
|
||||
if (tt < t) c2++; \
|
||||
t1=(BN_ULONG)Lw(tt); \
|
||||
t2=(BN_ULONG)Hw(tt); \
|
||||
c0=(c0+t1)&BN_MASK2; \
|
||||
if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \
|
||||
c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
|
||||
|
||||
# define sqr_add_c(a,i,c0,c1,c2) \
|
||||
t=(BN_ULLONG)a[i]*a[i]; \
|
||||
t1=(BN_ULONG)Lw(t); \
|
||||
t2=(BN_ULONG)Hw(t); \
|
||||
c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
|
||||
c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
|
||||
|
||||
# define sqr_add_c2(a,i,j,c0,c1,c2) \
|
||||
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
|
||||
|
||||
# elif defined(BN_UMULT_LOHI)
|
||||
|
||||
# define mul_add_c(a,b,c0,c1,c2) { \
|
||||
BN_ULONG ta=(a),tb=(b); \
|
||||
BN_UMULT_LOHI(t1,t2,ta,tb); \
|
||||
c0 += t1; t2 += (c0<t1)?1:0; \
|
||||
c1 += t2; c2 += (c1<t2)?1:0; \
|
||||
}
|
||||
|
||||
# define mul_add_c2(a,b,c0,c1,c2) { \
|
||||
BN_ULONG ta=(a),tb=(b),t0; \
|
||||
BN_UMULT_LOHI(t0,t1,ta,tb); \
|
||||
c0 += t0; t2 = t1+((c0<t0)?1:0);\
|
||||
c1 += t2; c2 += (c1<t2)?1:0; \
|
||||
c0 += t0; t1 += (c0<t0)?1:0; \
|
||||
c1 += t1; c2 += (c1<t1)?1:0; \
|
||||
}
|
||||
|
||||
# define sqr_add_c(a,i,c0,c1,c2) { \
|
||||
BN_ULONG ta=(a)[i]; \
|
||||
BN_UMULT_LOHI(t1,t2,ta,ta); \
|
||||
c0 += t1; t2 += (c0<t1)?1:0; \
|
||||
c1 += t2; c2 += (c1<t2)?1:0; \
|
||||
}
|
||||
|
||||
# define sqr_add_c2(a,i,j,c0,c1,c2) \
|
||||
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
|
||||
|
||||
# elif defined(BN_UMULT_HIGH)
|
||||
|
||||
# define mul_add_c(a,b,c0,c1,c2) { \
|
||||
BN_ULONG ta=(a),tb=(b); \
|
||||
t1 = ta * tb; \
|
||||
t2 = BN_UMULT_HIGH(ta,tb); \
|
||||
c0 += t1; t2 += (c0<t1)?1:0; \
|
||||
c1 += t2; c2 += (c1<t2)?1:0; \
|
||||
}
|
||||
|
||||
# define mul_add_c2(a,b,c0,c1,c2) { \
|
||||
BN_ULONG ta=(a),tb=(b),t0; \
|
||||
t1 = BN_UMULT_HIGH(ta,tb); \
|
||||
t0 = ta * tb; \
|
||||
c0 += t0; t2 = t1+((c0<t0)?1:0);\
|
||||
c1 += t2; c2 += (c1<t2)?1:0; \
|
||||
c0 += t0; t1 += (c0<t0)?1:0; \
|
||||
c1 += t1; c2 += (c1<t1)?1:0; \
|
||||
}
|
||||
|
||||
# define sqr_add_c(a,i,c0,c1,c2) { \
|
||||
BN_ULONG ta=(a)[i]; \
|
||||
t1 = ta * ta; \
|
||||
t2 = BN_UMULT_HIGH(ta,ta); \
|
||||
c0 += t1; t2 += (c0<t1)?1:0; \
|
||||
c1 += t2; c2 += (c1<t2)?1:0; \
|
||||
}
|
||||
|
||||
# define sqr_add_c2(a,i,j,c0,c1,c2) \
|
||||
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
|
||||
|
||||
# else /* !BN_LLONG */
|
||||
# define mul_add_c(a,b,c0,c1,c2) \
|
||||
t1=LBITS(a); t2=HBITS(a); \
|
||||
bl=LBITS(b); bh=HBITS(b); \
|
||||
mul64(t1,t2,bl,bh); \
|
||||
c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
|
||||
c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
|
||||
|
||||
# define mul_add_c2(a,b,c0,c1,c2) \
|
||||
t1=LBITS(a); t2=HBITS(a); \
|
||||
bl=LBITS(b); bh=HBITS(b); \
|
||||
mul64(t1,t2,bl,bh); \
|
||||
if (t2 & BN_TBIT) c2++; \
|
||||
t2=(t2+t2)&BN_MASK2; \
|
||||
if (t1 & BN_TBIT) t2++; \
|
||||
t1=(t1+t1)&BN_MASK2; \
|
||||
c0=(c0+t1)&BN_MASK2; \
|
||||
if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \
|
||||
c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
|
||||
|
||||
# define sqr_add_c(a,i,c0,c1,c2) \
|
||||
sqr64(t1,t2,(a)[i]); \
|
||||
c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
|
||||
c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
|
||||
|
||||
# define sqr_add_c2(a,i,j,c0,c1,c2) \
|
||||
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
|
||||
# endif /* !BN_LLONG */
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
# ifdef BN_LLONG
|
||||
BN_ULLONG t;
|
||||
# else
|
||||
BN_ULONG bl, bh;
|
||||
# endif
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[0], c1, c2, c3);
|
||||
r[0] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[0], b[1], c2, c3, c1);
|
||||
mul_add_c(a[1], b[0], c2, c3, c1);
|
||||
r[1] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[2], b[0], c3, c1, c2);
|
||||
mul_add_c(a[1], b[1], c3, c1, c2);
|
||||
mul_add_c(a[0], b[2], c3, c1, c2);
|
||||
r[2] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[3], c1, c2, c3);
|
||||
mul_add_c(a[1], b[2], c1, c2, c3);
|
||||
mul_add_c(a[2], b[1], c1, c2, c3);
|
||||
mul_add_c(a[3], b[0], c1, c2, c3);
|
||||
r[3] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[4], b[0], c2, c3, c1);
|
||||
mul_add_c(a[3], b[1], c2, c3, c1);
|
||||
mul_add_c(a[2], b[2], c2, c3, c1);
|
||||
mul_add_c(a[1], b[3], c2, c3, c1);
|
||||
mul_add_c(a[0], b[4], c2, c3, c1);
|
||||
r[4] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[0], b[5], c3, c1, c2);
|
||||
mul_add_c(a[1], b[4], c3, c1, c2);
|
||||
mul_add_c(a[2], b[3], c3, c1, c2);
|
||||
mul_add_c(a[3], b[2], c3, c1, c2);
|
||||
mul_add_c(a[4], b[1], c3, c1, c2);
|
||||
mul_add_c(a[5], b[0], c3, c1, c2);
|
||||
r[5] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[6], b[0], c1, c2, c3);
|
||||
mul_add_c(a[5], b[1], c1, c2, c3);
|
||||
mul_add_c(a[4], b[2], c1, c2, c3);
|
||||
mul_add_c(a[3], b[3], c1, c2, c3);
|
||||
mul_add_c(a[2], b[4], c1, c2, c3);
|
||||
mul_add_c(a[1], b[5], c1, c2, c3);
|
||||
mul_add_c(a[0], b[6], c1, c2, c3);
|
||||
r[6] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[0], b[7], c2, c3, c1);
|
||||
mul_add_c(a[1], b[6], c2, c3, c1);
|
||||
mul_add_c(a[2], b[5], c2, c3, c1);
|
||||
mul_add_c(a[3], b[4], c2, c3, c1);
|
||||
mul_add_c(a[4], b[3], c2, c3, c1);
|
||||
mul_add_c(a[5], b[2], c2, c3, c1);
|
||||
mul_add_c(a[6], b[1], c2, c3, c1);
|
||||
mul_add_c(a[7], b[0], c2, c3, c1);
|
||||
r[7] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[7], b[1], c3, c1, c2);
|
||||
mul_add_c(a[6], b[2], c3, c1, c2);
|
||||
mul_add_c(a[5], b[3], c3, c1, c2);
|
||||
mul_add_c(a[4], b[4], c3, c1, c2);
|
||||
mul_add_c(a[3], b[5], c3, c1, c2);
|
||||
mul_add_c(a[2], b[6], c3, c1, c2);
|
||||
mul_add_c(a[1], b[7], c3, c1, c2);
|
||||
r[8] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[2], b[7], c1, c2, c3);
|
||||
mul_add_c(a[3], b[6], c1, c2, c3);
|
||||
mul_add_c(a[4], b[5], c1, c2, c3);
|
||||
mul_add_c(a[5], b[4], c1, c2, c3);
|
||||
mul_add_c(a[6], b[3], c1, c2, c3);
|
||||
mul_add_c(a[7], b[2], c1, c2, c3);
|
||||
r[9] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[7], b[3], c2, c3, c1);
|
||||
mul_add_c(a[6], b[4], c2, c3, c1);
|
||||
mul_add_c(a[5], b[5], c2, c3, c1);
|
||||
mul_add_c(a[4], b[6], c2, c3, c1);
|
||||
mul_add_c(a[3], b[7], c2, c3, c1);
|
||||
r[10] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[4], b[7], c3, c1, c2);
|
||||
mul_add_c(a[5], b[6], c3, c1, c2);
|
||||
mul_add_c(a[6], b[5], c3, c1, c2);
|
||||
mul_add_c(a[7], b[4], c3, c1, c2);
|
||||
r[11] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[7], b[5], c1, c2, c3);
|
||||
mul_add_c(a[6], b[6], c1, c2, c3);
|
||||
mul_add_c(a[5], b[7], c1, c2, c3);
|
||||
r[12] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[6], b[7], c2, c3, c1);
|
||||
mul_add_c(a[7], b[6], c2, c3, c1);
|
||||
r[13] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[7], b[7], c3, c1, c2);
|
||||
r[14] = c3;
|
||||
r[15] = c1;
|
||||
}
|
||||
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
# ifdef BN_LLONG
|
||||
BN_ULLONG t;
|
||||
# else
|
||||
BN_ULONG bl, bh;
|
||||
# endif
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[0], c1, c2, c3);
|
||||
r[0] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[0], b[1], c2, c3, c1);
|
||||
mul_add_c(a[1], b[0], c2, c3, c1);
|
||||
r[1] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[2], b[0], c3, c1, c2);
|
||||
mul_add_c(a[1], b[1], c3, c1, c2);
|
||||
mul_add_c(a[0], b[2], c3, c1, c2);
|
||||
r[2] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[3], c1, c2, c3);
|
||||
mul_add_c(a[1], b[2], c1, c2, c3);
|
||||
mul_add_c(a[2], b[1], c1, c2, c3);
|
||||
mul_add_c(a[3], b[0], c1, c2, c3);
|
||||
r[3] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[3], b[1], c2, c3, c1);
|
||||
mul_add_c(a[2], b[2], c2, c3, c1);
|
||||
mul_add_c(a[1], b[3], c2, c3, c1);
|
||||
r[4] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[2], b[3], c3, c1, c2);
|
||||
mul_add_c(a[3], b[2], c3, c1, c2);
|
||||
r[5] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[3], b[3], c1, c2, c3);
|
||||
r[6] = c1;
|
||||
r[7] = c2;
|
||||
}
|
||||
|
||||
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
|
||||
{
|
||||
# ifdef BN_LLONG
|
||||
BN_ULLONG t, tt;
|
||||
# else
|
||||
BN_ULONG bl, bh;
|
||||
# endif
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
c3 = 0;
|
||||
sqr_add_c(a, 0, c1, c2, c3);
|
||||
r[0] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c2(a, 1, 0, c2, c3, c1);
|
||||
r[1] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c(a, 1, c3, c1, c2);
|
||||
sqr_add_c2(a, 2, 0, c3, c1, c2);
|
||||
r[2] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c2(a, 3, 0, c1, c2, c3);
|
||||
sqr_add_c2(a, 2, 1, c1, c2, c3);
|
||||
r[3] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c(a, 2, c2, c3, c1);
|
||||
sqr_add_c2(a, 3, 1, c2, c3, c1);
|
||||
sqr_add_c2(a, 4, 0, c2, c3, c1);
|
||||
r[4] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c2(a, 5, 0, c3, c1, c2);
|
||||
sqr_add_c2(a, 4, 1, c3, c1, c2);
|
||||
sqr_add_c2(a, 3, 2, c3, c1, c2);
|
||||
r[5] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c(a, 3, c1, c2, c3);
|
||||
sqr_add_c2(a, 4, 2, c1, c2, c3);
|
||||
sqr_add_c2(a, 5, 1, c1, c2, c3);
|
||||
sqr_add_c2(a, 6, 0, c1, c2, c3);
|
||||
r[6] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c2(a, 7, 0, c2, c3, c1);
|
||||
sqr_add_c2(a, 6, 1, c2, c3, c1);
|
||||
sqr_add_c2(a, 5, 2, c2, c3, c1);
|
||||
sqr_add_c2(a, 4, 3, c2, c3, c1);
|
||||
r[7] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c(a, 4, c3, c1, c2);
|
||||
sqr_add_c2(a, 5, 3, c3, c1, c2);
|
||||
sqr_add_c2(a, 6, 2, c3, c1, c2);
|
||||
sqr_add_c2(a, 7, 1, c3, c1, c2);
|
||||
r[8] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c2(a, 7, 2, c1, c2, c3);
|
||||
sqr_add_c2(a, 6, 3, c1, c2, c3);
|
||||
sqr_add_c2(a, 5, 4, c1, c2, c3);
|
||||
r[9] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c(a, 5, c2, c3, c1);
|
||||
sqr_add_c2(a, 6, 4, c2, c3, c1);
|
||||
sqr_add_c2(a, 7, 3, c2, c3, c1);
|
||||
r[10] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c2(a, 7, 4, c3, c1, c2);
|
||||
sqr_add_c2(a, 6, 5, c3, c1, c2);
|
||||
r[11] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c(a, 6, c1, c2, c3);
|
||||
sqr_add_c2(a, 7, 5, c1, c2, c3);
|
||||
r[12] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c2(a, 7, 6, c2, c3, c1);
|
||||
r[13] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c(a, 7, c3, c1, c2);
|
||||
r[14] = c3;
|
||||
r[15] = c1;
|
||||
}
|
||||
|
||||
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
|
||||
{
|
||||
# ifdef BN_LLONG
|
||||
BN_ULLONG t, tt;
|
||||
# else
|
||||
BN_ULONG bl, bh;
|
||||
# endif
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
c3 = 0;
|
||||
sqr_add_c(a, 0, c1, c2, c3);
|
||||
r[0] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c2(a, 1, 0, c2, c3, c1);
|
||||
r[1] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c(a, 1, c3, c1, c2);
|
||||
sqr_add_c2(a, 2, 0, c3, c1, c2);
|
||||
r[2] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c2(a, 3, 0, c1, c2, c3);
|
||||
sqr_add_c2(a, 2, 1, c1, c2, c3);
|
||||
r[3] = c1;
|
||||
c1 = 0;
|
||||
sqr_add_c(a, 2, c2, c3, c1);
|
||||
sqr_add_c2(a, 3, 1, c2, c3, c1);
|
||||
r[4] = c2;
|
||||
c2 = 0;
|
||||
sqr_add_c2(a, 3, 2, c3, c1, c2);
|
||||
r[5] = c3;
|
||||
c3 = 0;
|
||||
sqr_add_c(a, 3, c1, c2, c3);
|
||||
r[6] = c1;
|
||||
r[7] = c2;
|
||||
}
|
||||
#else /* !BN_MUL_COMBA */
|
||||
|
||||
/* hmm... is it faster just to do a multiply? */
|
||||
# undef bn_sqr_comba4
|
||||
void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a)
|
||||
{
|
||||
BN_ULONG t[8];
|
||||
bn_sqr_normal(r, a, 4, t);
|
||||
}
|
||||
|
||||
# undef bn_sqr_comba8
|
||||
void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a)
|
||||
{
|
||||
BN_ULONG t[16];
|
||||
bn_sqr_normal(r, a, 8, t);
|
||||
}
|
||||
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
r[4] = bn_mul_words(&(r[0]), a, 4, b[0]);
|
||||
r[5] = bn_mul_add_words(&(r[1]), a, 4, b[1]);
|
||||
r[6] = bn_mul_add_words(&(r[2]), a, 4, b[2]);
|
||||
r[7] = bn_mul_add_words(&(r[3]), a, 4, b[3]);
|
||||
}
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
r[8] = bn_mul_words(&(r[0]), a, 8, b[0]);
|
||||
r[9] = bn_mul_add_words(&(r[1]), a, 8, b[1]);
|
||||
r[10] = bn_mul_add_words(&(r[2]), a, 8, b[2]);
|
||||
r[11] = bn_mul_add_words(&(r[3]), a, 8, b[3]);
|
||||
r[12] = bn_mul_add_words(&(r[4]), a, 8, b[4]);
|
||||
r[13] = bn_mul_add_words(&(r[5]), a, 8, b[5]);
|
||||
r[14] = bn_mul_add_words(&(r[6]), a, 8, b[6]);
|
||||
r[15] = bn_mul_add_words(&(r[7]), a, 8, b[7]);
|
||||
}
|
||||
|
||||
#endif /* !BN_MUL_COMBA */
|
||||
@@ -0,0 +1,13 @@
|
||||
#if defined(IPARCH_pentium)
|
||||
#include "bn86-elf.s"
|
||||
#include "co86-elf.s"
|
||||
|
||||
#elif defined(IPARCH_pentium64)
|
||||
#include "x86_64-mont.s"
|
||||
|
||||
#elif defined(IPARCH_powerpc)
|
||||
#include "ppc32.s"
|
||||
|
||||
#else
|
||||
#error "Unsupported IPARCH"
|
||||
#endif
|
||||
@@ -0,0 +1,374 @@
|
||||
/* crypto/bn/bn_blind.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
#define BN_BLINDING_COUNTER 32
|
||||
|
||||
struct bn_blinding_st {
|
||||
BIGNUM *A;
|
||||
BIGNUM *Ai;
|
||||
BIGNUM *e;
|
||||
BIGNUM *mod; /* just a reference */
|
||||
unsigned long thread_id; /* added in OpenSSL 0.9.6j and 0.9.7b; used
|
||||
* only by crypto/rsa/rsa_eay.c, rsa_lib.c */
|
||||
int counter;
|
||||
unsigned long flags;
|
||||
BN_MONT_CTX *m_ctx;
|
||||
int (*bn_mod_exp) (BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *m_ctx);
|
||||
};
|
||||
|
||||
BN_BLINDING *BN_BLINDING_new(const BIGNUM *A, const BIGNUM *Ai, BIGNUM *mod)
|
||||
{
|
||||
BN_BLINDING *ret = NULL;
|
||||
|
||||
bn_check_top(mod);
|
||||
|
||||
if ((ret = (BN_BLINDING *)OPENSSL_malloc(sizeof(BN_BLINDING))) == NULL) {
|
||||
BNerr(BN_F_BN_BLINDING_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
memset(ret, 0, sizeof(BN_BLINDING));
|
||||
if (A != NULL) {
|
||||
if ((ret->A = BN_dup(A)) == NULL)
|
||||
goto err;
|
||||
}
|
||||
if (Ai != NULL) {
|
||||
if ((ret->Ai = BN_dup(Ai)) == NULL)
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* save a copy of mod in the BN_BLINDING structure */
|
||||
if ((ret->mod = BN_dup(mod)) == NULL)
|
||||
goto err;
|
||||
if (BN_get_flags(mod, BN_FLG_CONSTTIME) != 0)
|
||||
BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
|
||||
|
||||
/*
|
||||
* Set the counter to the special value -1 to indicate that this is
|
||||
* never-used fresh blinding that does not need updating before first
|
||||
* use.
|
||||
*/
|
||||
ret->counter = -1;
|
||||
return (ret);
|
||||
err:
|
||||
if (ret != NULL)
|
||||
BN_BLINDING_free(ret);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
void BN_BLINDING_free(BN_BLINDING *r)
|
||||
{
|
||||
if (r == NULL)
|
||||
return;
|
||||
|
||||
if (r->A != NULL)
|
||||
BN_free(r->A);
|
||||
if (r->Ai != NULL)
|
||||
BN_free(r->Ai);
|
||||
if (r->e != NULL)
|
||||
BN_free(r->e);
|
||||
if (r->mod != NULL)
|
||||
BN_free(r->mod);
|
||||
OPENSSL_free(r);
|
||||
}
|
||||
|
||||
int BN_BLINDING_update(BN_BLINDING *b, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
if ((b->A == NULL) || (b->Ai == NULL)) {
|
||||
BNerr(BN_F_BN_BLINDING_UPDATE, BN_R_NOT_INITIALIZED);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (b->counter == -1)
|
||||
b->counter = 0;
|
||||
|
||||
if (++b->counter == BN_BLINDING_COUNTER && b->e != NULL &&
|
||||
!(b->flags & BN_BLINDING_NO_RECREATE)) {
|
||||
/* re-create blinding parameters */
|
||||
if (!BN_BLINDING_create_param(b, NULL, NULL, ctx, NULL, NULL))
|
||||
goto err;
|
||||
} else if (!(b->flags & BN_BLINDING_NO_UPDATE)) {
|
||||
if (!BN_mod_mul(b->A, b->A, b->A, b->mod, ctx))
|
||||
goto err;
|
||||
if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
if (b->counter == BN_BLINDING_COUNTER)
|
||||
b->counter = 0;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
|
||||
{
|
||||
return BN_BLINDING_convert_ex(n, NULL, b, ctx);
|
||||
}
|
||||
|
||||
int BN_BLINDING_convert_ex(BIGNUM *n, BIGNUM *r, BN_BLINDING *b, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 1;
|
||||
|
||||
bn_check_top(n);
|
||||
|
||||
if ((b->A == NULL) || (b->Ai == NULL)) {
|
||||
BNerr(BN_F_BN_BLINDING_CONVERT_EX, BN_R_NOT_INITIALIZED);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (b->counter == -1)
|
||||
/* Fresh blinding, doesn't need updating. */
|
||||
b->counter = 0;
|
||||
else if (!BN_BLINDING_update(b, ctx))
|
||||
return (0);
|
||||
|
||||
if (r != NULL) {
|
||||
if (!BN_copy(r, b->Ai))
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
if (!BN_mod_mul(n, n, b->A, b->mod, ctx))
|
||||
ret = 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int BN_BLINDING_invert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx)
|
||||
{
|
||||
return BN_BLINDING_invert_ex(n, NULL, b, ctx);
|
||||
}
|
||||
|
||||
int BN_BLINDING_invert_ex(BIGNUM *n, const BIGNUM *r, BN_BLINDING *b,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
bn_check_top(n);
|
||||
|
||||
if (r != NULL)
|
||||
ret = BN_mod_mul(n, n, r, b->mod, ctx);
|
||||
else {
|
||||
if (b->Ai == NULL) {
|
||||
BNerr(BN_F_BN_BLINDING_INVERT_EX, BN_R_NOT_INITIALIZED);
|
||||
return (0);
|
||||
}
|
||||
ret = BN_mod_mul(n, n, b->Ai, b->mod, ctx);
|
||||
}
|
||||
|
||||
bn_check_top(n);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
unsigned long BN_BLINDING_get_thread_id(const BN_BLINDING *b)
|
||||
{
|
||||
return b->thread_id;
|
||||
}
|
||||
|
||||
void BN_BLINDING_set_thread_id(BN_BLINDING *b, unsigned long n)
|
||||
{
|
||||
b->thread_id = n;
|
||||
}
|
||||
|
||||
unsigned long BN_BLINDING_get_flags(const BN_BLINDING *b)
|
||||
{
|
||||
return b->flags;
|
||||
}
|
||||
|
||||
void BN_BLINDING_set_flags(BN_BLINDING *b, unsigned long flags)
|
||||
{
|
||||
b->flags = flags;
|
||||
}
|
||||
|
||||
BN_BLINDING *BN_BLINDING_create_param(BN_BLINDING *b,
|
||||
const BIGNUM *e, BIGNUM *m, BN_CTX *ctx,
|
||||
int (*bn_mod_exp) (BIGNUM *r,
|
||||
const BIGNUM *a,
|
||||
const BIGNUM *p,
|
||||
const BIGNUM *m,
|
||||
BN_CTX *ctx,
|
||||
BN_MONT_CTX *m_ctx),
|
||||
BN_MONT_CTX *m_ctx)
|
||||
{
|
||||
int retry_counter = 32;
|
||||
BN_BLINDING *ret = NULL;
|
||||
|
||||
if (b == NULL)
|
||||
ret = BN_BLINDING_new(NULL, NULL, m);
|
||||
else
|
||||
ret = b;
|
||||
|
||||
if (ret == NULL)
|
||||
goto err;
|
||||
|
||||
if (ret->A == NULL && (ret->A = BN_new()) == NULL)
|
||||
goto err;
|
||||
if (ret->Ai == NULL && (ret->Ai = BN_new()) == NULL)
|
||||
goto err;
|
||||
|
||||
if (e != NULL) {
|
||||
if (ret->e != NULL)
|
||||
BN_free(ret->e);
|
||||
ret->e = BN_dup(e);
|
||||
}
|
||||
if (ret->e == NULL)
|
||||
goto err;
|
||||
|
||||
if (bn_mod_exp != NULL)
|
||||
ret->bn_mod_exp = bn_mod_exp;
|
||||
if (m_ctx != NULL)
|
||||
ret->m_ctx = m_ctx;
|
||||
|
||||
do {
|
||||
if (!BN_rand_range(ret->A, ret->mod))
|
||||
goto err;
|
||||
if (BN_mod_inverse(ret->Ai, ret->A, ret->mod, ctx) == NULL) {
|
||||
/*
|
||||
* this should almost never happen for good RSA keys
|
||||
*/
|
||||
unsigned long error = ERR_peek_last_error();
|
||||
if (ERR_GET_REASON(error) == BN_R_NO_INVERSE) {
|
||||
if (retry_counter-- == 0) {
|
||||
BNerr(BN_F_BN_BLINDING_CREATE_PARAM,
|
||||
BN_R_TOO_MANY_ITERATIONS);
|
||||
goto err;
|
||||
}
|
||||
ERR_clear_error();
|
||||
} else
|
||||
goto err;
|
||||
} else
|
||||
break;
|
||||
} while (1);
|
||||
|
||||
if (ret->bn_mod_exp != NULL && ret->m_ctx != NULL) {
|
||||
if (!ret->bn_mod_exp
|
||||
(ret->A, ret->A, ret->e, ret->mod, ctx, ret->m_ctx))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_mod_exp(ret->A, ret->A, ret->e, ret->mod, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
return ret;
|
||||
err:
|
||||
if (b == NULL && ret != NULL) {
|
||||
BN_BLINDING_free(ret);
|
||||
ret = NULL;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,548 @@
|
||||
/* crypto/bn/knownprimes.c */
|
||||
/* Insert boilerplate */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/*-
|
||||
* "First Oakley Default Group" from RFC2409, section 6.1.
|
||||
*
|
||||
* The prime is: 2^768 - 2 ^704 - 1 + 2^64 * { [2^638 pi] + 149686 }
|
||||
*
|
||||
* RFC2409 specifies a generator of 2.
|
||||
* RFC2412 specifies a generator of of 22.
|
||||
*/
|
||||
|
||||
BIGNUM *get_rfc2409_prime_768(BIGNUM *bn)
|
||||
{
|
||||
static const unsigned char RFC2409_PRIME_768[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
|
||||
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
|
||||
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
|
||||
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
|
||||
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
|
||||
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
|
||||
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x3A, 0x36, 0x20,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
return BN_bin2bn(RFC2409_PRIME_768, sizeof(RFC2409_PRIME_768), bn);
|
||||
}
|
||||
|
||||
/*-
|
||||
* "Second Oakley Default Group" from RFC2409, section 6.2.
|
||||
*
|
||||
* The prime is: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }.
|
||||
*
|
||||
* RFC2409 specifies a generator of 2.
|
||||
* RFC2412 specifies a generator of 22.
|
||||
*/
|
||||
|
||||
BIGNUM *get_rfc2409_prime_1024(BIGNUM *bn)
|
||||
{
|
||||
static const unsigned char RFC2409_PRIME_1024[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
|
||||
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
|
||||
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
|
||||
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
|
||||
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
|
||||
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
|
||||
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
|
||||
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
|
||||
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
|
||||
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE6, 0x53, 0x81,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
return BN_bin2bn(RFC2409_PRIME_1024, sizeof(RFC2409_PRIME_1024), bn);
|
||||
}
|
||||
|
||||
/*-
|
||||
* "1536-bit MODP Group" from RFC3526, Section 2.
|
||||
*
|
||||
* The prime is: 2^1536 - 2^1472 - 1 + 2^64 * { [2^1406 pi] + 741804 }
|
||||
*
|
||||
* RFC3526 specifies a generator of 2.
|
||||
* RFC2312 specifies a generator of 22.
|
||||
*/
|
||||
|
||||
BIGNUM *get_rfc3526_prime_1536(BIGNUM *bn)
|
||||
{
|
||||
static const unsigned char RFC3526_PRIME_1536[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
|
||||
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
|
||||
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
|
||||
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
|
||||
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
|
||||
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
|
||||
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
|
||||
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
|
||||
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
|
||||
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
|
||||
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
|
||||
0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
|
||||
0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
|
||||
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
|
||||
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x23, 0x73, 0x27,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
return BN_bin2bn(RFC3526_PRIME_1536, sizeof(RFC3526_PRIME_1536), bn);
|
||||
}
|
||||
|
||||
/*-
|
||||
* "2048-bit MODP Group" from RFC3526, Section 3.
|
||||
*
|
||||
* The prime is: 2^2048 - 2^1984 - 1 + 2^64 * { [2^1918 pi] + 124476 }
|
||||
*
|
||||
* RFC3526 specifies a generator of 2.
|
||||
*/
|
||||
|
||||
BIGNUM *get_rfc3526_prime_2048(BIGNUM *bn)
|
||||
{
|
||||
static const unsigned char RFC3526_PRIME_2048[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
|
||||
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
|
||||
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
|
||||
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
|
||||
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
|
||||
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
|
||||
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
|
||||
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
|
||||
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
|
||||
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
|
||||
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
|
||||
0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
|
||||
0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
|
||||
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
|
||||
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
|
||||
0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
||||
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
|
||||
0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
|
||||
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
|
||||
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
|
||||
0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
|
||||
0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
||||
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAC, 0xAA, 0x68,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
return BN_bin2bn(RFC3526_PRIME_2048, sizeof(RFC3526_PRIME_2048), bn);
|
||||
}
|
||||
|
||||
/*-
|
||||
* "3072-bit MODP Group" from RFC3526, Section 4.
|
||||
*
|
||||
* The prime is: 2^3072 - 2^3008 - 1 + 2^64 * { [2^2942 pi] + 1690314 }
|
||||
*
|
||||
* RFC3526 specifies a generator of 2.
|
||||
*/
|
||||
|
||||
BIGNUM *get_rfc3526_prime_3072(BIGNUM *bn)
|
||||
{
|
||||
static const unsigned char RFC3526_PRIME_3072[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
|
||||
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
|
||||
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
|
||||
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
|
||||
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
|
||||
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
|
||||
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
|
||||
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
|
||||
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
|
||||
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
|
||||
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
|
||||
0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
|
||||
0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
|
||||
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
|
||||
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
|
||||
0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
||||
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
|
||||
0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
|
||||
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
|
||||
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
|
||||
0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
|
||||
0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
||||
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
|
||||
0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
|
||||
0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
|
||||
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
|
||||
0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
|
||||
0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
|
||||
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
|
||||
0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
|
||||
0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
|
||||
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
|
||||
0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
|
||||
0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
|
||||
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
|
||||
0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
|
||||
0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
|
||||
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
|
||||
0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x3A, 0xD2, 0xCA,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
return BN_bin2bn(RFC3526_PRIME_3072, sizeof(RFC3526_PRIME_3072), bn);
|
||||
}
|
||||
|
||||
/*-
|
||||
* "4096-bit MODP Group" from RFC3526, Section 5.
|
||||
*
|
||||
* The prime is: 2^4096 - 2^4032 - 1 + 2^64 * { [2^3966 pi] + 240904 }
|
||||
*
|
||||
* RFC3526 specifies a generator of 2.
|
||||
*/
|
||||
|
||||
BIGNUM *get_rfc3526_prime_4096(BIGNUM *bn)
|
||||
{
|
||||
static const unsigned char RFC3526_PRIME_4096[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
|
||||
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
|
||||
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
|
||||
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
|
||||
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
|
||||
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
|
||||
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
|
||||
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
|
||||
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
|
||||
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
|
||||
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
|
||||
0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
|
||||
0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
|
||||
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
|
||||
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
|
||||
0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
||||
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
|
||||
0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
|
||||
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
|
||||
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
|
||||
0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
|
||||
0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
||||
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
|
||||
0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
|
||||
0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
|
||||
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
|
||||
0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
|
||||
0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
|
||||
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
|
||||
0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
|
||||
0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
|
||||
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
|
||||
0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
|
||||
0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
|
||||
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
|
||||
0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
|
||||
0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
|
||||
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
|
||||
0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
|
||||
0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
|
||||
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
|
||||
0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
|
||||
0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
|
||||
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
|
||||
0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
|
||||
0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
|
||||
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
|
||||
0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
|
||||
0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
|
||||
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
|
||||
0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
|
||||
0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
|
||||
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
|
||||
0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
|
||||
0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x06, 0x31, 0x99,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
return BN_bin2bn(RFC3526_PRIME_4096, sizeof(RFC3526_PRIME_4096), bn);
|
||||
}
|
||||
|
||||
/*-
|
||||
* "6144-bit MODP Group" from RFC3526, Section 6.
|
||||
*
|
||||
* The prime is: 2^6144 - 2^6080 - 1 + 2^64 * { [2^6014 pi] + 929484 }
|
||||
*
|
||||
* RFC3526 specifies a generator of 2.
|
||||
*/
|
||||
|
||||
BIGNUM *get_rfc3526_prime_6144(BIGNUM *bn)
|
||||
{
|
||||
static const unsigned char RFC3526_PRIME_6144[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
|
||||
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
|
||||
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
|
||||
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
|
||||
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
|
||||
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
|
||||
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
|
||||
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
|
||||
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
|
||||
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
|
||||
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
|
||||
0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
|
||||
0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
|
||||
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
|
||||
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
|
||||
0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
||||
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
|
||||
0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
|
||||
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
|
||||
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
|
||||
0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
|
||||
0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
||||
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
|
||||
0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
|
||||
0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
|
||||
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
|
||||
0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
|
||||
0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
|
||||
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
|
||||
0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
|
||||
0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
|
||||
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
|
||||
0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
|
||||
0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
|
||||
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
|
||||
0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
|
||||
0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
|
||||
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
|
||||
0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
|
||||
0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
|
||||
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
|
||||
0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
|
||||
0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
|
||||
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
|
||||
0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
|
||||
0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
|
||||
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
|
||||
0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
|
||||
0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
|
||||
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
|
||||
0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
|
||||
0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
|
||||
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
|
||||
0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
|
||||
0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
|
||||
0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26,
|
||||
0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE,
|
||||
0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
|
||||
0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E,
|
||||
0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE,
|
||||
0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
|
||||
0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18,
|
||||
0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED,
|
||||
0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
|
||||
0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B,
|
||||
0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42,
|
||||
0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
|
||||
0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC,
|
||||
0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03,
|
||||
0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
|
||||
0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82,
|
||||
0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E,
|
||||
0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
|
||||
0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE,
|
||||
0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5,
|
||||
0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
|
||||
0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8,
|
||||
0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0,
|
||||
0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
|
||||
0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76,
|
||||
0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0,
|
||||
0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
|
||||
0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32,
|
||||
0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68,
|
||||
0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
|
||||
0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6,
|
||||
0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xCC, 0x40, 0x24,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
return BN_bin2bn(RFC3526_PRIME_6144, sizeof(RFC3526_PRIME_6144), bn);
|
||||
}
|
||||
|
||||
/*-
|
||||
* "8192-bit MODP Group" from RFC3526, Section 7.
|
||||
*
|
||||
* The prime is: 2^8192 - 2^8128 - 1 + 2^64 * { [2^8062 pi] + 4743158 }
|
||||
*
|
||||
* RFC3526 specifies a generator of 2.
|
||||
*/
|
||||
|
||||
BIGNUM *get_rfc3526_prime_8192(BIGNUM *bn)
|
||||
{
|
||||
static const unsigned char RFC3526_PRIME_8192[] = {
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
0xC9, 0x0F, 0xDA, 0xA2, 0x21, 0x68, 0xC2, 0x34,
|
||||
0xC4, 0xC6, 0x62, 0x8B, 0x80, 0xDC, 0x1C, 0xD1,
|
||||
0x29, 0x02, 0x4E, 0x08, 0x8A, 0x67, 0xCC, 0x74,
|
||||
0x02, 0x0B, 0xBE, 0xA6, 0x3B, 0x13, 0x9B, 0x22,
|
||||
0x51, 0x4A, 0x08, 0x79, 0x8E, 0x34, 0x04, 0xDD,
|
||||
0xEF, 0x95, 0x19, 0xB3, 0xCD, 0x3A, 0x43, 0x1B,
|
||||
0x30, 0x2B, 0x0A, 0x6D, 0xF2, 0x5F, 0x14, 0x37,
|
||||
0x4F, 0xE1, 0x35, 0x6D, 0x6D, 0x51, 0xC2, 0x45,
|
||||
0xE4, 0x85, 0xB5, 0x76, 0x62, 0x5E, 0x7E, 0xC6,
|
||||
0xF4, 0x4C, 0x42, 0xE9, 0xA6, 0x37, 0xED, 0x6B,
|
||||
0x0B, 0xFF, 0x5C, 0xB6, 0xF4, 0x06, 0xB7, 0xED,
|
||||
0xEE, 0x38, 0x6B, 0xFB, 0x5A, 0x89, 0x9F, 0xA5,
|
||||
0xAE, 0x9F, 0x24, 0x11, 0x7C, 0x4B, 0x1F, 0xE6,
|
||||
0x49, 0x28, 0x66, 0x51, 0xEC, 0xE4, 0x5B, 0x3D,
|
||||
0xC2, 0x00, 0x7C, 0xB8, 0xA1, 0x63, 0xBF, 0x05,
|
||||
0x98, 0xDA, 0x48, 0x36, 0x1C, 0x55, 0xD3, 0x9A,
|
||||
0x69, 0x16, 0x3F, 0xA8, 0xFD, 0x24, 0xCF, 0x5F,
|
||||
0x83, 0x65, 0x5D, 0x23, 0xDC, 0xA3, 0xAD, 0x96,
|
||||
0x1C, 0x62, 0xF3, 0x56, 0x20, 0x85, 0x52, 0xBB,
|
||||
0x9E, 0xD5, 0x29, 0x07, 0x70, 0x96, 0x96, 0x6D,
|
||||
0x67, 0x0C, 0x35, 0x4E, 0x4A, 0xBC, 0x98, 0x04,
|
||||
0xF1, 0x74, 0x6C, 0x08, 0xCA, 0x18, 0x21, 0x7C,
|
||||
0x32, 0x90, 0x5E, 0x46, 0x2E, 0x36, 0xCE, 0x3B,
|
||||
0xE3, 0x9E, 0x77, 0x2C, 0x18, 0x0E, 0x86, 0x03,
|
||||
0x9B, 0x27, 0x83, 0xA2, 0xEC, 0x07, 0xA2, 0x8F,
|
||||
0xB5, 0xC5, 0x5D, 0xF0, 0x6F, 0x4C, 0x52, 0xC9,
|
||||
0xDE, 0x2B, 0xCB, 0xF6, 0x95, 0x58, 0x17, 0x18,
|
||||
0x39, 0x95, 0x49, 0x7C, 0xEA, 0x95, 0x6A, 0xE5,
|
||||
0x15, 0xD2, 0x26, 0x18, 0x98, 0xFA, 0x05, 0x10,
|
||||
0x15, 0x72, 0x8E, 0x5A, 0x8A, 0xAA, 0xC4, 0x2D,
|
||||
0xAD, 0x33, 0x17, 0x0D, 0x04, 0x50, 0x7A, 0x33,
|
||||
0xA8, 0x55, 0x21, 0xAB, 0xDF, 0x1C, 0xBA, 0x64,
|
||||
0xEC, 0xFB, 0x85, 0x04, 0x58, 0xDB, 0xEF, 0x0A,
|
||||
0x8A, 0xEA, 0x71, 0x57, 0x5D, 0x06, 0x0C, 0x7D,
|
||||
0xB3, 0x97, 0x0F, 0x85, 0xA6, 0xE1, 0xE4, 0xC7,
|
||||
0xAB, 0xF5, 0xAE, 0x8C, 0xDB, 0x09, 0x33, 0xD7,
|
||||
0x1E, 0x8C, 0x94, 0xE0, 0x4A, 0x25, 0x61, 0x9D,
|
||||
0xCE, 0xE3, 0xD2, 0x26, 0x1A, 0xD2, 0xEE, 0x6B,
|
||||
0xF1, 0x2F, 0xFA, 0x06, 0xD9, 0x8A, 0x08, 0x64,
|
||||
0xD8, 0x76, 0x02, 0x73, 0x3E, 0xC8, 0x6A, 0x64,
|
||||
0x52, 0x1F, 0x2B, 0x18, 0x17, 0x7B, 0x20, 0x0C,
|
||||
0xBB, 0xE1, 0x17, 0x57, 0x7A, 0x61, 0x5D, 0x6C,
|
||||
0x77, 0x09, 0x88, 0xC0, 0xBA, 0xD9, 0x46, 0xE2,
|
||||
0x08, 0xE2, 0x4F, 0xA0, 0x74, 0xE5, 0xAB, 0x31,
|
||||
0x43, 0xDB, 0x5B, 0xFC, 0xE0, 0xFD, 0x10, 0x8E,
|
||||
0x4B, 0x82, 0xD1, 0x20, 0xA9, 0x21, 0x08, 0x01,
|
||||
0x1A, 0x72, 0x3C, 0x12, 0xA7, 0x87, 0xE6, 0xD7,
|
||||
0x88, 0x71, 0x9A, 0x10, 0xBD, 0xBA, 0x5B, 0x26,
|
||||
0x99, 0xC3, 0x27, 0x18, 0x6A, 0xF4, 0xE2, 0x3C,
|
||||
0x1A, 0x94, 0x68, 0x34, 0xB6, 0x15, 0x0B, 0xDA,
|
||||
0x25, 0x83, 0xE9, 0xCA, 0x2A, 0xD4, 0x4C, 0xE8,
|
||||
0xDB, 0xBB, 0xC2, 0xDB, 0x04, 0xDE, 0x8E, 0xF9,
|
||||
0x2E, 0x8E, 0xFC, 0x14, 0x1F, 0xBE, 0xCA, 0xA6,
|
||||
0x28, 0x7C, 0x59, 0x47, 0x4E, 0x6B, 0xC0, 0x5D,
|
||||
0x99, 0xB2, 0x96, 0x4F, 0xA0, 0x90, 0xC3, 0xA2,
|
||||
0x23, 0x3B, 0xA1, 0x86, 0x51, 0x5B, 0xE7, 0xED,
|
||||
0x1F, 0x61, 0x29, 0x70, 0xCE, 0xE2, 0xD7, 0xAF,
|
||||
0xB8, 0x1B, 0xDD, 0x76, 0x21, 0x70, 0x48, 0x1C,
|
||||
0xD0, 0x06, 0x91, 0x27, 0xD5, 0xB0, 0x5A, 0xA9,
|
||||
0x93, 0xB4, 0xEA, 0x98, 0x8D, 0x8F, 0xDD, 0xC1,
|
||||
0x86, 0xFF, 0xB7, 0xDC, 0x90, 0xA6, 0xC0, 0x8F,
|
||||
0x4D, 0xF4, 0x35, 0xC9, 0x34, 0x02, 0x84, 0x92,
|
||||
0x36, 0xC3, 0xFA, 0xB4, 0xD2, 0x7C, 0x70, 0x26,
|
||||
0xC1, 0xD4, 0xDC, 0xB2, 0x60, 0x26, 0x46, 0xDE,
|
||||
0xC9, 0x75, 0x1E, 0x76, 0x3D, 0xBA, 0x37, 0xBD,
|
||||
0xF8, 0xFF, 0x94, 0x06, 0xAD, 0x9E, 0x53, 0x0E,
|
||||
0xE5, 0xDB, 0x38, 0x2F, 0x41, 0x30, 0x01, 0xAE,
|
||||
0xB0, 0x6A, 0x53, 0xED, 0x90, 0x27, 0xD8, 0x31,
|
||||
0x17, 0x97, 0x27, 0xB0, 0x86, 0x5A, 0x89, 0x18,
|
||||
0xDA, 0x3E, 0xDB, 0xEB, 0xCF, 0x9B, 0x14, 0xED,
|
||||
0x44, 0xCE, 0x6C, 0xBA, 0xCE, 0xD4, 0xBB, 0x1B,
|
||||
0xDB, 0x7F, 0x14, 0x47, 0xE6, 0xCC, 0x25, 0x4B,
|
||||
0x33, 0x20, 0x51, 0x51, 0x2B, 0xD7, 0xAF, 0x42,
|
||||
0x6F, 0xB8, 0xF4, 0x01, 0x37, 0x8C, 0xD2, 0xBF,
|
||||
0x59, 0x83, 0xCA, 0x01, 0xC6, 0x4B, 0x92, 0xEC,
|
||||
0xF0, 0x32, 0xEA, 0x15, 0xD1, 0x72, 0x1D, 0x03,
|
||||
0xF4, 0x82, 0xD7, 0xCE, 0x6E, 0x74, 0xFE, 0xF6,
|
||||
0xD5, 0x5E, 0x70, 0x2F, 0x46, 0x98, 0x0C, 0x82,
|
||||
0xB5, 0xA8, 0x40, 0x31, 0x90, 0x0B, 0x1C, 0x9E,
|
||||
0x59, 0xE7, 0xC9, 0x7F, 0xBE, 0xC7, 0xE8, 0xF3,
|
||||
0x23, 0xA9, 0x7A, 0x7E, 0x36, 0xCC, 0x88, 0xBE,
|
||||
0x0F, 0x1D, 0x45, 0xB7, 0xFF, 0x58, 0x5A, 0xC5,
|
||||
0x4B, 0xD4, 0x07, 0xB2, 0x2B, 0x41, 0x54, 0xAA,
|
||||
0xCC, 0x8F, 0x6D, 0x7E, 0xBF, 0x48, 0xE1, 0xD8,
|
||||
0x14, 0xCC, 0x5E, 0xD2, 0x0F, 0x80, 0x37, 0xE0,
|
||||
0xA7, 0x97, 0x15, 0xEE, 0xF2, 0x9B, 0xE3, 0x28,
|
||||
0x06, 0xA1, 0xD5, 0x8B, 0xB7, 0xC5, 0xDA, 0x76,
|
||||
0xF5, 0x50, 0xAA, 0x3D, 0x8A, 0x1F, 0xBF, 0xF0,
|
||||
0xEB, 0x19, 0xCC, 0xB1, 0xA3, 0x13, 0xD5, 0x5C,
|
||||
0xDA, 0x56, 0xC9, 0xEC, 0x2E, 0xF2, 0x96, 0x32,
|
||||
0x38, 0x7F, 0xE8, 0xD7, 0x6E, 0x3C, 0x04, 0x68,
|
||||
0x04, 0x3E, 0x8F, 0x66, 0x3F, 0x48, 0x60, 0xEE,
|
||||
0x12, 0xBF, 0x2D, 0x5B, 0x0B, 0x74, 0x74, 0xD6,
|
||||
0xE6, 0x94, 0xF9, 0x1E, 0x6D, 0xBE, 0x11, 0x59,
|
||||
0x74, 0xA3, 0x92, 0x6F, 0x12, 0xFE, 0xE5, 0xE4,
|
||||
0x38, 0x77, 0x7C, 0xB6, 0xA9, 0x32, 0xDF, 0x8C,
|
||||
0xD8, 0xBE, 0xC4, 0xD0, 0x73, 0xB9, 0x31, 0xBA,
|
||||
0x3B, 0xC8, 0x32, 0xB6, 0x8D, 0x9D, 0xD3, 0x00,
|
||||
0x74, 0x1F, 0xA7, 0xBF, 0x8A, 0xFC, 0x47, 0xED,
|
||||
0x25, 0x76, 0xF6, 0x93, 0x6B, 0xA4, 0x24, 0x66,
|
||||
0x3A, 0xAB, 0x63, 0x9C, 0x5A, 0xE4, 0xF5, 0x68,
|
||||
0x34, 0x23, 0xB4, 0x74, 0x2B, 0xF1, 0xC9, 0x78,
|
||||
0x23, 0x8F, 0x16, 0xCB, 0xE3, 0x9D, 0x65, 0x2D,
|
||||
0xE3, 0xFD, 0xB8, 0xBE, 0xFC, 0x84, 0x8A, 0xD9,
|
||||
0x22, 0x22, 0x2E, 0x04, 0xA4, 0x03, 0x7C, 0x07,
|
||||
0x13, 0xEB, 0x57, 0xA8, 0x1A, 0x23, 0xF0, 0xC7,
|
||||
0x34, 0x73, 0xFC, 0x64, 0x6C, 0xEA, 0x30, 0x6B,
|
||||
0x4B, 0xCB, 0xC8, 0x86, 0x2F, 0x83, 0x85, 0xDD,
|
||||
0xFA, 0x9D, 0x4B, 0x7F, 0xA2, 0xC0, 0x87, 0xE8,
|
||||
0x79, 0x68, 0x33, 0x03, 0xED, 0x5B, 0xDD, 0x3A,
|
||||
0x06, 0x2B, 0x3C, 0xF5, 0xB3, 0xA2, 0x78, 0xA6,
|
||||
0x6D, 0x2A, 0x13, 0xF8, 0x3F, 0x44, 0xF8, 0x2D,
|
||||
0xDF, 0x31, 0x0E, 0xE0, 0x74, 0xAB, 0x6A, 0x36,
|
||||
0x45, 0x97, 0xE8, 0x99, 0xA0, 0x25, 0x5D, 0xC1,
|
||||
0x64, 0xF3, 0x1C, 0xC5, 0x08, 0x46, 0x85, 0x1D,
|
||||
0xF9, 0xAB, 0x48, 0x19, 0x5D, 0xED, 0x7E, 0xA1,
|
||||
0xB1, 0xD5, 0x10, 0xBD, 0x7E, 0xE7, 0x4D, 0x73,
|
||||
0xFA, 0xF3, 0x6B, 0xC3, 0x1E, 0xCF, 0xA2, 0x68,
|
||||
0x35, 0x90, 0x46, 0xF4, 0xEB, 0x87, 0x9F, 0x92,
|
||||
0x40, 0x09, 0x43, 0x8B, 0x48, 0x1C, 0x6C, 0xD7,
|
||||
0x88, 0x9A, 0x00, 0x2E, 0xD5, 0xEE, 0x38, 0x2B,
|
||||
0xC9, 0x19, 0x0D, 0xA6, 0xFC, 0x02, 0x6E, 0x47,
|
||||
0x95, 0x58, 0xE4, 0x47, 0x56, 0x77, 0xE9, 0xAA,
|
||||
0x9E, 0x30, 0x50, 0xE2, 0x76, 0x56, 0x94, 0xDF,
|
||||
0xC8, 0x1F, 0x56, 0xE8, 0x80, 0xB9, 0x6E, 0x71,
|
||||
0x60, 0xC9, 0x80, 0xDD, 0x98, 0xED, 0xD3, 0xDF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
|
||||
};
|
||||
return BN_bin2bn(RFC3526_PRIME_8192, sizeof(RFC3526_PRIME_8192), bn);
|
||||
}
|
||||
@@ -0,0 +1,448 @@
|
||||
/* crypto/bn/bn_ctx.c */
|
||||
/* Written by Ulf Moeller for the OpenSSL project. */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2004 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#if !defined(BN_CTX_DEBUG) && !defined(BN_DEBUG)
|
||||
# ifndef NDEBUG
|
||||
# define NDEBUG
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
/*-
|
||||
* TODO list
|
||||
*
|
||||
* 1. Check a bunch of "(words+1)" type hacks in various bignum functions and
|
||||
* check they can be safely removed.
|
||||
* - Check +1 and other ugliness in BN_from_montgomery()
|
||||
*
|
||||
* 2. Consider allowing a BN_new_ex() that, at least, lets you specify an
|
||||
* appropriate 'block' size that will be honoured by bn_expand_internal() to
|
||||
* prevent piddly little reallocations. OTOH, profiling bignum expansions in
|
||||
* BN_CTX doesn't show this to be a big issue.
|
||||
*/
|
||||
|
||||
/* How many bignums are in each "pool item"; */
|
||||
#define BN_CTX_POOL_SIZE 16
|
||||
/* The stack frame info is resizing, set a first-time expansion size; */
|
||||
#define BN_CTX_START_FRAMES 32
|
||||
|
||||
/***********/
|
||||
/* BN_POOL */
|
||||
/***********/
|
||||
|
||||
/* A bundle of bignums that can be linked with other bundles */
|
||||
typedef struct bignum_pool_item {
|
||||
/* The bignum values */
|
||||
BIGNUM vals[BN_CTX_POOL_SIZE];
|
||||
/* Linked-list admin */
|
||||
struct bignum_pool_item *prev, *next;
|
||||
} BN_POOL_ITEM;
|
||||
/* A linked-list of bignums grouped in bundles */
|
||||
typedef struct bignum_pool {
|
||||
/* Linked-list admin */
|
||||
BN_POOL_ITEM *head, *current, *tail;
|
||||
/* Stack depth and allocation size */
|
||||
unsigned used, size;
|
||||
} BN_POOL;
|
||||
static void BN_POOL_init(BN_POOL *);
|
||||
static void BN_POOL_finish(BN_POOL *);
|
||||
#ifndef OPENSSL_NO_DEPRECATED
|
||||
static void BN_POOL_reset(BN_POOL *);
|
||||
#endif
|
||||
static BIGNUM *BN_POOL_get(BN_POOL *);
|
||||
static void BN_POOL_release(BN_POOL *, unsigned int);
|
||||
|
||||
/************/
|
||||
/* BN_STACK */
|
||||
/************/
|
||||
|
||||
/* A wrapper to manage the "stack frames" */
|
||||
typedef struct bignum_ctx_stack {
|
||||
/* Array of indexes into the bignum stack */
|
||||
unsigned int *indexes;
|
||||
/* Number of stack frames, and the size of the allocated array */
|
||||
unsigned int depth, size;
|
||||
} BN_STACK;
|
||||
static void BN_STACK_init(BN_STACK *);
|
||||
static void BN_STACK_finish(BN_STACK *);
|
||||
#ifndef OPENSSL_NO_DEPRECATED
|
||||
static void BN_STACK_reset(BN_STACK *);
|
||||
#endif
|
||||
static int BN_STACK_push(BN_STACK *, unsigned int);
|
||||
static unsigned int BN_STACK_pop(BN_STACK *);
|
||||
|
||||
/**********/
|
||||
/* BN_CTX */
|
||||
/**********/
|
||||
|
||||
/* The opaque BN_CTX type */
|
||||
struct bignum_ctx {
|
||||
/* The bignum bundles */
|
||||
BN_POOL pool;
|
||||
/* The "stack frames", if you will */
|
||||
BN_STACK stack;
|
||||
/* The number of bignums currently assigned */
|
||||
unsigned int used;
|
||||
/* Depth of stack overflow */
|
||||
int err_stack;
|
||||
/* Block "gets" until an "end" (compatibility behaviour) */
|
||||
int too_many;
|
||||
};
|
||||
|
||||
/* Enable this to find BN_CTX bugs */
|
||||
#ifdef BN_CTX_DEBUG
|
||||
static const char *ctxdbg_cur = NULL;
|
||||
static void ctxdbg(BN_CTX *ctx)
|
||||
{
|
||||
unsigned int bnidx = 0, fpidx = 0;
|
||||
BN_POOL_ITEM *item = ctx->pool.head;
|
||||
BN_STACK *stack = &ctx->stack;
|
||||
fprintf(stderr, "(%08x): ", (unsigned int)ctx);
|
||||
while (bnidx < ctx->used) {
|
||||
fprintf(stderr, "%02x ", item->vals[bnidx++ % BN_CTX_POOL_SIZE].dmax);
|
||||
if (!(bnidx % BN_CTX_POOL_SIZE))
|
||||
item = item->next;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
bnidx = 0;
|
||||
fprintf(stderr, " : ");
|
||||
while (fpidx < stack->depth) {
|
||||
while (bnidx++ < stack->indexes[fpidx])
|
||||
fprintf(stderr, " ");
|
||||
fprintf(stderr, "^^ ");
|
||||
bnidx++;
|
||||
fpidx++;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
|
||||
# define CTXDBG_ENTRY(str, ctx) do { \
|
||||
ctxdbg_cur = (str); \
|
||||
fprintf(stderr,"Starting %s\n", ctxdbg_cur); \
|
||||
ctxdbg(ctx); \
|
||||
} while(0)
|
||||
# define CTXDBG_EXIT(ctx) do { \
|
||||
fprintf(stderr,"Ending %s\n", ctxdbg_cur); \
|
||||
ctxdbg(ctx); \
|
||||
} while(0)
|
||||
# define CTXDBG_RET(ctx,ret)
|
||||
#else
|
||||
# define CTXDBG_ENTRY(str, ctx)
|
||||
# define CTXDBG_EXIT(ctx)
|
||||
# define CTXDBG_RET(ctx,ret)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This function is an evil legacy and should not be used. This
|
||||
* implementation is WYSIWYG, though I've done my best.
|
||||
*/
|
||||
#ifndef OPENSSL_NO_DEPRECATED
|
||||
void BN_CTX_init(BN_CTX *ctx)
|
||||
{
|
||||
/*
|
||||
* Assume the caller obtained the context via BN_CTX_new() and so is
|
||||
* trying to reset it for use. Nothing else makes sense, least of all
|
||||
* binary compatibility from a time when they could declare a static
|
||||
* variable.
|
||||
*/
|
||||
BN_POOL_reset(&ctx->pool);
|
||||
BN_STACK_reset(&ctx->stack);
|
||||
ctx->used = 0;
|
||||
ctx->err_stack = 0;
|
||||
ctx->too_many = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
BN_CTX *BN_CTX_new(void)
|
||||
{
|
||||
BN_CTX *ret = OPENSSL_malloc(sizeof(BN_CTX));
|
||||
if (!ret) {
|
||||
BNerr(BN_F_BN_CTX_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return NULL;
|
||||
}
|
||||
/* Initialise the structure */
|
||||
BN_POOL_init(&ret->pool);
|
||||
BN_STACK_init(&ret->stack);
|
||||
ret->used = 0;
|
||||
ret->err_stack = 0;
|
||||
ret->too_many = 0;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void BN_CTX_free(BN_CTX *ctx)
|
||||
{
|
||||
if (ctx == NULL)
|
||||
return;
|
||||
#ifdef BN_CTX_DEBUG
|
||||
{
|
||||
BN_POOL_ITEM *pool = ctx->pool.head;
|
||||
fprintf(stderr, "BN_CTX_free, stack-size=%d, pool-bignums=%d\n",
|
||||
ctx->stack.size, ctx->pool.size);
|
||||
fprintf(stderr, "dmaxs: ");
|
||||
while (pool) {
|
||||
unsigned loop = 0;
|
||||
while (loop < BN_CTX_POOL_SIZE)
|
||||
fprintf(stderr, "%02x ", pool->vals[loop++].dmax);
|
||||
pool = pool->next;
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
}
|
||||
#endif
|
||||
BN_STACK_finish(&ctx->stack);
|
||||
BN_POOL_finish(&ctx->pool);
|
||||
OPENSSL_free(ctx);
|
||||
}
|
||||
|
||||
void BN_CTX_start(BN_CTX *ctx)
|
||||
{
|
||||
CTXDBG_ENTRY("BN_CTX_start", ctx);
|
||||
/* If we're already overflowing ... */
|
||||
if (ctx->err_stack || ctx->too_many)
|
||||
ctx->err_stack++;
|
||||
/* (Try to) get a new frame pointer */
|
||||
else if (!BN_STACK_push(&ctx->stack, ctx->used)) {
|
||||
BNerr(BN_F_BN_CTX_START, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
|
||||
ctx->err_stack++;
|
||||
}
|
||||
CTXDBG_EXIT(ctx);
|
||||
}
|
||||
|
||||
void BN_CTX_end(BN_CTX *ctx)
|
||||
{
|
||||
CTXDBG_ENTRY("BN_CTX_end", ctx);
|
||||
if (ctx->err_stack)
|
||||
ctx->err_stack--;
|
||||
else {
|
||||
unsigned int fp = BN_STACK_pop(&ctx->stack);
|
||||
/* Does this stack frame have anything to release? */
|
||||
if (fp < ctx->used)
|
||||
BN_POOL_release(&ctx->pool, ctx->used - fp);
|
||||
ctx->used = fp;
|
||||
/* Unjam "too_many" in case "get" had failed */
|
||||
ctx->too_many = 0;
|
||||
}
|
||||
CTXDBG_EXIT(ctx);
|
||||
}
|
||||
|
||||
BIGNUM *BN_CTX_get(BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
CTXDBG_ENTRY("BN_CTX_get", ctx);
|
||||
if (ctx->err_stack || ctx->too_many)
|
||||
return NULL;
|
||||
if ((ret = BN_POOL_get(&ctx->pool)) == NULL) {
|
||||
/*
|
||||
* Setting too_many prevents repeated "get" attempts from cluttering
|
||||
* the error stack.
|
||||
*/
|
||||
ctx->too_many = 1;
|
||||
BNerr(BN_F_BN_CTX_GET, BN_R_TOO_MANY_TEMPORARY_VARIABLES);
|
||||
return NULL;
|
||||
}
|
||||
/* OK, make sure the returned bignum is "zero" */
|
||||
BN_zero(ret);
|
||||
ctx->used++;
|
||||
CTXDBG_RET(ctx, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/************/
|
||||
/* BN_STACK */
|
||||
/************/
|
||||
|
||||
static void BN_STACK_init(BN_STACK *st)
|
||||
{
|
||||
st->indexes = NULL;
|
||||
st->depth = st->size = 0;
|
||||
}
|
||||
|
||||
static void BN_STACK_finish(BN_STACK *st)
|
||||
{
|
||||
if (st->size)
|
||||
OPENSSL_free(st->indexes);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_DEPRECATED
|
||||
static void BN_STACK_reset(BN_STACK *st)
|
||||
{
|
||||
st->depth = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int BN_STACK_push(BN_STACK *st, unsigned int idx)
|
||||
{
|
||||
if (st->depth == st->size)
|
||||
/* Need to expand */
|
||||
{
|
||||
unsigned int newsize = (st->size ?
|
||||
(st->size * 3 / 2) : BN_CTX_START_FRAMES);
|
||||
unsigned int *newitems = OPENSSL_malloc(newsize *
|
||||
sizeof(unsigned int));
|
||||
if (!newitems)
|
||||
return 0;
|
||||
if (st->depth)
|
||||
memcpy(newitems, st->indexes, st->depth * sizeof(unsigned int));
|
||||
if (st->size)
|
||||
OPENSSL_free(st->indexes);
|
||||
st->indexes = newitems;
|
||||
st->size = newsize;
|
||||
}
|
||||
st->indexes[(st->depth)++] = idx;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static unsigned int BN_STACK_pop(BN_STACK *st)
|
||||
{
|
||||
return st->indexes[--(st->depth)];
|
||||
}
|
||||
|
||||
/***********/
|
||||
/* BN_POOL */
|
||||
/***********/
|
||||
|
||||
static void BN_POOL_init(BN_POOL *p)
|
||||
{
|
||||
p->head = p->current = p->tail = NULL;
|
||||
p->used = p->size = 0;
|
||||
}
|
||||
|
||||
static void BN_POOL_finish(BN_POOL *p)
|
||||
{
|
||||
while (p->head) {
|
||||
unsigned int loop = 0;
|
||||
BIGNUM *bn = p->head->vals;
|
||||
while (loop++ < BN_CTX_POOL_SIZE) {
|
||||
if (bn->d)
|
||||
BN_clear_free(bn);
|
||||
bn++;
|
||||
}
|
||||
p->current = p->head->next;
|
||||
OPENSSL_free(p->head);
|
||||
p->head = p->current;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_DEPRECATED
|
||||
static void BN_POOL_reset(BN_POOL *p)
|
||||
{
|
||||
BN_POOL_ITEM *item = p->head;
|
||||
while (item) {
|
||||
unsigned int loop = 0;
|
||||
BIGNUM *bn = item->vals;
|
||||
while (loop++ < BN_CTX_POOL_SIZE) {
|
||||
if (bn->d)
|
||||
BN_clear(bn);
|
||||
bn++;
|
||||
}
|
||||
item = item->next;
|
||||
}
|
||||
p->current = p->head;
|
||||
p->used = 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static BIGNUM *BN_POOL_get(BN_POOL *p)
|
||||
{
|
||||
if (p->used == p->size) {
|
||||
BIGNUM *bn;
|
||||
unsigned int loop = 0;
|
||||
BN_POOL_ITEM *item = OPENSSL_malloc(sizeof(BN_POOL_ITEM));
|
||||
if (!item)
|
||||
return NULL;
|
||||
/* Initialise the structure */
|
||||
bn = item->vals;
|
||||
while (loop++ < BN_CTX_POOL_SIZE)
|
||||
BN_init(bn++);
|
||||
item->prev = p->tail;
|
||||
item->next = NULL;
|
||||
/* Link it in */
|
||||
if (!p->head)
|
||||
p->head = p->current = p->tail = item;
|
||||
else {
|
||||
p->tail->next = item;
|
||||
p->tail = item;
|
||||
p->current = item;
|
||||
}
|
||||
p->size += BN_CTX_POOL_SIZE;
|
||||
p->used++;
|
||||
/* Return the first bignum from the new pool */
|
||||
return item->vals;
|
||||
}
|
||||
if (!p->used)
|
||||
p->current = p->head;
|
||||
else if ((p->used % BN_CTX_POOL_SIZE) == 0)
|
||||
p->current = p->current->next;
|
||||
return p->current->vals + ((p->used++) % BN_CTX_POOL_SIZE);
|
||||
}
|
||||
|
||||
static void BN_POOL_release(BN_POOL *p, unsigned int num)
|
||||
{
|
||||
unsigned int offset = (p->used - 1) % BN_CTX_POOL_SIZE;
|
||||
p->used -= num;
|
||||
while (num--) {
|
||||
bn_check_top(p->current->vals + offset);
|
||||
if (!offset) {
|
||||
offset = BN_CTX_POOL_SIZE - 1;
|
||||
p->current = p->current->prev;
|
||||
} else
|
||||
offset--;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/* crypto/bn/bn_depr.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2002 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Support for deprecated functions goes here - static linkage will only
|
||||
* slurp this code if applications are using them directly.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
#include <openssl/rand.h>
|
||||
|
||||
static void *dummy = &dummy;
|
||||
|
||||
#ifndef OPENSSL_NO_DEPRECATED
|
||||
BIGNUM *BN_generate_prime(BIGNUM *ret, int bits, int safe,
|
||||
const BIGNUM *add, const BIGNUM *rem,
|
||||
void (*callback) (int, int, void *), void *cb_arg)
|
||||
{
|
||||
BN_GENCB cb;
|
||||
BIGNUM *rnd = NULL;
|
||||
int found = 0;
|
||||
|
||||
BN_GENCB_set_old(&cb, callback, cb_arg);
|
||||
|
||||
if (ret == NULL) {
|
||||
if ((rnd = BN_new()) == NULL)
|
||||
goto err;
|
||||
} else
|
||||
rnd = ret;
|
||||
if (!BN_generate_prime_ex(rnd, bits, safe, add, rem, &cb))
|
||||
goto err;
|
||||
|
||||
/* we have a prime :-) */
|
||||
found = 1;
|
||||
err:
|
||||
if (!found && (ret == NULL) && (rnd != NULL))
|
||||
BN_free(rnd);
|
||||
return (found ? rnd : NULL);
|
||||
}
|
||||
|
||||
int BN_is_prime(const BIGNUM *a, int checks,
|
||||
void (*callback) (int, int, void *), BN_CTX *ctx_passed,
|
||||
void *cb_arg)
|
||||
{
|
||||
BN_GENCB cb;
|
||||
BN_GENCB_set_old(&cb, callback, cb_arg);
|
||||
return BN_is_prime_ex(a, checks, ctx_passed, &cb);
|
||||
}
|
||||
|
||||
int BN_is_prime_fasttest(const BIGNUM *a, int checks,
|
||||
void (*callback) (int, int, void *),
|
||||
BN_CTX *ctx_passed, void *cb_arg,
|
||||
int do_trial_division)
|
||||
{
|
||||
BN_GENCB cb;
|
||||
BN_GENCB_set_old(&cb, callback, cb_arg);
|
||||
return BN_is_prime_fasttest_ex(a, checks, ctx_passed,
|
||||
do_trial_division, &cb);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,691 @@
|
||||
/* crypto/bn/bn_div.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/bn.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
/* The old slow way */
|
||||
#if 0
|
||||
int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int i, nm, nd;
|
||||
int ret = 0;
|
||||
BIGNUM *D;
|
||||
|
||||
bn_check_top(m);
|
||||
bn_check_top(d);
|
||||
if (BN_is_zero(d)) {
|
||||
BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (BN_ucmp(m, d) < 0) {
|
||||
if (rem != NULL) {
|
||||
if (BN_copy(rem, m) == NULL)
|
||||
return (0);
|
||||
}
|
||||
if (dv != NULL)
|
||||
BN_zero(dv);
|
||||
return (1);
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
D = BN_CTX_get(ctx);
|
||||
if (dv == NULL)
|
||||
dv = BN_CTX_get(ctx);
|
||||
if (rem == NULL)
|
||||
rem = BN_CTX_get(ctx);
|
||||
if (D == NULL || dv == NULL || rem == NULL)
|
||||
goto end;
|
||||
|
||||
nd = BN_num_bits(d);
|
||||
nm = BN_num_bits(m);
|
||||
if (BN_copy(D, d) == NULL)
|
||||
goto end;
|
||||
if (BN_copy(rem, m) == NULL)
|
||||
goto end;
|
||||
|
||||
/*
|
||||
* The next 2 are needed so we can do a dv->d[0]|=1 later since
|
||||
* BN_lshift1 will only work once there is a value :-)
|
||||
*/
|
||||
BN_zero(dv);
|
||||
if (bn_wexpand(dv, 1) == NULL)
|
||||
goto end;
|
||||
dv->top = 1;
|
||||
|
||||
if (!BN_lshift(D, D, nm - nd))
|
||||
goto end;
|
||||
for (i = nm - nd; i >= 0; i--) {
|
||||
if (!BN_lshift1(dv, dv))
|
||||
goto end;
|
||||
if (BN_ucmp(rem, D) >= 0) {
|
||||
dv->d[0] |= 1;
|
||||
if (!BN_usub(rem, rem, D))
|
||||
goto end;
|
||||
}
|
||||
/* CAN IMPROVE (and have now :=) */
|
||||
if (!BN_rshift1(D, D))
|
||||
goto end;
|
||||
}
|
||||
rem->neg = BN_is_zero(rem) ? 0 : m->neg;
|
||||
dv->neg = m->neg ^ d->neg;
|
||||
ret = 1;
|
||||
end:
|
||||
BN_CTX_end(ctx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
# if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) \
|
||||
&& !defined(PEDANTIC) && !defined(BN_DIV3W)
|
||||
# if defined(__GNUC__) && __GNUC__>=2
|
||||
# if defined(__i386) || defined (__i386__)
|
||||
/*-
|
||||
* There were two reasons for implementing this template:
|
||||
* - GNU C generates a call to a function (__udivdi3 to be exact)
|
||||
* in reply to ((((BN_ULLONG)n0)<<BN_BITS2)|n1)/d0 (I fail to
|
||||
* understand why...);
|
||||
* - divl doesn't only calculate quotient, but also leaves
|
||||
* remainder in %edx which we can definitely use here:-)
|
||||
*
|
||||
* <appro@fy.chalmers.se>
|
||||
*/
|
||||
# define bn_div_words(n0,n1,d0) \
|
||||
({ asm volatile ( \
|
||||
"divl %4" \
|
||||
: "=a"(q), "=d"(rem) \
|
||||
: "a"(n1), "d"(n0), "g"(d0) \
|
||||
: "cc"); \
|
||||
q; \
|
||||
})
|
||||
# define REMAINDER_IS_ALREADY_CALCULATED
|
||||
# elif defined(__x86_64) && defined(SIXTY_FOUR_BIT_LONG)
|
||||
/*
|
||||
* Same story here, but it's 128-bit by 64-bit division. Wow!
|
||||
* <appro@fy.chalmers.se>
|
||||
*/
|
||||
# define bn_div_words(n0,n1,d0) \
|
||||
({ asm volatile ( \
|
||||
"divq %4" \
|
||||
: "=a"(q), "=d"(rem) \
|
||||
: "a"(n1), "d"(n0), "g"(d0) \
|
||||
: "cc"); \
|
||||
q; \
|
||||
})
|
||||
# define REMAINDER_IS_ALREADY_CALCULATED
|
||||
# endif /* __<cpu> */
|
||||
# endif /* __GNUC__ */
|
||||
# endif /* OPENSSL_NO_ASM */
|
||||
|
||||
/*-
|
||||
* BN_div[_no_branch] computes dv := num / divisor, rounding towards
|
||||
* zero, and sets up rm such that dv*divisor + rm = num holds.
|
||||
* Thus:
|
||||
* dv->neg == num->neg ^ divisor->neg (unless the result is zero)
|
||||
* rm->neg == num->neg (unless the remainder is zero)
|
||||
* If 'dv' or 'rm' is NULL, the respective value is not returned.
|
||||
*/
|
||||
static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
|
||||
const BIGNUM *divisor, BN_CTX *ctx);
|
||||
int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int norm_shift, i, loop;
|
||||
BIGNUM *tmp, wnum, *snum, *sdiv, *res;
|
||||
BN_ULONG *resp, *wnump;
|
||||
BN_ULONG d0, d1;
|
||||
int num_n, div_n;
|
||||
|
||||
/*
|
||||
* Invalid zero-padding would have particularly bad consequences in the
|
||||
* case of 'num', so don't just rely on bn_check_top() for this one
|
||||
* (bn_check_top() works only for BN_DEBUG builds)
|
||||
*/
|
||||
if (num->top > 0 && num->d[num->top - 1] == 0) {
|
||||
BNerr(BN_F_BN_DIV, BN_R_NOT_INITIALIZED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bn_check_top(num);
|
||||
|
||||
if ((BN_get_flags(num, BN_FLG_CONSTTIME) != 0)
|
||||
|| (BN_get_flags(divisor, BN_FLG_CONSTTIME) != 0)) {
|
||||
return BN_div_no_branch(dv, rm, num, divisor, ctx);
|
||||
}
|
||||
|
||||
bn_check_top(dv);
|
||||
bn_check_top(rm);
|
||||
/*- bn_check_top(num); *//*
|
||||
* 'num' has been checked already
|
||||
*/
|
||||
bn_check_top(divisor);
|
||||
|
||||
if (BN_is_zero(divisor)) {
|
||||
BNerr(BN_F_BN_DIV, BN_R_DIV_BY_ZERO);
|
||||
return (0);
|
||||
}
|
||||
|
||||
if (BN_ucmp(num, divisor) < 0) {
|
||||
if (rm != NULL) {
|
||||
if (BN_copy(rm, num) == NULL)
|
||||
return (0);
|
||||
}
|
||||
if (dv != NULL)
|
||||
BN_zero(dv);
|
||||
return (1);
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
snum = BN_CTX_get(ctx);
|
||||
sdiv = BN_CTX_get(ctx);
|
||||
if (dv == NULL)
|
||||
res = BN_CTX_get(ctx);
|
||||
else
|
||||
res = dv;
|
||||
if (sdiv == NULL || res == NULL || tmp == NULL || snum == NULL)
|
||||
goto err;
|
||||
|
||||
/* First we normalise the numbers */
|
||||
norm_shift = BN_BITS2 - ((BN_num_bits(divisor)) % BN_BITS2);
|
||||
if (!(BN_lshift(sdiv, divisor, norm_shift)))
|
||||
goto err;
|
||||
sdiv->neg = 0;
|
||||
norm_shift += BN_BITS2;
|
||||
if (!(BN_lshift(snum, num, norm_shift)))
|
||||
goto err;
|
||||
snum->neg = 0;
|
||||
div_n = sdiv->top;
|
||||
num_n = snum->top;
|
||||
loop = num_n - div_n;
|
||||
/*
|
||||
* Lets setup a 'window' into snum This is the part that corresponds to
|
||||
* the current 'area' being divided
|
||||
*/
|
||||
wnum.neg = 0;
|
||||
wnum.d = &(snum->d[loop]);
|
||||
wnum.top = div_n;
|
||||
/*
|
||||
* only needed when BN_ucmp messes up the values between top and max
|
||||
*/
|
||||
wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */
|
||||
|
||||
/* Get the top 2 words of sdiv */
|
||||
/* div_n=sdiv->top; */
|
||||
d0 = sdiv->d[div_n - 1];
|
||||
d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2];
|
||||
|
||||
/* pointer to the 'top' of snum */
|
||||
wnump = &(snum->d[num_n - 1]);
|
||||
|
||||
/* Setup to 'res' */
|
||||
res->neg = (num->neg ^ divisor->neg);
|
||||
if (!bn_wexpand(res, (loop + 1)))
|
||||
goto err;
|
||||
res->top = loop;
|
||||
resp = &(res->d[loop - 1]);
|
||||
|
||||
/* space for temp */
|
||||
if (!bn_wexpand(tmp, (div_n + 1)))
|
||||
goto err;
|
||||
|
||||
if (BN_ucmp(&wnum, sdiv) >= 0) {
|
||||
/*
|
||||
* If BN_DEBUG_RAND is defined BN_ucmp changes (via bn_pollute) the
|
||||
* const bignum arguments => clean the values between top and max
|
||||
* again
|
||||
*/
|
||||
bn_clear_top2max(&wnum);
|
||||
bn_sub_words(wnum.d, wnum.d, sdiv->d, div_n);
|
||||
*resp = 1;
|
||||
} else
|
||||
res->top--;
|
||||
/*
|
||||
* if res->top == 0 then clear the neg value otherwise decrease the resp
|
||||
* pointer
|
||||
*/
|
||||
if (res->top == 0)
|
||||
res->neg = 0;
|
||||
else
|
||||
resp--;
|
||||
|
||||
for (i = 0; i < loop - 1; i++, wnump--, resp--) {
|
||||
BN_ULONG q, l0;
|
||||
/*
|
||||
* the first part of the loop uses the top two words of snum and sdiv
|
||||
* to calculate a BN_ULONG q such that | wnum - sdiv * q | < sdiv
|
||||
*/
|
||||
# if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM)
|
||||
BN_ULONG bn_div_3_words(BN_ULONG *, BN_ULONG, BN_ULONG);
|
||||
q = bn_div_3_words(wnump, d1, d0);
|
||||
# else
|
||||
BN_ULONG n0, n1, rem = 0;
|
||||
|
||||
n0 = wnump[0];
|
||||
n1 = wnump[-1];
|
||||
if (n0 == d0)
|
||||
q = BN_MASK2;
|
||||
else { /* n0 < d0 */
|
||||
|
||||
# ifdef BN_LLONG
|
||||
BN_ULLONG t2;
|
||||
|
||||
# if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words)
|
||||
q = (BN_ULONG)(((((BN_ULLONG) n0) << BN_BITS2) | n1) / d0);
|
||||
# else
|
||||
q = bn_div_words(n0, n1, d0);
|
||||
# ifdef BN_DEBUG_LEVITTE
|
||||
fprintf(stderr, "DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
|
||||
X) -> 0x%08X\n", n0, n1, d0, q);
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef REMAINDER_IS_ALREADY_CALCULATED
|
||||
/*
|
||||
* rem doesn't have to be BN_ULLONG. The least we
|
||||
* know it's less that d0, isn't it?
|
||||
*/
|
||||
rem = (n1 - q * d0) & BN_MASK2;
|
||||
# endif
|
||||
t2 = (BN_ULLONG) d1 *q;
|
||||
|
||||
for (;;) {
|
||||
if (t2 <= ((((BN_ULLONG) rem) << BN_BITS2) | wnump[-2]))
|
||||
break;
|
||||
q--;
|
||||
rem += d0;
|
||||
if (rem < d0)
|
||||
break; /* don't let rem overflow */
|
||||
t2 -= d1;
|
||||
}
|
||||
# else /* !BN_LLONG */
|
||||
BN_ULONG t2l, t2h;
|
||||
# if !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
|
||||
BN_ULONG ql, qh;
|
||||
# endif
|
||||
|
||||
q = bn_div_words(n0, n1, d0);
|
||||
# ifdef BN_DEBUG_LEVITTE
|
||||
fprintf(stderr, "DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
|
||||
X) -> 0x%08X\n", n0, n1, d0, q);
|
||||
# endif
|
||||
# ifndef REMAINDER_IS_ALREADY_CALCULATED
|
||||
rem = (n1 - q * d0) & BN_MASK2;
|
||||
# endif
|
||||
|
||||
# if defined(BN_UMULT_LOHI)
|
||||
BN_UMULT_LOHI(t2l, t2h, d1, q);
|
||||
# elif defined(BN_UMULT_HIGH)
|
||||
t2l = d1 * q;
|
||||
t2h = BN_UMULT_HIGH(d1, q);
|
||||
# else
|
||||
t2l = LBITS(d1);
|
||||
t2h = HBITS(d1);
|
||||
ql = LBITS(q);
|
||||
qh = HBITS(q);
|
||||
mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */
|
||||
# endif
|
||||
|
||||
for (;;) {
|
||||
if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2])))
|
||||
break;
|
||||
q--;
|
||||
rem += d0;
|
||||
if (rem < d0)
|
||||
break; /* don't let rem overflow */
|
||||
if (t2l < d1)
|
||||
t2h--;
|
||||
t2l -= d1;
|
||||
}
|
||||
# endif /* !BN_LLONG */
|
||||
}
|
||||
# endif /* !BN_DIV3W */
|
||||
|
||||
l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q);
|
||||
tmp->d[div_n] = l0;
|
||||
wnum.d--;
|
||||
/*
|
||||
* ingore top values of the bignums just sub the two BN_ULONG arrays
|
||||
* with bn_sub_words
|
||||
*/
|
||||
if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) {
|
||||
/*
|
||||
* Note: As we have considered only the leading two BN_ULONGs in
|
||||
* the calculation of q, sdiv * q might be greater than wnum (but
|
||||
* then (q-1) * sdiv is less or equal than wnum)
|
||||
*/
|
||||
q--;
|
||||
if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n))
|
||||
/*
|
||||
* we can't have an overflow here (assuming that q != 0, but
|
||||
* if q == 0 then tmp is zero anyway)
|
||||
*/
|
||||
(*wnump)++;
|
||||
}
|
||||
/* store part of the result */
|
||||
*resp = q;
|
||||
}
|
||||
bn_correct_top(snum);
|
||||
if (rm != NULL) {
|
||||
/*
|
||||
* Keep a copy of the neg flag in num because if rm==num BN_rshift()
|
||||
* will overwrite it.
|
||||
*/
|
||||
int neg = num->neg;
|
||||
BN_rshift(rm, snum, norm_shift);
|
||||
if (!BN_is_zero(rm))
|
||||
rm->neg = neg;
|
||||
bn_check_top(rm);
|
||||
}
|
||||
BN_CTX_end(ctx);
|
||||
return (1);
|
||||
err:
|
||||
bn_check_top(rm);
|
||||
BN_CTX_end(ctx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* BN_div_no_branch is a special version of BN_div. It does not contain
|
||||
* branches that may leak sensitive information.
|
||||
*/
|
||||
static int BN_div_no_branch(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num,
|
||||
const BIGNUM *divisor, BN_CTX *ctx)
|
||||
{
|
||||
int norm_shift, i, loop;
|
||||
BIGNUM *tmp, wnum, *snum, *sdiv, *res;
|
||||
BN_ULONG *resp, *wnump;
|
||||
BN_ULONG d0, d1;
|
||||
int num_n, div_n;
|
||||
|
||||
bn_check_top(dv);
|
||||
bn_check_top(rm);
|
||||
/*- bn_check_top(num); *//*
|
||||
* 'num' has been checked in BN_div()
|
||||
*/
|
||||
bn_check_top(divisor);
|
||||
|
||||
if (BN_is_zero(divisor)) {
|
||||
BNerr(BN_F_BN_DIV_NO_BRANCH, BN_R_DIV_BY_ZERO);
|
||||
return (0);
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
snum = BN_CTX_get(ctx);
|
||||
sdiv = BN_CTX_get(ctx);
|
||||
if (dv == NULL)
|
||||
res = BN_CTX_get(ctx);
|
||||
else
|
||||
res = dv;
|
||||
if (sdiv == NULL || res == NULL)
|
||||
goto err;
|
||||
|
||||
/* First we normalise the numbers */
|
||||
norm_shift = BN_BITS2 - ((BN_num_bits(divisor)) % BN_BITS2);
|
||||
if (!(BN_lshift(sdiv, divisor, norm_shift)))
|
||||
goto err;
|
||||
sdiv->neg = 0;
|
||||
norm_shift += BN_BITS2;
|
||||
if (!(BN_lshift(snum, num, norm_shift)))
|
||||
goto err;
|
||||
snum->neg = 0;
|
||||
|
||||
/*
|
||||
* Since we don't know whether snum is larger than sdiv, we pad snum with
|
||||
* enough zeroes without changing its value.
|
||||
*/
|
||||
if (snum->top <= sdiv->top + 1) {
|
||||
if (bn_wexpand(snum, sdiv->top + 2) == NULL)
|
||||
goto err;
|
||||
for (i = snum->top; i < sdiv->top + 2; i++)
|
||||
snum->d[i] = 0;
|
||||
snum->top = sdiv->top + 2;
|
||||
} else {
|
||||
if (bn_wexpand(snum, snum->top + 1) == NULL)
|
||||
goto err;
|
||||
snum->d[snum->top] = 0;
|
||||
snum->top++;
|
||||
}
|
||||
|
||||
div_n = sdiv->top;
|
||||
num_n = snum->top;
|
||||
loop = num_n - div_n;
|
||||
/*
|
||||
* Lets setup a 'window' into snum This is the part that corresponds to
|
||||
* the current 'area' being divided
|
||||
*/
|
||||
wnum.neg = 0;
|
||||
wnum.d = &(snum->d[loop]);
|
||||
wnum.top = div_n;
|
||||
/*
|
||||
* only needed when BN_ucmp messes up the values between top and max
|
||||
*/
|
||||
wnum.dmax = snum->dmax - loop; /* so we don't step out of bounds */
|
||||
|
||||
/* Get the top 2 words of sdiv */
|
||||
/* div_n=sdiv->top; */
|
||||
d0 = sdiv->d[div_n - 1];
|
||||
d1 = (div_n == 1) ? 0 : sdiv->d[div_n - 2];
|
||||
|
||||
/* pointer to the 'top' of snum */
|
||||
wnump = &(snum->d[num_n - 1]);
|
||||
|
||||
/* Setup to 'res' */
|
||||
res->neg = (num->neg ^ divisor->neg);
|
||||
if (!bn_wexpand(res, (loop + 1)))
|
||||
goto err;
|
||||
res->top = loop - 1;
|
||||
resp = &(res->d[loop - 1]);
|
||||
|
||||
/* space for temp */
|
||||
if (!bn_wexpand(tmp, (div_n + 1)))
|
||||
goto err;
|
||||
|
||||
/*
|
||||
* if res->top == 0 then clear the neg value otherwise decrease the resp
|
||||
* pointer
|
||||
*/
|
||||
if (res->top == 0)
|
||||
res->neg = 0;
|
||||
else
|
||||
resp--;
|
||||
|
||||
for (i = 0; i < loop - 1; i++, wnump--, resp--) {
|
||||
BN_ULONG q, l0;
|
||||
/*
|
||||
* the first part of the loop uses the top two words of snum and sdiv
|
||||
* to calculate a BN_ULONG q such that | wnum - sdiv * q | < sdiv
|
||||
*/
|
||||
# if defined(BN_DIV3W) && !defined(OPENSSL_NO_ASM)
|
||||
BN_ULONG bn_div_3_words(BN_ULONG *, BN_ULONG, BN_ULONG);
|
||||
q = bn_div_3_words(wnump, d1, d0);
|
||||
# else
|
||||
BN_ULONG n0, n1, rem = 0;
|
||||
|
||||
n0 = wnump[0];
|
||||
n1 = wnump[-1];
|
||||
if (n0 == d0)
|
||||
q = BN_MASK2;
|
||||
else { /* n0 < d0 */
|
||||
|
||||
# ifdef BN_LLONG
|
||||
BN_ULLONG t2;
|
||||
|
||||
# if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words)
|
||||
q = (BN_ULONG)(((((BN_ULLONG) n0) << BN_BITS2) | n1) / d0);
|
||||
# else
|
||||
q = bn_div_words(n0, n1, d0);
|
||||
# ifdef BN_DEBUG_LEVITTE
|
||||
fprintf(stderr, "DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
|
||||
X) -> 0x%08X\n", n0, n1, d0, q);
|
||||
# endif
|
||||
# endif
|
||||
|
||||
# ifndef REMAINDER_IS_ALREADY_CALCULATED
|
||||
/*
|
||||
* rem doesn't have to be BN_ULLONG. The least we
|
||||
* know it's less that d0, isn't it?
|
||||
*/
|
||||
rem = (n1 - q * d0) & BN_MASK2;
|
||||
# endif
|
||||
t2 = (BN_ULLONG) d1 *q;
|
||||
|
||||
for (;;) {
|
||||
if (t2 <= ((((BN_ULLONG) rem) << BN_BITS2) | wnump[-2]))
|
||||
break;
|
||||
q--;
|
||||
rem += d0;
|
||||
if (rem < d0)
|
||||
break; /* don't let rem overflow */
|
||||
t2 -= d1;
|
||||
}
|
||||
# else /* !BN_LLONG */
|
||||
BN_ULONG t2l, t2h;
|
||||
# if !defined(BN_UMULT_LOHI) && !defined(BN_UMULT_HIGH)
|
||||
BN_ULONG ql, qh;
|
||||
# endif
|
||||
|
||||
q = bn_div_words(n0, n1, d0);
|
||||
# ifdef BN_DEBUG_LEVITTE
|
||||
fprintf(stderr, "DEBUG: bn_div_words(0x%08X,0x%08X,0x%08\
|
||||
X) -> 0x%08X\n", n0, n1, d0, q);
|
||||
# endif
|
||||
# ifndef REMAINDER_IS_ALREADY_CALCULATED
|
||||
rem = (n1 - q * d0) & BN_MASK2;
|
||||
# endif
|
||||
|
||||
# if defined(BN_UMULT_LOHI)
|
||||
BN_UMULT_LOHI(t2l, t2h, d1, q);
|
||||
# elif defined(BN_UMULT_HIGH)
|
||||
t2l = d1 * q;
|
||||
t2h = BN_UMULT_HIGH(d1, q);
|
||||
# else
|
||||
t2l = LBITS(d1);
|
||||
t2h = HBITS(d1);
|
||||
ql = LBITS(q);
|
||||
qh = HBITS(q);
|
||||
mul64(t2l, t2h, ql, qh); /* t2=(BN_ULLONG)d1*q; */
|
||||
# endif
|
||||
|
||||
for (;;) {
|
||||
if ((t2h < rem) || ((t2h == rem) && (t2l <= wnump[-2])))
|
||||
break;
|
||||
q--;
|
||||
rem += d0;
|
||||
if (rem < d0)
|
||||
break; /* don't let rem overflow */
|
||||
if (t2l < d1)
|
||||
t2h--;
|
||||
t2l -= d1;
|
||||
}
|
||||
# endif /* !BN_LLONG */
|
||||
}
|
||||
# endif /* !BN_DIV3W */
|
||||
|
||||
l0 = bn_mul_words(tmp->d, sdiv->d, div_n, q);
|
||||
tmp->d[div_n] = l0;
|
||||
wnum.d--;
|
||||
/*
|
||||
* ingore top values of the bignums just sub the two BN_ULONG arrays
|
||||
* with bn_sub_words
|
||||
*/
|
||||
if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) {
|
||||
/*
|
||||
* Note: As we have considered only the leading two BN_ULONGs in
|
||||
* the calculation of q, sdiv * q might be greater than wnum (but
|
||||
* then (q-1) * sdiv is less or equal than wnum)
|
||||
*/
|
||||
q--;
|
||||
if (bn_add_words(wnum.d, wnum.d, sdiv->d, div_n))
|
||||
/*
|
||||
* we can't have an overflow here (assuming that q != 0, but
|
||||
* if q == 0 then tmp is zero anyway)
|
||||
*/
|
||||
(*wnump)++;
|
||||
}
|
||||
/* store part of the result */
|
||||
*resp = q;
|
||||
}
|
||||
bn_correct_top(snum);
|
||||
if (rm != NULL) {
|
||||
/*
|
||||
* Keep a copy of the neg flag in num because if rm==num BN_rshift()
|
||||
* will overwrite it.
|
||||
*/
|
||||
int neg = num->neg;
|
||||
BN_rshift(rm, snum, norm_shift);
|
||||
if (!BN_is_zero(rm))
|
||||
rm->neg = neg;
|
||||
bn_check_top(rm);
|
||||
}
|
||||
bn_correct_top(res);
|
||||
BN_CTX_end(ctx);
|
||||
return (1);
|
||||
err:
|
||||
bn_check_top(rm);
|
||||
BN_CTX_end(ctx);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,154 @@
|
||||
/* crypto/bn/bn_err.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1999-2015 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* NOTE: this file was auto generated by the mkerr.pl script: any changes
|
||||
* made to it will be overwritten when the script next updates this file,
|
||||
* only reason strings will be preserved.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/* BEGIN ERROR CODES */
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
# define ERR_FUNC(func) ERR_PACK(ERR_LIB_BN,func,0)
|
||||
# define ERR_REASON(reason) ERR_PACK(ERR_LIB_BN,0,reason)
|
||||
|
||||
static ERR_STRING_DATA BN_str_functs[] = {
|
||||
{ERR_FUNC(BN_F_BNRAND), "BNRAND"},
|
||||
{ERR_FUNC(BN_F_BN_BLINDING_CONVERT_EX), "BN_BLINDING_convert_ex"},
|
||||
{ERR_FUNC(BN_F_BN_BLINDING_CREATE_PARAM), "BN_BLINDING_create_param"},
|
||||
{ERR_FUNC(BN_F_BN_BLINDING_INVERT_EX), "BN_BLINDING_invert_ex"},
|
||||
{ERR_FUNC(BN_F_BN_BLINDING_NEW), "BN_BLINDING_new"},
|
||||
{ERR_FUNC(BN_F_BN_BLINDING_UPDATE), "BN_BLINDING_update"},
|
||||
{ERR_FUNC(BN_F_BN_BN2DEC), "BN_bn2dec"},
|
||||
{ERR_FUNC(BN_F_BN_BN2HEX), "BN_bn2hex"},
|
||||
{ERR_FUNC(BN_F_BN_CTX_GET), "BN_CTX_get"},
|
||||
{ERR_FUNC(BN_F_BN_CTX_NEW), "BN_CTX_new"},
|
||||
{ERR_FUNC(BN_F_BN_CTX_START), "BN_CTX_start"},
|
||||
{ERR_FUNC(BN_F_BN_DIV), "BN_div"},
|
||||
{ERR_FUNC(BN_F_BN_DIV_NO_BRANCH), "BN_div_no_branch"},
|
||||
{ERR_FUNC(BN_F_BN_DIV_RECP), "BN_div_recp"},
|
||||
{ERR_FUNC(BN_F_BN_EXP), "BN_exp"},
|
||||
{ERR_FUNC(BN_F_BN_EXPAND2), "bn_expand2"},
|
||||
{ERR_FUNC(BN_F_BN_EXPAND_INTERNAL), "BN_EXPAND_INTERNAL"},
|
||||
{ERR_FUNC(BN_F_BN_GF2M_MOD), "BN_GF2m_mod"},
|
||||
{ERR_FUNC(BN_F_BN_GF2M_MOD_EXP), "BN_GF2m_mod_exp"},
|
||||
{ERR_FUNC(BN_F_BN_GF2M_MOD_MUL), "BN_GF2m_mod_mul"},
|
||||
{ERR_FUNC(BN_F_BN_GF2M_MOD_SOLVE_QUAD), "BN_GF2m_mod_solve_quad"},
|
||||
{ERR_FUNC(BN_F_BN_GF2M_MOD_SOLVE_QUAD_ARR), "BN_GF2m_mod_solve_quad_arr"},
|
||||
{ERR_FUNC(BN_F_BN_GF2M_MOD_SQR), "BN_GF2m_mod_sqr"},
|
||||
{ERR_FUNC(BN_F_BN_GF2M_MOD_SQRT), "BN_GF2m_mod_sqrt"},
|
||||
{ERR_FUNC(BN_F_BN_LSHIFT), "BN_lshift"},
|
||||
{ERR_FUNC(BN_F_BN_MOD_EXP2_MONT), "BN_mod_exp2_mont"},
|
||||
{ERR_FUNC(BN_F_BN_MOD_EXP_MONT), "BN_mod_exp_mont"},
|
||||
{ERR_FUNC(BN_F_BN_MOD_EXP_MONT_CONSTTIME), "BN_mod_exp_mont_consttime"},
|
||||
{ERR_FUNC(BN_F_BN_MOD_EXP_MONT_WORD), "BN_mod_exp_mont_word"},
|
||||
{ERR_FUNC(BN_F_BN_MOD_EXP_RECP), "BN_mod_exp_recp"},
|
||||
{ERR_FUNC(BN_F_BN_MOD_EXP_SIMPLE), "BN_mod_exp_simple"},
|
||||
{ERR_FUNC(BN_F_BN_MOD_INVERSE), "BN_mod_inverse"},
|
||||
{ERR_FUNC(BN_F_BN_MOD_INVERSE_NO_BRANCH), "BN_mod_inverse_no_branch"},
|
||||
{ERR_FUNC(BN_F_BN_MOD_LSHIFT_QUICK), "BN_mod_lshift_quick"},
|
||||
{ERR_FUNC(BN_F_BN_MOD_MUL_RECIPROCAL), "BN_mod_mul_reciprocal"},
|
||||
{ERR_FUNC(BN_F_BN_MOD_SQRT), "BN_mod_sqrt"},
|
||||
{ERR_FUNC(BN_F_BN_MPI2BN), "BN_mpi2bn"},
|
||||
{ERR_FUNC(BN_F_BN_NEW), "BN_new"},
|
||||
{ERR_FUNC(BN_F_BN_RAND), "BN_rand"},
|
||||
{ERR_FUNC(BN_F_BN_RAND_RANGE), "BN_rand_range"},
|
||||
{ERR_FUNC(BN_F_BN_RSHIFT), "BN_rshift"},
|
||||
{ERR_FUNC(BN_F_BN_USUB), "BN_usub"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
static ERR_STRING_DATA BN_str_reasons[] = {
|
||||
{ERR_REASON(BN_R_ARG2_LT_ARG3), "arg2 lt arg3"},
|
||||
{ERR_REASON(BN_R_BAD_RECIPROCAL), "bad reciprocal"},
|
||||
{ERR_REASON(BN_R_BIGNUM_TOO_LONG), "bignum too long"},
|
||||
{ERR_REASON(BN_R_BITS_TOO_SMALL), "bits too small"},
|
||||
{ERR_REASON(BN_R_CALLED_WITH_EVEN_MODULUS), "called with even modulus"},
|
||||
{ERR_REASON(BN_R_DIV_BY_ZERO), "div by zero"},
|
||||
{ERR_REASON(BN_R_ENCODING_ERROR), "encoding error"},
|
||||
{ERR_REASON(BN_R_EXPAND_ON_STATIC_BIGNUM_DATA),
|
||||
"expand on static bignum data"},
|
||||
{ERR_REASON(BN_R_INPUT_NOT_REDUCED), "input not reduced"},
|
||||
{ERR_REASON(BN_R_INVALID_LENGTH), "invalid length"},
|
||||
{ERR_REASON(BN_R_INVALID_RANGE), "invalid range"},
|
||||
{ERR_REASON(BN_R_INVALID_SHIFT), "invalid shift"},
|
||||
{ERR_REASON(BN_R_NOT_A_SQUARE), "not a square"},
|
||||
{ERR_REASON(BN_R_NOT_INITIALIZED), "not initialized"},
|
||||
{ERR_REASON(BN_R_NO_INVERSE), "no inverse"},
|
||||
{ERR_REASON(BN_R_NO_SOLUTION), "no solution"},
|
||||
{ERR_REASON(BN_R_P_IS_NOT_PRIME), "p is not prime"},
|
||||
{ERR_REASON(BN_R_TOO_MANY_ITERATIONS), "too many iterations"},
|
||||
{ERR_REASON(BN_R_TOO_MANY_TEMPORARY_VARIABLES),
|
||||
"too many temporary variables"},
|
||||
{0, NULL}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void ERR_load_BN_strings(void)
|
||||
{
|
||||
#ifndef OPENSSL_NO_ERR
|
||||
|
||||
if (ERR_func_error_string(BN_str_functs[0].error) == NULL) {
|
||||
ERR_load_strings(0, BN_str_functs);
|
||||
ERR_load_strings(0, BN_str_reasons);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -0,0 +1,999 @@
|
||||
/* crypto/bn/bn_exp.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
/* maximum precomputation table size for *variable* sliding windows */
|
||||
#define TABLE_SIZE 32
|
||||
|
||||
/* this one works - simple but works */
|
||||
int BN_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
|
||||
{
|
||||
int i, bits, ret = 0;
|
||||
BIGNUM *v, *rr;
|
||||
|
||||
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
|
||||
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
|
||||
BNerr(BN_F_BN_EXP, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if ((r == a) || (r == p))
|
||||
rr = BN_CTX_get(ctx);
|
||||
else
|
||||
rr = r;
|
||||
v = BN_CTX_get(ctx);
|
||||
if (rr == NULL || v == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_copy(v, a) == NULL)
|
||||
goto err;
|
||||
bits = BN_num_bits(p);
|
||||
|
||||
if (BN_is_odd(p)) {
|
||||
if (BN_copy(rr, a) == NULL)
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_one(rr))
|
||||
goto err;
|
||||
}
|
||||
|
||||
for (i = 1; i < bits; i++) {
|
||||
if (!BN_sqr(v, v, ctx))
|
||||
goto err;
|
||||
if (BN_is_bit_set(p, i)) {
|
||||
if (!BN_mul(rr, rr, v, ctx))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
if (r != rr)
|
||||
BN_copy(r, rr);
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(r);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int ret;
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(p);
|
||||
bn_check_top(m);
|
||||
|
||||
/* For even modulus m = 2^k*m_odd, it might make sense to compute
|
||||
* a^p mod m_odd and a^p mod 2^k separately (with Montgomery
|
||||
* exponentiation for the odd part), using appropriate exponent
|
||||
* reductions, and combine the results using the CRT.
|
||||
*
|
||||
* For now, we use Montgomery only if the modulus is odd; otherwise,
|
||||
* exponentiation using the reciprocal-based quick remaindering
|
||||
* algorithm is used.
|
||||
*
|
||||
* (Timing obtained with expspeed.c [computations a^p mod m
|
||||
* where a, p, m are of the same length: 256, 512, 1024, 2048,
|
||||
* 4096, 8192 bits], compared to the running time of the
|
||||
* standard algorithm:
|
||||
*
|
||||
* BN_mod_exp_mont 33 .. 40 % [AMD K6-2, Linux, debug configuration]
|
||||
* 55 .. 77 % [UltraSparc processor, but
|
||||
* debug-solaris-sparcv8-gcc conf.]
|
||||
*
|
||||
* BN_mod_exp_recp 50 .. 70 % [AMD K6-2, Linux, debug configuration]
|
||||
* 62 .. 118 % [UltraSparc, debug-solaris-sparcv8-gcc]
|
||||
*
|
||||
* On the Sparc, BN_mod_exp_recp was faster than BN_mod_exp_mont
|
||||
* at 2048 and more bits, but at 512 and 1024 bits, it was
|
||||
* slower even than the standard algorithm!
|
||||
*
|
||||
* "Real" timings [linux-elf, solaris-sparcv9-gcc configurations]
|
||||
* should be obtained when the new Montgomery reduction code
|
||||
* has been integrated into OpenSSL.)
|
||||
*/
|
||||
|
||||
#define MONT_MUL_MOD
|
||||
#define MONT_EXP_WORD
|
||||
#define RECP_MUL_MOD
|
||||
|
||||
#ifdef MONT_MUL_MOD
|
||||
/*
|
||||
* I have finally been able to take out this pre-condition of the top bit
|
||||
* being set. It was caused by an error in BN_div with negatives. There
|
||||
* was also another problem when for a^b%m a >= m. eay 07-May-97
|
||||
*/
|
||||
/* if ((m->d[m->top-1]&BN_TBIT) && BN_is_odd(m)) */
|
||||
|
||||
if (BN_is_odd(m)) {
|
||||
# ifdef MONT_EXP_WORD
|
||||
if (a->top == 1 && !a->neg
|
||||
&& (BN_get_flags(p, BN_FLG_CONSTTIME) == 0)) {
|
||||
BN_ULONG A = a->d[0];
|
||||
ret = BN_mod_exp_mont_word(r, A, p, m, ctx, NULL);
|
||||
} else
|
||||
# endif
|
||||
ret = BN_mod_exp_mont(r, a, p, m, ctx, NULL);
|
||||
} else
|
||||
#endif
|
||||
#ifdef RECP_MUL_MOD
|
||||
{
|
||||
ret = BN_mod_exp_recp(r, a, p, m, ctx);
|
||||
}
|
||||
#else
|
||||
{
|
||||
ret = BN_mod_exp_simple(r, a, p, m, ctx);
|
||||
}
|
||||
#endif
|
||||
|
||||
bn_check_top(r);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int BN_mod_exp_recp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx)
|
||||
{
|
||||
int i,j,bits,ret=0,wstart,wend,window,wvalue;
|
||||
int start=1;
|
||||
BIGNUM *aa;
|
||||
/* Table of variables obtained from 'ctx' */
|
||||
BIGNUM *val[TABLE_SIZE];
|
||||
BN_RECP_CTX recp;
|
||||
|
||||
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0)
|
||||
{
|
||||
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
|
||||
BNerr(BN_F_BN_MOD_EXP_RECP,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bits=BN_num_bits(p);
|
||||
|
||||
if (bits == 0)
|
||||
{
|
||||
ret = BN_one(r);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
aa = BN_CTX_get(ctx);
|
||||
val[0] = BN_CTX_get(ctx);
|
||||
if(!aa || !val[0]) goto err;
|
||||
|
||||
BN_RECP_CTX_init(&recp);
|
||||
if (m->neg)
|
||||
{
|
||||
/* ignore sign of 'm' */
|
||||
if (!BN_copy(aa, m)) goto err;
|
||||
aa->neg = 0;
|
||||
if (BN_RECP_CTX_set(&recp,aa,ctx) <= 0) goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BN_RECP_CTX_set(&recp,m,ctx) <= 0) goto err;
|
||||
}
|
||||
|
||||
if (!BN_nnmod(val[0],a,m,ctx)) goto err; /* 1 */
|
||||
if (BN_is_zero(val[0]))
|
||||
{
|
||||
BN_zero(r);
|
||||
ret = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
window = BN_window_bits_for_exponent_size(bits);
|
||||
if (window > 1)
|
||||
{
|
||||
if (!BN_mod_mul_reciprocal(aa,val[0],val[0],&recp,ctx))
|
||||
goto err; /* 2 */
|
||||
j=1<<(window-1);
|
||||
for (i=1; i<j; i++)
|
||||
{
|
||||
if(((val[i] = BN_CTX_get(ctx)) == NULL) ||
|
||||
!BN_mod_mul_reciprocal(val[i],val[i-1],
|
||||
aa,&recp,ctx))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
start=1; /* This is used to avoid multiplication etc
|
||||
* when there is only the value '1' in the
|
||||
* buffer. */
|
||||
wvalue=0; /* The 'value' of the window */
|
||||
wstart=bits-1; /* The top bit of the window */
|
||||
wend=0; /* The bottom bit of the window */
|
||||
|
||||
if (!BN_one(r)) goto err;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (BN_is_bit_set(p,wstart) == 0)
|
||||
{
|
||||
if (!start)
|
||||
if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
|
||||
goto err;
|
||||
if (wstart == 0) break;
|
||||
wstart--;
|
||||
continue;
|
||||
}
|
||||
/* We now have wstart on a 'set' bit, we now need to work out
|
||||
* how bit a window to do. To do this we need to scan
|
||||
* forward until the last set bit before the end of the
|
||||
* window */
|
||||
j=wstart;
|
||||
wvalue=1;
|
||||
wend=0;
|
||||
for (i=1; i<window; i++)
|
||||
{
|
||||
if (wstart-i < 0) break;
|
||||
if (BN_is_bit_set(p,wstart-i))
|
||||
{
|
||||
wvalue<<=(i-wend);
|
||||
wvalue|=1;
|
||||
wend=i;
|
||||
}
|
||||
}
|
||||
|
||||
/* wend is the size of the current window */
|
||||
j=wend+1;
|
||||
/* add the 'bytes above' */
|
||||
if (!start)
|
||||
for (i=0; i<j; i++)
|
||||
{
|
||||
if (!BN_mod_mul_reciprocal(r,r,r,&recp,ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* wvalue will be an odd number < 2^window */
|
||||
if (!BN_mod_mul_reciprocal(r,r,val[wvalue>>1],&recp,ctx))
|
||||
goto err;
|
||||
|
||||
/* move the 'window' down further */
|
||||
wstart-=wend+1;
|
||||
wvalue=0;
|
||||
start=0;
|
||||
if (wstart < 0) break;
|
||||
}
|
||||
ret=1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
BN_RECP_CTX_free(&recp);
|
||||
bn_check_top(r);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
|
||||
{
|
||||
int i,j,bits,ret=0,wstart,wend,window,wvalue;
|
||||
int start=1;
|
||||
BIGNUM *d,*r;
|
||||
const BIGNUM *aa;
|
||||
/* Table of variables obtained from 'ctx' */
|
||||
BIGNUM *val[TABLE_SIZE];
|
||||
BN_MONT_CTX *mont=NULL;
|
||||
|
||||
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0)
|
||||
{
|
||||
return BN_mod_exp_mont_consttime(rr, a, p, m, ctx, in_mont);
|
||||
}
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(p);
|
||||
bn_check_top(m);
|
||||
|
||||
if (!BN_is_odd(m))
|
||||
{
|
||||
BNerr(BN_F_BN_MOD_EXP_MONT,BN_R_CALLED_WITH_EVEN_MODULUS);
|
||||
return(0);
|
||||
}
|
||||
bits=BN_num_bits(p);
|
||||
if (bits == 0)
|
||||
{
|
||||
ret = BN_one(rr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
d = BN_CTX_get(ctx);
|
||||
r = BN_CTX_get(ctx);
|
||||
val[0] = BN_CTX_get(ctx);
|
||||
if (!d || !r || !val[0]) goto err;
|
||||
|
||||
/* If this is not done, things will break in the montgomery
|
||||
* part */
|
||||
|
||||
if (in_mont != NULL)
|
||||
mont=in_mont;
|
||||
else
|
||||
{
|
||||
if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
|
||||
if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
|
||||
}
|
||||
|
||||
if (a->neg || BN_ucmp(a,m) >= 0)
|
||||
{
|
||||
if (!BN_nnmod(val[0],a,m,ctx))
|
||||
goto err;
|
||||
aa= val[0];
|
||||
}
|
||||
else
|
||||
aa=a;
|
||||
if (BN_is_zero(aa))
|
||||
{
|
||||
BN_zero(rr);
|
||||
ret = 1;
|
||||
goto err;
|
||||
}
|
||||
if (!BN_to_montgomery(val[0],aa,mont,ctx)) goto err; /* 1 */
|
||||
|
||||
window = BN_window_bits_for_exponent_size(bits);
|
||||
if (window > 1)
|
||||
{
|
||||
if (!BN_mod_mul_montgomery(d,val[0],val[0],mont,ctx)) goto err; /* 2 */
|
||||
j=1<<(window-1);
|
||||
for (i=1; i<j; i++)
|
||||
{
|
||||
if(((val[i] = BN_CTX_get(ctx)) == NULL) ||
|
||||
!BN_mod_mul_montgomery(val[i],val[i-1],
|
||||
d,mont,ctx))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
start=1; /* This is used to avoid multiplication etc
|
||||
* when there is only the value '1' in the
|
||||
* buffer. */
|
||||
wvalue=0; /* The 'value' of the window */
|
||||
wstart=bits-1; /* The top bit of the window */
|
||||
wend=0; /* The bottom bit of the window */
|
||||
|
||||
if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
|
||||
for (;;)
|
||||
{
|
||||
if (BN_is_bit_set(p,wstart) == 0)
|
||||
{
|
||||
if (!start)
|
||||
{
|
||||
if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
|
||||
goto err;
|
||||
}
|
||||
if (wstart == 0) break;
|
||||
wstart--;
|
||||
continue;
|
||||
}
|
||||
/* We now have wstart on a 'set' bit, we now need to work out
|
||||
* how bit a window to do. To do this we need to scan
|
||||
* forward until the last set bit before the end of the
|
||||
* window */
|
||||
j=wstart;
|
||||
wvalue=1;
|
||||
wend=0;
|
||||
for (i=1; i<window; i++)
|
||||
{
|
||||
if (wstart-i < 0) break;
|
||||
if (BN_is_bit_set(p,wstart-i))
|
||||
{
|
||||
wvalue<<=(i-wend);
|
||||
wvalue|=1;
|
||||
wend=i;
|
||||
}
|
||||
}
|
||||
|
||||
/* wend is the size of the current window */
|
||||
j=wend+1;
|
||||
/* add the 'bytes above' */
|
||||
if (!start)
|
||||
for (i=0; i<j; i++)
|
||||
{
|
||||
if (!BN_mod_mul_montgomery(r,r,r,mont,ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* wvalue will be an odd number < 2^window */
|
||||
if (!BN_mod_mul_montgomery(r,r,val[wvalue>>1],mont,ctx))
|
||||
goto err;
|
||||
|
||||
/* move the 'window' down further */
|
||||
wstart-=wend+1;
|
||||
wvalue=0;
|
||||
start=0;
|
||||
if (wstart < 0) break;
|
||||
}
|
||||
if (!BN_from_montgomery(rr,r,mont,ctx)) goto err;
|
||||
ret=1;
|
||||
err:
|
||||
if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(rr);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* BN_mod_exp_mont_consttime() stores the precomputed powers in a specific layout
|
||||
* so that accessing any of these table values shows the same access pattern as far
|
||||
* as cache lines are concerned. The following functions are used to transfer a BIGNUM
|
||||
* from/to that table. */
|
||||
|
||||
static int MOD_EXP_CTIME_COPY_TO_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, int width)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
if (bn_wexpand(b, top) == NULL)
|
||||
return 0;
|
||||
while (b->top < top)
|
||||
{
|
||||
b->d[b->top++] = 0;
|
||||
}
|
||||
|
||||
for (i = 0, j=idx; i < top * sizeof b->d[0]; i++, j+=width)
|
||||
{
|
||||
buf[j] = ((unsigned char*)b->d)[i];
|
||||
}
|
||||
|
||||
bn_correct_top(b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, unsigned char *buf, int idx, int width)
|
||||
{
|
||||
size_t i, j;
|
||||
|
||||
if (bn_wexpand(b, top) == NULL)
|
||||
return 0;
|
||||
|
||||
for (i=0, j=idx; i < top * sizeof b->d[0]; i++, j+=width)
|
||||
{
|
||||
((unsigned char*)b->d)[i] = buf[j];
|
||||
}
|
||||
|
||||
b->top = top;
|
||||
bn_correct_top(b);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Given a pointer value, compute the next address that is a cache line
|
||||
* multiple.
|
||||
*/
|
||||
#define MOD_EXP_CTIME_ALIGN(x_) \
|
||||
((unsigned char*)(x_) + (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - (((BN_ULONG)(x_)) & (MOD_EXP_CTIME_MIN_CACHE_LINE_MASK))))
|
||||
|
||||
/*
|
||||
* This variant of BN_mod_exp_mont() uses fixed windows and the special
|
||||
* precomputation memory layout to limit data-dependency to a minimum to
|
||||
* protect secret exponents (cf. the hyper-threading timing attacks pointed
|
||||
* out by Colin Percival,
|
||||
* http://www.daemong-consideredperthreading-considered-harmful/)
|
||||
*/
|
||||
int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
|
||||
{
|
||||
int i,bits,ret=0,idx,window,wvalue;
|
||||
int top;
|
||||
BIGNUM *r;
|
||||
const BIGNUM *aa;
|
||||
BN_MONT_CTX *mont=NULL;
|
||||
|
||||
int numPowers;
|
||||
unsigned char *powerbufFree=NULL;
|
||||
int powerbufLen = 0;
|
||||
unsigned char *powerbuf=NULL;
|
||||
BIGNUM *computeTemp=NULL, *am=NULL;
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(p);
|
||||
bn_check_top(m);
|
||||
|
||||
top = m->top;
|
||||
|
||||
if (!(m->d[0] & 1))
|
||||
{
|
||||
BNerr(BN_F_BN_MOD_EXP_MONT_CONSTTIME,BN_R_CALLED_WITH_EVEN_MODULUS);
|
||||
return(0);
|
||||
}
|
||||
bits=BN_num_bits(p);
|
||||
if (bits == 0)
|
||||
{
|
||||
ret = BN_one(rr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Initialize BIGNUM context and allocate intermediate result */
|
||||
BN_CTX_start(ctx);
|
||||
r = BN_CTX_get(ctx);
|
||||
if (r == NULL) goto err;
|
||||
|
||||
/* Allocate a montgomery context if it was not supplied by the caller.
|
||||
* If this is not done, things will break in the montgomery part.
|
||||
*/
|
||||
if (in_mont != NULL)
|
||||
mont=in_mont;
|
||||
else
|
||||
{
|
||||
if ((mont=BN_MONT_CTX_new()) == NULL) goto err;
|
||||
if (!BN_MONT_CTX_set(mont,m,ctx)) goto err;
|
||||
}
|
||||
|
||||
/* Get the window size to use with size of p. */
|
||||
window = BN_window_bits_for_ctime_exponent_size(bits);
|
||||
|
||||
/* Allocate a buffer large enough to hold all of the pre-computed
|
||||
* powers of a.
|
||||
*/
|
||||
numPowers = 1 << window;
|
||||
powerbufLen = sizeof(m->d[0])*top*numPowers;
|
||||
if ((powerbufFree=(unsigned char*)OPENSSL_malloc(powerbufLen+MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH)) == NULL)
|
||||
goto err;
|
||||
|
||||
powerbuf = MOD_EXP_CTIME_ALIGN(powerbufFree);
|
||||
memset(powerbuf, 0, powerbufLen);
|
||||
|
||||
/* Initialize the intermediate result. Do this early to save double conversion,
|
||||
* once each for a^0 and intermediate result.
|
||||
*/
|
||||
if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
|
||||
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(r, top, powerbuf, 0, numPowers)) goto err;
|
||||
|
||||
/* Initialize computeTemp as a^1 with montgomery precalcs */
|
||||
computeTemp = BN_CTX_get(ctx);
|
||||
am = BN_CTX_get(ctx);
|
||||
if (computeTemp==NULL || am==NULL) goto err;
|
||||
|
||||
if (a->neg || BN_ucmp(a,m) >= 0)
|
||||
{
|
||||
if (!BN_mod(am,a,m,ctx))
|
||||
goto err;
|
||||
aa= am;
|
||||
}
|
||||
else
|
||||
aa=a;
|
||||
if (!BN_to_montgomery(am,aa,mont,ctx)) goto err;
|
||||
if (!BN_copy(computeTemp, am)) goto err;
|
||||
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(am, top, powerbuf, 1, numPowers)) goto err;
|
||||
|
||||
/* If the window size is greater than 1, then calculate
|
||||
* val[i=2..2^winsize-1]. Powers are computed as a*a^(i-1)
|
||||
* (even powers could instead be computed as (a^(i/2))^2
|
||||
* to use the slight performance advantage of sqr over mul).
|
||||
*/
|
||||
if (window > 1)
|
||||
{
|
||||
for (i=2; i<numPowers; i++)
|
||||
{
|
||||
/* Calculate a^i = a^(i-1) * a */
|
||||
if (!BN_mod_mul_montgomery(computeTemp,am,computeTemp,mont,ctx))
|
||||
goto err;
|
||||
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(computeTemp, top, powerbuf, i, numPowers)) goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjust the number of bits up to a multiple of the window size.
|
||||
* If the exponent length is not a multiple of the window size, then
|
||||
* this pads the most significant bits with zeros to normalize the
|
||||
* scanning loop to there's no special cases.
|
||||
*
|
||||
* * NOTE: Making the window size a power of two less than the native
|
||||
* * word size ensures that the padded bits won't go past the last
|
||||
* * word in the internal BIGNUM structure. Going past the end will
|
||||
* * still produce the correct result, but causes a different branch
|
||||
* * to be taken in the BN_is_bit_set function.
|
||||
*/
|
||||
bits = ((bits+window-1)/window)*window;
|
||||
idx=bits-1; /* The top bit of the window */
|
||||
|
||||
/* Scan the exponent one window at a time starting from the most
|
||||
* significant bits.
|
||||
*/
|
||||
while (idx >= 0)
|
||||
{
|
||||
wvalue=0; /* The 'value' of the window */
|
||||
|
||||
/* Scan the window, squaring the result as we go */
|
||||
for (i=0; i<window; i++,idx--)
|
||||
{
|
||||
if (!BN_mod_mul_montgomery(r,r,r,mont,ctx)) goto err;
|
||||
wvalue = (wvalue<<1)+BN_is_bit_set(p,idx);
|
||||
}
|
||||
|
||||
/* Fetch the appropriate pre-computed value from the pre-buf */
|
||||
if (!MOD_EXP_CTIME_COPY_FROM_PREBUF(computeTemp, top, powerbuf, wvalue, numPowers)) goto err;
|
||||
|
||||
/* Multiply the result into the intermediate result */
|
||||
if (!BN_mod_mul_montgomery(r,r,computeTemp,mont,ctx)) goto err;
|
||||
}
|
||||
|
||||
/* Convert the final result from montgomery to standard format */
|
||||
if (!BN_from_montgomery(rr,r,mont,ctx)) goto err;
|
||||
ret=1;
|
||||
err:
|
||||
if ((in_mont == NULL) && (mont != NULL)) BN_MONT_CTX_free(mont);
|
||||
if (powerbuf!=NULL)
|
||||
{
|
||||
OPENSSL_cleanse(powerbuf,powerbufLen);
|
||||
OPENSSL_free(powerbufFree);
|
||||
}
|
||||
if (am!=NULL) BN_clear(am);
|
||||
if (computeTemp!=NULL) BN_clear(computeTemp);
|
||||
BN_CTX_end(ctx);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx, BN_MONT_CTX *in_mont)
|
||||
{
|
||||
BN_MONT_CTX *mont = NULL;
|
||||
int b, bits, ret = 0;
|
||||
int r_is_one;
|
||||
BN_ULONG w, next_w;
|
||||
BIGNUM *d, *r, *t;
|
||||
BIGNUM *swap_tmp;
|
||||
#define BN_MOD_MUL_WORD(r, w, m) \
|
||||
(BN_mul_word(r, (w)) && \
|
||||
(/* BN_ucmp(r, (m)) < 0 ? 1 :*/ \
|
||||
(BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1))))
|
||||
/*
|
||||
* BN_MOD_MUL_WORD is only used with 'w' large, so the BN_ucmp test is
|
||||
* probably more overhead than always using BN_mod (which uses BN_copy if
|
||||
* a similar test returns true).
|
||||
*/
|
||||
/*
|
||||
* We can use BN_mod and do not need BN_nnmod because our accumulator is
|
||||
* never negative (the result of BN_mod does not depend on the sign of
|
||||
* the modulus).
|
||||
*/
|
||||
#define BN_TO_MONTGOMERY_WORD(r, w, mont) \
|
||||
(BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))
|
||||
|
||||
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
|
||||
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
|
||||
BNerr(BN_F_BN_MOD_EXP_MONT_WORD, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bn_check_top(p);
|
||||
bn_check_top(m);
|
||||
|
||||
if (!BN_is_odd(m)) {
|
||||
BNerr(BN_F_BN_MOD_EXP_MONT_WORD, BN_R_CALLED_WITH_EVEN_MODULUS);
|
||||
return (0);
|
||||
}
|
||||
if (m->top == 1)
|
||||
a %= m->d[0]; /* make sure that 'a' is reduced */
|
||||
|
||||
bits = BN_num_bits(p);
|
||||
if (bits == 0) {
|
||||
/* x**0 mod 1 is still zero. */
|
||||
if (BN_is_one(m)) {
|
||||
ret = 1;
|
||||
BN_zero(rr);
|
||||
} else
|
||||
ret = BN_one(rr);
|
||||
return ret;
|
||||
}
|
||||
if (a == 0) {
|
||||
BN_zero(rr);
|
||||
ret = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
d = BN_CTX_get(ctx);
|
||||
r = BN_CTX_get(ctx);
|
||||
t = BN_CTX_get(ctx);
|
||||
if (d == NULL || r == NULL || t == NULL)
|
||||
goto err;
|
||||
|
||||
if (in_mont != NULL)
|
||||
mont = in_mont;
|
||||
else {
|
||||
if ((mont = BN_MONT_CTX_new()) == NULL)
|
||||
goto err;
|
||||
if (!BN_MONT_CTX_set(mont, m, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
r_is_one = 1; /* except for Montgomery factor */
|
||||
|
||||
/* bits-1 >= 0 */
|
||||
|
||||
/* The result is accumulated in the product r*w. */
|
||||
w = a; /* bit 'bits-1' of 'p' is always set */
|
||||
for (b = bits - 2; b >= 0; b--) {
|
||||
/* First, square r*w. */
|
||||
next_w = w * w;
|
||||
if ((next_w / w) != w) { /* overflow */
|
||||
if (r_is_one) {
|
||||
if (!BN_TO_MONTGOMERY_WORD(r, w, mont))
|
||||
goto err;
|
||||
r_is_one = 0;
|
||||
} else {
|
||||
if (!BN_MOD_MUL_WORD(r, w, m))
|
||||
goto err;
|
||||
}
|
||||
next_w = 1;
|
||||
}
|
||||
w = next_w;
|
||||
if (!r_is_one) {
|
||||
if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Second, multiply r*w by 'a' if exponent bit is set. */
|
||||
if (BN_is_bit_set(p, b)) {
|
||||
next_w = w * a;
|
||||
if ((next_w / a) != w) { /* overflow */
|
||||
if (r_is_one) {
|
||||
if (!BN_TO_MONTGOMERY_WORD(r, w, mont))
|
||||
goto err;
|
||||
r_is_one = 0;
|
||||
} else {
|
||||
if (!BN_MOD_MUL_WORD(r, w, m))
|
||||
goto err;
|
||||
}
|
||||
next_w = a;
|
||||
}
|
||||
w = next_w;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, set r:=r*w. */
|
||||
if (w != 1) {
|
||||
if (r_is_one) {
|
||||
if (!BN_TO_MONTGOMERY_WORD(r, w, mont))
|
||||
goto err;
|
||||
r_is_one = 0;
|
||||
} else {
|
||||
if (!BN_MOD_MUL_WORD(r, w, m))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
if (r_is_one) { /* can happen only if a == 1 */
|
||||
if (!BN_one(rr))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_from_montgomery(rr, r, mont, ctx))
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
if ((in_mont == NULL) && (mont != NULL))
|
||||
BN_MONT_CTX_free(mont);
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(rr);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* The old fallback, simple version :-) */
|
||||
int BN_mod_exp_simple(BIGNUM *r, const BIGNUM *a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx)
|
||||
{
|
||||
int i,j,bits,ret=0,wstart,wend,window,wvalue;
|
||||
int start=1;
|
||||
BIGNUM *d;
|
||||
/* Table of variables obtained from 'ctx' */
|
||||
BIGNUM *val[TABLE_SIZE];
|
||||
|
||||
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0)
|
||||
{
|
||||
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
|
||||
BNerr(BN_F_BN_MOD_EXP_SIMPLE,ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return -1;
|
||||
}
|
||||
|
||||
bits=BN_num_bits(p);
|
||||
|
||||
if (bits == 0)
|
||||
{
|
||||
ret = BN_one(r);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
d = BN_CTX_get(ctx);
|
||||
val[0] = BN_CTX_get(ctx);
|
||||
if(!d || !val[0]) goto err;
|
||||
|
||||
if (!BN_nnmod(val[0],a,m,ctx)) goto err; /* 1 */
|
||||
if (BN_is_zero(val[0]))
|
||||
{
|
||||
BN_zero(r);
|
||||
ret = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
window = BN_window_bits_for_exponent_size(bits);
|
||||
if (window > 1)
|
||||
{
|
||||
if (!BN_mod_mul(d,val[0],val[0],m,ctx))
|
||||
goto err; /* 2 */
|
||||
j=1<<(window-1);
|
||||
for (i=1; i<j; i++)
|
||||
{
|
||||
if(((val[i] = BN_CTX_get(ctx)) == NULL) ||
|
||||
!BN_mod_mul(val[i],val[i-1],d,m,ctx))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
start=1; /* This is used to avoid multiplication etc
|
||||
* when there is only the value '1' in the
|
||||
* buffer. */
|
||||
wvalue=0; /* The 'value' of the window */
|
||||
wstart=bits-1; /* The top bit of the window */
|
||||
wend=0; /* The bottom bit of the window */
|
||||
|
||||
if (!BN_one(r)) goto err;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (BN_is_bit_set(p,wstart) == 0)
|
||||
{
|
||||
if (!start)
|
||||
if (!BN_mod_mul(r,r,r,m,ctx))
|
||||
goto err;
|
||||
if (wstart == 0) break;
|
||||
wstart--;
|
||||
continue;
|
||||
}
|
||||
/* We now have wstart on a 'set' bit, we now need to work out
|
||||
* how bit a window to do. To do this we need to scan
|
||||
* forward until the last set bit before the end of the
|
||||
* window */
|
||||
j=wstart;
|
||||
wvalue=1;
|
||||
wend=0;
|
||||
for (i=1; i<window; i++)
|
||||
{
|
||||
if (wstart-i < 0) break;
|
||||
if (BN_is_bit_set(p,wstart-i))
|
||||
{
|
||||
wvalue<<=(i-wend);
|
||||
wvalue|=1;
|
||||
wend=i;
|
||||
}
|
||||
}
|
||||
|
||||
/* wend is the size of the current window */
|
||||
j=wend+1;
|
||||
/* add the 'bytes above' */
|
||||
if (!start)
|
||||
for (i=0; i<j; i++)
|
||||
{
|
||||
if (!BN_mod_mul(r,r,r,m,ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* wvalue will be an odd number < 2^window */
|
||||
if (!BN_mod_mul(r,r,val[wvalue>>1],m,ctx))
|
||||
goto err;
|
||||
|
||||
/* move the 'window' down further */
|
||||
wstart-=wend+1;
|
||||
wvalue=0;
|
||||
start=0;
|
||||
if (wstart < 0) break;
|
||||
}
|
||||
ret=1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(r);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,303 @@
|
||||
/* crypto/bn/bn_exp2.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
#define TABLE_SIZE 32
|
||||
|
||||
int BN_mod_exp2_mont(BIGNUM *rr, const BIGNUM *a1, const BIGNUM *p1,
|
||||
const BIGNUM *a2, const BIGNUM *p2, const BIGNUM *m,
|
||||
BN_CTX *ctx, BN_MONT_CTX *in_mont)
|
||||
{
|
||||
int i, j, bits, b, bits1, bits2, ret =
|
||||
0, wpos1, wpos2, window1, window2, wvalue1, wvalue2;
|
||||
int r_is_one = 1;
|
||||
BIGNUM *d, *r;
|
||||
const BIGNUM *a_mod_m;
|
||||
/* Tables of variables obtained from 'ctx' */
|
||||
BIGNUM *val1[TABLE_SIZE], *val2[TABLE_SIZE];
|
||||
BN_MONT_CTX *mont = NULL;
|
||||
|
||||
bn_check_top(a1);
|
||||
bn_check_top(p1);
|
||||
bn_check_top(a2);
|
||||
bn_check_top(p2);
|
||||
bn_check_top(m);
|
||||
|
||||
if (!(m->d[0] & 1)) {
|
||||
BNerr(BN_F_BN_MOD_EXP2_MONT, BN_R_CALLED_WITH_EVEN_MODULUS);
|
||||
return (0);
|
||||
}
|
||||
bits1 = BN_num_bits(p1);
|
||||
bits2 = BN_num_bits(p2);
|
||||
if ((bits1 == 0) && (bits2 == 0)) {
|
||||
ret = BN_one(rr);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bits = (bits1 > bits2) ? bits1 : bits2;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
d = BN_CTX_get(ctx);
|
||||
r = BN_CTX_get(ctx);
|
||||
val1[0] = BN_CTX_get(ctx);
|
||||
val2[0] = BN_CTX_get(ctx);
|
||||
if (!d || !r || !val1[0] || !val2[0])
|
||||
goto err;
|
||||
|
||||
if (in_mont != NULL)
|
||||
mont = in_mont;
|
||||
else {
|
||||
if ((mont = BN_MONT_CTX_new()) == NULL)
|
||||
goto err;
|
||||
if (!BN_MONT_CTX_set(mont, m, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
window1 = BN_window_bits_for_exponent_size(bits1);
|
||||
window2 = BN_window_bits_for_exponent_size(bits2);
|
||||
|
||||
/*
|
||||
* Build table for a1: val1[i] := a1^(2*i + 1) mod m for i = 0 .. 2^(window1-1)
|
||||
*/
|
||||
if (a1->neg || BN_ucmp(a1, m) >= 0) {
|
||||
if (!BN_mod(val1[0], a1, m, ctx))
|
||||
goto err;
|
||||
a_mod_m = val1[0];
|
||||
} else
|
||||
a_mod_m = a1;
|
||||
if (BN_is_zero(a_mod_m)) {
|
||||
BN_zero(rr);
|
||||
ret = 1;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!BN_to_montgomery(val1[0], a_mod_m, mont, ctx))
|
||||
goto err;
|
||||
if (window1 > 1) {
|
||||
if (!BN_mod_mul_montgomery(d, val1[0], val1[0], mont, ctx))
|
||||
goto err;
|
||||
|
||||
j = 1 << (window1 - 1);
|
||||
for (i = 1; i < j; i++) {
|
||||
if (((val1[i] = BN_CTX_get(ctx)) == NULL) ||
|
||||
!BN_mod_mul_montgomery(val1[i], val1[i - 1], d, mont, ctx))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Build table for a2: val2[i] := a2^(2*i + 1) mod m for i = 0 .. 2^(window2-1)
|
||||
*/
|
||||
if (a2->neg || BN_ucmp(a2, m) >= 0) {
|
||||
if (!BN_mod(val2[0], a2, m, ctx))
|
||||
goto err;
|
||||
a_mod_m = val2[0];
|
||||
} else
|
||||
a_mod_m = a2;
|
||||
if (BN_is_zero(a_mod_m)) {
|
||||
BN_zero(rr);
|
||||
ret = 1;
|
||||
goto err;
|
||||
}
|
||||
if (!BN_to_montgomery(val2[0], a_mod_m, mont, ctx))
|
||||
goto err;
|
||||
if (window2 > 1) {
|
||||
if (!BN_mod_mul_montgomery(d, val2[0], val2[0], mont, ctx))
|
||||
goto err;
|
||||
|
||||
j = 1 << (window2 - 1);
|
||||
for (i = 1; i < j; i++) {
|
||||
if (((val2[i] = BN_CTX_get(ctx)) == NULL) ||
|
||||
!BN_mod_mul_montgomery(val2[i], val2[i - 1], d, mont, ctx))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Now compute the power product, using independent windows. */
|
||||
r_is_one = 1;
|
||||
wvalue1 = 0; /* The 'value' of the first window */
|
||||
wvalue2 = 0; /* The 'value' of the second window */
|
||||
wpos1 = 0; /* If wvalue1 > 0, the bottom bit of the
|
||||
* first window */
|
||||
wpos2 = 0; /* If wvalue2 > 0, the bottom bit of the
|
||||
* second window */
|
||||
|
||||
if (!BN_to_montgomery(r, BN_value_one(), mont, ctx))
|
||||
goto err;
|
||||
for (b = bits - 1; b >= 0; b--) {
|
||||
if (!r_is_one) {
|
||||
if (!BN_mod_mul_montgomery(r, r, r, mont, ctx))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!wvalue1)
|
||||
if (BN_is_bit_set(p1, b)) {
|
||||
/*
|
||||
* consider bits b-window1+1 .. b for this window
|
||||
*/
|
||||
i = b - window1 + 1;
|
||||
while (!BN_is_bit_set(p1, i)) /* works for i<0 */
|
||||
i++;
|
||||
wpos1 = i;
|
||||
wvalue1 = 1;
|
||||
for (i = b - 1; i >= wpos1; i--) {
|
||||
wvalue1 <<= 1;
|
||||
if (BN_is_bit_set(p1, i))
|
||||
wvalue1++;
|
||||
}
|
||||
}
|
||||
|
||||
if (!wvalue2)
|
||||
if (BN_is_bit_set(p2, b)) {
|
||||
/*
|
||||
* consider bits b-window2+1 .. b for this window
|
||||
*/
|
||||
i = b - window2 + 1;
|
||||
while (!BN_is_bit_set(p2, i))
|
||||
i++;
|
||||
wpos2 = i;
|
||||
wvalue2 = 1;
|
||||
for (i = b - 1; i >= wpos2; i--) {
|
||||
wvalue2 <<= 1;
|
||||
if (BN_is_bit_set(p2, i))
|
||||
wvalue2++;
|
||||
}
|
||||
}
|
||||
|
||||
if (wvalue1 && b == wpos1) {
|
||||
/* wvalue1 is odd and < 2^window1 */
|
||||
if (!BN_mod_mul_montgomery(r, r, val1[wvalue1 >> 1], mont, ctx))
|
||||
goto err;
|
||||
wvalue1 = 0;
|
||||
r_is_one = 0;
|
||||
}
|
||||
|
||||
if (wvalue2 && b == wpos2) {
|
||||
/* wvalue2 is odd and < 2^window2 */
|
||||
if (!BN_mod_mul_montgomery(r, r, val2[wvalue2 >> 1], mont, ctx))
|
||||
goto err;
|
||||
wvalue2 = 0;
|
||||
r_is_one = 0;
|
||||
}
|
||||
}
|
||||
if (!BN_from_montgomery(rr, r, mont, ctx))
|
||||
goto err;
|
||||
ret = 1;
|
||||
err:
|
||||
if ((in_mont == NULL) && (mont != NULL))
|
||||
BN_MONT_CTX_free(mont);
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(rr);
|
||||
return (ret);
|
||||
}
|
||||
@@ -0,0 +1,683 @@
|
||||
/* crypto/bn/bn_gcd.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
static BIGNUM *euclid(BIGNUM *a, BIGNUM *b);
|
||||
|
||||
int BN_gcd(BIGNUM *r, const BIGNUM *in_a, const BIGNUM *in_b, BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *a, *b, *t;
|
||||
int ret = 0;
|
||||
|
||||
bn_check_top(in_a);
|
||||
bn_check_top(in_b);
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
a = BN_CTX_get(ctx);
|
||||
b = BN_CTX_get(ctx);
|
||||
if (a == NULL || b == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_copy(a, in_a) == NULL)
|
||||
goto err;
|
||||
if (BN_copy(b, in_b) == NULL)
|
||||
goto err;
|
||||
a->neg = 0;
|
||||
b->neg = 0;
|
||||
|
||||
if (BN_cmp(a, b) < 0) {
|
||||
t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
t = euclid(a, b);
|
||||
if (t == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_copy(r, t) == NULL)
|
||||
goto err;
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(r);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static BIGNUM *euclid(BIGNUM *a, BIGNUM *b)
|
||||
{
|
||||
BIGNUM *t;
|
||||
int shifts = 0;
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
|
||||
/* 0 <= b <= a */
|
||||
while (!BN_is_zero(b)) {
|
||||
/* 0 < b <= a */
|
||||
|
||||
if (BN_is_odd(a)) {
|
||||
if (BN_is_odd(b)) {
|
||||
if (!BN_sub(a, a, b))
|
||||
goto err;
|
||||
if (!BN_rshift1(a, a))
|
||||
goto err;
|
||||
if (BN_cmp(a, b) < 0) {
|
||||
t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
} else { /* a odd - b even */
|
||||
|
||||
if (!BN_rshift1(b, b))
|
||||
goto err;
|
||||
if (BN_cmp(a, b) < 0) {
|
||||
t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
}
|
||||
} else { /* a is even */
|
||||
|
||||
if (BN_is_odd(b)) {
|
||||
if (!BN_rshift1(a, a))
|
||||
goto err;
|
||||
if (BN_cmp(a, b) < 0) {
|
||||
t = a;
|
||||
a = b;
|
||||
b = t;
|
||||
}
|
||||
} else { /* a even - b even */
|
||||
|
||||
if (!BN_rshift1(a, a))
|
||||
goto err;
|
||||
if (!BN_rshift1(b, b))
|
||||
goto err;
|
||||
shifts++;
|
||||
}
|
||||
}
|
||||
/* 0 <= b <= a */
|
||||
}
|
||||
|
||||
if (shifts) {
|
||||
if (!BN_lshift(a, a, shifts))
|
||||
goto err;
|
||||
}
|
||||
bn_check_top(a);
|
||||
return (a);
|
||||
err:
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* solves ax == 1 (mod n) */
|
||||
static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in,
|
||||
const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx);
|
||||
BIGNUM *BN_mod_inverse(BIGNUM *in,
|
||||
const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *A,*B,*X,*Y,*M,*D,*T,*R=NULL;
|
||||
BIGNUM *ret=NULL;
|
||||
int sign;
|
||||
|
||||
if ((BN_get_flags(a, BN_FLG_CONSTTIME) != 0) || (BN_get_flags(n, BN_FLG_CONSTTIME) != 0))
|
||||
{
|
||||
return BN_mod_inverse_no_branch(in, a, n, ctx);
|
||||
}
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(n);
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
A = BN_CTX_get(ctx);
|
||||
B = BN_CTX_get(ctx);
|
||||
X = BN_CTX_get(ctx);
|
||||
D = BN_CTX_get(ctx);
|
||||
M = BN_CTX_get(ctx);
|
||||
Y = BN_CTX_get(ctx);
|
||||
T = BN_CTX_get(ctx);
|
||||
if (T == NULL) goto err;
|
||||
|
||||
if (in == NULL)
|
||||
R=BN_new();
|
||||
else
|
||||
R=in;
|
||||
if (R == NULL) goto err;
|
||||
|
||||
BN_one(X);
|
||||
BN_zero(Y);
|
||||
if (BN_copy(B,a) == NULL) goto err;
|
||||
if (BN_copy(A,n) == NULL) goto err;
|
||||
A->neg = 0;
|
||||
if (B->neg || (BN_ucmp(B, A) >= 0))
|
||||
{
|
||||
if (!BN_nnmod(B, B, A, ctx)) goto err;
|
||||
}
|
||||
sign = -1;
|
||||
/* From B = a mod |n|, A = |n| it follows that
|
||||
*
|
||||
* 0 <= B < A,
|
||||
* -sign*X*a == B (mod |n|),
|
||||
* sign*Y*a == A (mod |n|).
|
||||
*/
|
||||
|
||||
if (BN_is_odd(n) && (BN_num_bits(n) <= (BN_BITS <= 32 ? 450 : 2048)))
|
||||
{
|
||||
/* Binary inversion algorithm; requires odd modulus.
|
||||
* This is faster than the general algorithm if the modulus
|
||||
* is sufficiently small (about 400 .. 500 bits on 32-bit
|
||||
* sytems, but much more on 64-bit systems) */
|
||||
int shift;
|
||||
|
||||
while (!BN_is_zero(B))
|
||||
{
|
||||
/*
|
||||
* 0 < B < |n|,
|
||||
* 0 < A <= |n|,
|
||||
* (1) -sign*X*a == B (mod |n|),
|
||||
* (2) sign*Y*a == A (mod |n|)
|
||||
*/
|
||||
|
||||
/* Now divide B by the maximum possible power of two in the integers,
|
||||
* and divide X by the same value mod |n|.
|
||||
* When we're done, (1) still holds. */
|
||||
shift = 0;
|
||||
while (!BN_is_bit_set(B, shift)) /* note that 0 < B */
|
||||
{
|
||||
shift++;
|
||||
|
||||
if (BN_is_odd(X))
|
||||
{
|
||||
if (!BN_uadd(X, X, n)) goto err;
|
||||
}
|
||||
/* now X is even, so we can easily divide it by two */
|
||||
if (!BN_rshift1(X, X)) goto err;
|
||||
}
|
||||
if (shift > 0)
|
||||
{
|
||||
if (!BN_rshift(B, B, shift)) goto err;
|
||||
}
|
||||
|
||||
|
||||
/* Same for A and Y. Afterwards, (2) still holds. */
|
||||
shift = 0;
|
||||
while (!BN_is_bit_set(A, shift)) /* note that 0 < A */
|
||||
{
|
||||
shift++;
|
||||
|
||||
if (BN_is_odd(Y))
|
||||
{
|
||||
if (!BN_uadd(Y, Y, n)) goto err;
|
||||
}
|
||||
/* now Y is even */
|
||||
if (!BN_rshift1(Y, Y)) goto err;
|
||||
}
|
||||
if (shift > 0)
|
||||
{
|
||||
if (!BN_rshift(A, A, shift)) goto err;
|
||||
}
|
||||
|
||||
|
||||
/* We still have (1) and (2).
|
||||
* Both A and B are odd.
|
||||
* The following computations ensure that
|
||||
*
|
||||
* 0 <= B < |n|,
|
||||
* 0 < A < |n|,
|
||||
* (1) -sign*X*a == B (mod |n|),
|
||||
* (2) sign*Y*a == A (mod |n|),
|
||||
*
|
||||
* and that either A or B is even in the next iteration.
|
||||
*/
|
||||
if (BN_ucmp(B, A) >= 0)
|
||||
{
|
||||
/* -sign*(X + Y)*a == B - A (mod |n|) */
|
||||
if (!BN_uadd(X, X, Y)) goto err;
|
||||
/* NB: we could use BN_mod_add_quick(X, X, Y, n), but that
|
||||
* actually makes the algorithm slower */
|
||||
if (!BN_usub(B, B, A)) goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* sign*(X + Y)*a == A - B (mod |n|) */
|
||||
if (!BN_uadd(Y, Y, X)) goto err;
|
||||
/* as above, BN_mod_add_quick(Y, Y, X, n) would slow things down */
|
||||
if (!BN_usub(A, A, B)) goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* general inversion algorithm */
|
||||
|
||||
while (!BN_is_zero(B))
|
||||
{
|
||||
BIGNUM *tmp;
|
||||
|
||||
/*
|
||||
* 0 < B < A,
|
||||
* (*) -sign*X*a == B (mod |n|),
|
||||
* sign*Y*a == A (mod |n|)
|
||||
*/
|
||||
|
||||
/* (D, M) := (A/B, A%B) ... */
|
||||
if (BN_num_bits(A) == BN_num_bits(B))
|
||||
{
|
||||
if (!BN_one(D)) goto err;
|
||||
if (!BN_sub(M,A,B)) goto err;
|
||||
}
|
||||
else if (BN_num_bits(A) == BN_num_bits(B) + 1)
|
||||
{
|
||||
/* A/B is 1, 2, or 3 */
|
||||
if (!BN_lshift1(T,B)) goto err;
|
||||
if (BN_ucmp(A,T) < 0)
|
||||
{
|
||||
/* A < 2*B, so D=1 */
|
||||
if (!BN_one(D)) goto err;
|
||||
if (!BN_sub(M,A,B)) goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* A >= 2*B, so D=2 or D=3 */
|
||||
if (!BN_sub(M,A,T)) goto err;
|
||||
if (!BN_add(D,T,B)) goto err; /* use D (:= 3*B) as temp */
|
||||
if (BN_ucmp(A,D) < 0)
|
||||
{
|
||||
/* A < 3*B, so D=2 */
|
||||
if (!BN_set_word(D,2)) goto err;
|
||||
/* M (= A - 2*B) already has the correct value */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* only D=3 remains */
|
||||
if (!BN_set_word(D,3)) goto err;
|
||||
/* currently M = A - 2*B, but we need M = A - 3*B */
|
||||
if (!BN_sub(M,M,B)) goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!BN_div(D,M,A,B,ctx)) goto err;
|
||||
}
|
||||
|
||||
/* Now
|
||||
* A = D*B + M;
|
||||
* thus we have
|
||||
* (**) sign*Y*a == D*B + M (mod |n|).
|
||||
*/
|
||||
|
||||
tmp=A; /* keep the BIGNUM object, the value does not matter */
|
||||
|
||||
/* (A, B) := (B, A mod B) ... */
|
||||
A=B;
|
||||
B=M;
|
||||
/* ... so we have 0 <= B < A again */
|
||||
|
||||
/* Since the former M is now B and the former B is now A,
|
||||
* (**) translates into
|
||||
* sign*Y*a == D*A + B (mod |n|),
|
||||
* i.e.
|
||||
* sign*Y*a - D*A == B (mod |n|).
|
||||
* Similarly, (*) translates into
|
||||
* -sign*X*a == A (mod |n|).
|
||||
*
|
||||
* Thus,
|
||||
* sign*Y*a + D*sign*X*a == B (mod |n|),
|
||||
* i.e.
|
||||
* sign*(Y + D*X)*a == B (mod |n|).
|
||||
*
|
||||
* So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at
|
||||
* -sign*X*a == B (mod |n|),
|
||||
* sign*Y*a == A (mod |n|).
|
||||
* Note that X and Y stay non-negative all the time.
|
||||
*/
|
||||
|
||||
/* most of the time D is very small, so we can optimize tmp := D*X+Y */
|
||||
if (BN_is_one(D))
|
||||
{
|
||||
if (!BN_add(tmp,X,Y)) goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BN_is_word(D,2))
|
||||
{
|
||||
if (!BN_lshift1(tmp,X)) goto err;
|
||||
}
|
||||
else if (BN_is_word(D,4))
|
||||
{
|
||||
if (!BN_lshift(tmp,X,2)) goto err;
|
||||
}
|
||||
else if (D->top == 1)
|
||||
{
|
||||
if (!BN_copy(tmp,X)) goto err;
|
||||
if (!BN_mul_word(tmp,D->d[0])) goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!BN_mul(tmp,D,X,ctx)) goto err;
|
||||
}
|
||||
if (!BN_add(tmp,tmp,Y)) goto err;
|
||||
}
|
||||
|
||||
M=Y; /* keep the BIGNUM object, the value does not matter */
|
||||
Y=X;
|
||||
X=tmp;
|
||||
sign = -sign;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The while loop (Euclid's algorithm) ends when
|
||||
* A == gcd(a,n);
|
||||
* we have
|
||||
* sign*Y*a == A (mod |n|),
|
||||
* where Y is non-negative.
|
||||
*/
|
||||
|
||||
if (sign < 0)
|
||||
{
|
||||
if (!BN_sub(Y,n,Y)) goto err;
|
||||
}
|
||||
/* Now Y*a == A (mod |n|). */
|
||||
|
||||
|
||||
if (BN_is_one(A))
|
||||
{
|
||||
/* Y*a == 1 (mod |n|) */
|
||||
if (!Y->neg && BN_ucmp(Y,n) < 0)
|
||||
{
|
||||
if (!BN_copy(R,Y)) goto err;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!BN_nnmod(R,Y,n,ctx)) goto err;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
BNerr(BN_F_BN_MOD_INVERSE,BN_R_NO_INVERSE);
|
||||
goto err;
|
||||
}
|
||||
ret=R;
|
||||
err:
|
||||
if ((ret == NULL) && (in == NULL)) BN_free(R);
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(ret);
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* BN_mod_inverse_no_branch is a special version of BN_mod_inverse.
|
||||
* It does not contain branches that may leak sensitive information.
|
||||
*/
|
||||
static BIGNUM *BN_mod_inverse_no_branch(BIGNUM *in,
|
||||
const BIGNUM *a, const BIGNUM *n,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *A, *B, *X, *Y, *M, *D, *T, *R = NULL;
|
||||
BIGNUM local_A, local_B;
|
||||
BIGNUM *pA, *pB;
|
||||
BIGNUM *ret = NULL;
|
||||
int sign;
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(n);
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
A = BN_CTX_get(ctx);
|
||||
B = BN_CTX_get(ctx);
|
||||
X = BN_CTX_get(ctx);
|
||||
D = BN_CTX_get(ctx);
|
||||
M = BN_CTX_get(ctx);
|
||||
Y = BN_CTX_get(ctx);
|
||||
T = BN_CTX_get(ctx);
|
||||
if (T == NULL)
|
||||
goto err;
|
||||
|
||||
if (in == NULL)
|
||||
R = BN_new();
|
||||
else
|
||||
R = in;
|
||||
if (R == NULL)
|
||||
goto err;
|
||||
|
||||
BN_one(X);
|
||||
BN_zero(Y);
|
||||
if (BN_copy(B, a) == NULL)
|
||||
goto err;
|
||||
if (BN_copy(A, n) == NULL)
|
||||
goto err;
|
||||
A->neg = 0;
|
||||
|
||||
if (B->neg || (BN_ucmp(B, A) >= 0)) {
|
||||
/*
|
||||
* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
|
||||
* BN_div_no_branch will be called eventually.
|
||||
*/
|
||||
pB = &local_B;
|
||||
BN_with_flags(pB, B, BN_FLG_CONSTTIME);
|
||||
if (!BN_nnmod(B, pB, A, ctx))
|
||||
goto err;
|
||||
}
|
||||
sign = -1;
|
||||
/*-
|
||||
* From B = a mod |n|, A = |n| it follows that
|
||||
*
|
||||
* 0 <= B < A,
|
||||
* -sign*X*a == B (mod |n|),
|
||||
* sign*Y*a == A (mod |n|).
|
||||
*/
|
||||
|
||||
while (!BN_is_zero(B)) {
|
||||
BIGNUM *tmp;
|
||||
|
||||
/*-
|
||||
* 0 < B < A,
|
||||
* (*) -sign*X*a == B (mod |n|),
|
||||
* sign*Y*a == A (mod |n|)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Turn BN_FLG_CONSTTIME flag on, so that when BN_div is invoked,
|
||||
* BN_div_no_branch will be called eventually.
|
||||
*/
|
||||
pA = &local_A;
|
||||
BN_with_flags(pA, A, BN_FLG_CONSTTIME);
|
||||
|
||||
/* (D, M) := (A/B, A%B) ... */
|
||||
if (!BN_div(D, M, pA, B, ctx))
|
||||
goto err;
|
||||
|
||||
/*-
|
||||
* Now
|
||||
* A = D*B + M;
|
||||
* thus we have
|
||||
* (**) sign*Y*a == D*B + M (mod |n|).
|
||||
*/
|
||||
|
||||
tmp = A; /* keep the BIGNUM object, the value does not
|
||||
* matter */
|
||||
|
||||
/* (A, B) := (B, A mod B) ... */
|
||||
A = B;
|
||||
B = M;
|
||||
/* ... so we have 0 <= B < A again */
|
||||
|
||||
/*-
|
||||
* Since the former M is now B and the former B is now A,
|
||||
* (**) translates into
|
||||
* sign*Y*a == D*A + B (mod |n|),
|
||||
* i.e.
|
||||
* sign*Y*a - D*A == B (mod |n|).
|
||||
* Similarly, (*) translates into
|
||||
* -sign*X*a == A (mod |n|).
|
||||
*
|
||||
* Thus,
|
||||
* sign*Y*a + D*sign*X*a == B (mod |n|),
|
||||
* i.e.
|
||||
* sign*(Y + D*X)*a == B (mod |n|).
|
||||
*
|
||||
* So if we set (X, Y, sign) := (Y + D*X, X, -sign), we arrive back at
|
||||
* -sign*X*a == B (mod |n|),
|
||||
* sign*Y*a == A (mod |n|).
|
||||
* Note that X and Y stay non-negative all the time.
|
||||
*/
|
||||
|
||||
if (!BN_mul(tmp, D, X, ctx))
|
||||
goto err;
|
||||
if (!BN_add(tmp, tmp, Y))
|
||||
goto err;
|
||||
|
||||
M = Y; /* keep the BIGNUM object, the value does not
|
||||
* matter */
|
||||
Y = X;
|
||||
X = tmp;
|
||||
sign = -sign;
|
||||
}
|
||||
|
||||
/*-
|
||||
* The while loop (Euclid's algorithm) ends when
|
||||
* A == gcd(a,n);
|
||||
* we have
|
||||
* sign*Y*a == A (mod |n|),
|
||||
* where Y is non-negative.
|
||||
*/
|
||||
|
||||
if (sign < 0) {
|
||||
if (!BN_sub(Y, n, Y))
|
||||
goto err;
|
||||
}
|
||||
/* Now Y*a == A (mod |n|). */
|
||||
|
||||
if (BN_is_one(A)) {
|
||||
/* Y*a == 1 (mod |n|) */
|
||||
if (!Y->neg && BN_ucmp(Y, n) < 0) {
|
||||
if (!BN_copy(R, Y))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_nnmod(R, Y, n, ctx))
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
BNerr(BN_F_BN_MOD_INVERSE_NO_BRANCH, BN_R_NO_INVERSE);
|
||||
goto err;
|
||||
}
|
||||
ret = R;
|
||||
err:
|
||||
if ((ret == NULL) && (in == NULL))
|
||||
BN_free(R);
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(ret);
|
||||
return (ret);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,186 @@
|
||||
/* crypto/bn/bn_kron.c */
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
/* least significant word */
|
||||
#define BN_lsw(n) (((n)->top == 0) ? (BN_ULONG) 0 : (n)->d[0])
|
||||
|
||||
/* Returns -2 for errors because both -1 and 0 are valid results. */
|
||||
int BN_kronecker(const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
|
||||
{
|
||||
int i;
|
||||
int ret = -2; /* avoid 'uninitialized' warning */
|
||||
int err = 0;
|
||||
BIGNUM *A, *B, *tmp;
|
||||
/* In 'tab', only odd-indexed entries are relevant:
|
||||
* For any odd BIGNUM n,
|
||||
* tab[BN_lsw(n) & 7]
|
||||
* is $(-1)^{(n^2-1)/8}$ (using TeX notation).
|
||||
* Note that the sign of n does not matter.
|
||||
*/
|
||||
static const int tab[8] = {0, 1, 0, -1, 0, -1, 0, 1};
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
A = BN_CTX_get(ctx);
|
||||
B = BN_CTX_get(ctx);
|
||||
if (B == NULL) goto end;
|
||||
|
||||
err = !BN_copy(A, a);
|
||||
if (err) goto end;
|
||||
err = !BN_copy(B, b);
|
||||
if (err) goto end;
|
||||
|
||||
/*
|
||||
* Kronecker symbol, imlemented according to Henri Cohen,
|
||||
* "A Course in Computational Algebraic Number Theory"
|
||||
* (algorithm 1.4.10).
|
||||
*/
|
||||
|
||||
/* Cohen's step 1: */
|
||||
|
||||
if (BN_is_zero(B))
|
||||
{
|
||||
ret = BN_abs_is_word(A, 1);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Cohen's step 2: */
|
||||
|
||||
if (!BN_is_odd(A) && !BN_is_odd(B))
|
||||
{
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* now B is non-zero */
|
||||
i = 0;
|
||||
while (!BN_is_bit_set(B, i))
|
||||
i++;
|
||||
err = !BN_rshift(B, B, i);
|
||||
if (err) goto end;
|
||||
if (i & 1)
|
||||
{
|
||||
/* i is odd */
|
||||
/* (thus B was even, thus A must be odd!) */
|
||||
|
||||
/* set 'ret' to $(-1)^{(A^2-1)/8}$ */
|
||||
ret = tab[BN_lsw(A) & 7];
|
||||
}
|
||||
else
|
||||
{
|
||||
/* i is even */
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
if (B->neg)
|
||||
{
|
||||
B->neg = 0;
|
||||
if (A->neg)
|
||||
ret = -ret;
|
||||
}
|
||||
|
||||
/* now B is positive and odd, so what remains to be done is
|
||||
* to compute the Jacobi symbol (A/B) and multiply it by 'ret' */
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Cohen's step 3: */
|
||||
|
||||
/* B is positive and odd */
|
||||
|
||||
if (BN_is_zero(A))
|
||||
{
|
||||
ret = BN_is_one(B) ? ret : 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* now A is non-zero */
|
||||
i = 0;
|
||||
while (!BN_is_bit_set(A, i))
|
||||
i++;
|
||||
err = !BN_rshift(A, A, i);
|
||||
if (err) goto end;
|
||||
if (i & 1)
|
||||
{
|
||||
/* i is odd */
|
||||
/* multiply 'ret' by $(-1)^{(B^2-1)/8}$ */
|
||||
ret = ret * tab[BN_lsw(B) & 7];
|
||||
}
|
||||
|
||||
/* Cohen's step 4: */
|
||||
/* multiply 'ret' by $(-1)^{(A-1)(B-1)/4}$ */
|
||||
if ((A->neg ? ~BN_lsw(A) : BN_lsw(A)) & BN_lsw(B) & 2)
|
||||
ret = -ret;
|
||||
|
||||
/* (A, B) := (B mod |A|, |A|) */
|
||||
err = !BN_nnmod(B, B, A, ctx);
|
||||
if (err) goto end;
|
||||
tmp = A; A = B; B = tmp;
|
||||
tmp->neg = 0;
|
||||
}
|
||||
end:
|
||||
BN_CTX_end(ctx);
|
||||
if (err)
|
||||
return -2;
|
||||
else
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,490 @@
|
||||
/* crypto/bn/bn_lcl.h */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef HEADER_BN_LCL_H
|
||||
# define HEADER_BN_LCL_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <openssl/bn.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*-
|
||||
* BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions
|
||||
*
|
||||
*
|
||||
* For window size 'w' (w >= 2) and a random 'b' bits exponent,
|
||||
* the number of multiplications is a constant plus on average
|
||||
*
|
||||
* 2^(w-1) + (b-w)/(w+1);
|
||||
*
|
||||
* here 2^(w-1) is for precomputing the table (we actually need
|
||||
* entries only for windows that have the lowest bit set), and
|
||||
* (b-w)/(w+1) is an approximation for the expected number of
|
||||
* w-bit windows, not counting the first one.
|
||||
*
|
||||
* Thus we should use
|
||||
*
|
||||
* w >= 6 if b > 671
|
||||
* w = 5 if 671 > b > 239
|
||||
* w = 4 if 239 > b > 79
|
||||
* w = 3 if 79 > b > 23
|
||||
* w <= 2 if 23 > b
|
||||
*
|
||||
* (with draws in between). Very small exponents are often selected
|
||||
* with low Hamming weight, so we use w = 1 for b <= 23.
|
||||
*/
|
||||
# if 1
|
||||
# define BN_window_bits_for_exponent_size(b) \
|
||||
((b) > 671 ? 6 : \
|
||||
(b) > 239 ? 5 : \
|
||||
(b) > 79 ? 4 : \
|
||||
(b) > 23 ? 3 : 1)
|
||||
# else
|
||||
/*
|
||||
* Old SSLeay/OpenSSL table. Maximum window size was 5, so this table differs
|
||||
* for b==1024; but it coincides for other interesting values (b==160,
|
||||
* b==512).
|
||||
*/
|
||||
#define BN_window_bits_for_exponent_size(b) \
|
||||
((b) > 255 ? 5 : \
|
||||
(b) > 127 ? 4 : \
|
||||
(b) > 17 ? 3 : 1)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* BN_mod_exp_mont_conttime is based on the assumption that the L1 data cache
|
||||
* line width of the target processor is at least the following value.
|
||||
*/
|
||||
# define MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH ( 64 )
|
||||
# define MOD_EXP_CTIME_MIN_CACHE_LINE_MASK (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - 1)
|
||||
|
||||
/* Window sizes optimized for fixed window size modular exponentiation
|
||||
* algorithm (BN_mod_exp_mont_consttime).
|
||||
*
|
||||
* To achieve the security goals of BN_mode_exp_mont_consttime, the
|
||||
* maximum size of the window must not exceed
|
||||
* log_2(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH).
|
||||
*
|
||||
* Window size thresholds are defined for cache line sizes of 32 and 64,
|
||||
* cache line sizes where log_2(32)=5 and log_2(64)=6 respectively. A
|
||||
* window size of 7 should only be used on processors that have a 128
|
||||
* byte or greater cache line size.
|
||||
*/
|
||||
# if MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 64
|
||||
|
||||
# define BN_window_bits_for_ctime_exponent_size(b) \
|
||||
((b) > 937 ? 6 : \
|
||||
(b) > 306 ? 5 : \
|
||||
(b) > 89 ? 4 : \
|
||||
(b) > 22 ? 3 : 1)
|
||||
# define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (6)
|
||||
|
||||
# elif MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 32
|
||||
|
||||
# define BN_window_bits_for_ctime_exponent_size(b) \
|
||||
((b) > 306 ? 5 : \
|
||||
(b) > 89 ? 4 : \
|
||||
(b) > 22 ? 3 : 1)
|
||||
# define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE (5)
|
||||
|
||||
# endif
|
||||
|
||||
/* Pentium pro 16,16,16,32,64 */
|
||||
/* Alpha 16,16,16,16.64 */
|
||||
# define BN_MULL_SIZE_NORMAL (16)/* 32 */
|
||||
# define BN_MUL_RECURSIVE_SIZE_NORMAL (16)/* 32 less than */
|
||||
# define BN_SQR_RECURSIVE_SIZE_NORMAL (16)/* 32 */
|
||||
# define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL (32)/* 32 */
|
||||
# define BN_MONT_CTX_SET_SIZE_WORD (64)/* 32 */
|
||||
|
||||
# if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC)
|
||||
/*
|
||||
* BN_UMULT_HIGH section.
|
||||
*
|
||||
* No, I'm not trying to overwhelm you when stating that the
|
||||
* product of N-bit numbers is 2*N bits wide:-) No, I don't expect
|
||||
* you to be impressed when I say that if the compiler doesn't
|
||||
* support 2*N integer type, then you have to replace every N*N
|
||||
* multiplication with 4 (N/2)*(N/2) accompanied by some shifts
|
||||
* and additions which unavoidably results in severe performance
|
||||
* penalties. Of course provided that the hardware is capable of
|
||||
* producing 2*N result... That's when you normally start
|
||||
* considering assembler implementation. However! It should be
|
||||
* pointed out that some CPUs (most notably Alpha, PowerPC and
|
||||
* upcoming IA-64 family:-) provide *separate* instruction
|
||||
* calculating the upper half of the product placing the result
|
||||
* into a general purpose register. Now *if* the compiler supports
|
||||
* inline assembler, then it's not impossible to implement the
|
||||
* "bignum" routines (and have the compiler optimize 'em)
|
||||
* exhibiting "native" performance in C. That's what BN_UMULT_HIGH
|
||||
* macro is about:-)
|
||||
*
|
||||
* <appro@fy.chalmers.se>
|
||||
*/
|
||||
# if defined(__alpha) && (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT))
|
||||
# if defined(__DECC)
|
||||
# include <c_asm.h>
|
||||
# define BN_UMULT_HIGH(a,b) (BN_ULONG)asm("umulh %a0,%a1,%v0",(a),(b))
|
||||
# elif defined(__GNUC__)
|
||||
# define BN_UMULT_HIGH(a,b) ({ \
|
||||
register BN_ULONG ret; \
|
||||
asm ("umulh %1,%2,%0" \
|
||||
: "=r"(ret) \
|
||||
: "r"(a), "r"(b)); \
|
||||
ret; })
|
||||
# endif /* compiler */
|
||||
# elif defined(_ARCH_PPC) && defined(__64BIT__) && defined(SIXTY_FOUR_BIT_LONG)
|
||||
# if defined(__GNUC__)
|
||||
# define BN_UMULT_HIGH(a,b) ({ \
|
||||
register BN_ULONG ret; \
|
||||
asm ("mulhdu %0,%1,%2" \
|
||||
: "=r"(ret) \
|
||||
: "r"(a), "r"(b)); \
|
||||
ret; })
|
||||
# endif /* compiler */
|
||||
# elif defined(__x86_64) && defined(SIXTY_FOUR_BIT_LONG)
|
||||
# if defined(__GNUC__)
|
||||
# define BN_UMULT_HIGH(a,b) ({ \
|
||||
register BN_ULONG ret,discard; \
|
||||
asm ("mulq %3" \
|
||||
: "=a"(discard),"=d"(ret) \
|
||||
: "a"(a), "g"(b) \
|
||||
: "cc"); \
|
||||
ret; })
|
||||
# define BN_UMULT_LOHI(low,high,a,b) \
|
||||
asm ("mulq %3" \
|
||||
: "=a"(low),"=d"(high) \
|
||||
: "a"(a),"g"(b) \
|
||||
: "cc");
|
||||
# endif
|
||||
# elif (defined(_M_AMD64) || defined(_M_X64)) && defined(SIXTY_FOUR_BIT)
|
||||
# if defined(_MSC_VER) && _MSC_VER>=1400
|
||||
unsigned __int64 __umulh(unsigned __int64 a, unsigned __int64 b);
|
||||
unsigned __int64 _umul128(unsigned __int64 a, unsigned __int64 b,
|
||||
unsigned __int64 *h);
|
||||
# pragma intrinsic(__umulh,_umul128)
|
||||
# define BN_UMULT_HIGH(a,b) __umulh((a),(b))
|
||||
# define BN_UMULT_LOHI(low,high,a,b) ((low)=_umul128((a),(b),&(high)))
|
||||
# endif
|
||||
# endif /* cpu */
|
||||
# endif /* OPENSSL_NO_ASM */
|
||||
|
||||
/*************************************************************
|
||||
* Using the long long type
|
||||
*/
|
||||
# define Lw(t) (((BN_ULONG)(t))&BN_MASK2)
|
||||
# define Hw(t) (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
|
||||
|
||||
# ifdef BN_DEBUG_RAND
|
||||
# define bn_clear_top2max(a) \
|
||||
{ \
|
||||
int ind = (a)->dmax - (a)->top; \
|
||||
BN_ULONG *ftl = &(a)->d[(a)->top-1]; \
|
||||
for (; ind != 0; ind--) \
|
||||
*(++ftl) = 0x0; \
|
||||
}
|
||||
# else
|
||||
# define bn_clear_top2max(a)
|
||||
# endif
|
||||
|
||||
# ifdef BN_LLONG
|
||||
# define mul_add(r,a,w,c) { \
|
||||
BN_ULLONG t; \
|
||||
t=(BN_ULLONG)w * (a) + (r) + (c); \
|
||||
(r)= Lw(t); \
|
||||
(c)= Hw(t); \
|
||||
}
|
||||
|
||||
# define mul(r,a,w,c) { \
|
||||
BN_ULLONG t; \
|
||||
t=(BN_ULLONG)w * (a) + (c); \
|
||||
(r)= Lw(t); \
|
||||
(c)= Hw(t); \
|
||||
}
|
||||
|
||||
# define sqr(r0,r1,a) { \
|
||||
BN_ULLONG t; \
|
||||
t=(BN_ULLONG)(a)*(a); \
|
||||
(r0)=Lw(t); \
|
||||
(r1)=Hw(t); \
|
||||
}
|
||||
|
||||
# elif defined(BN_UMULT_LOHI)
|
||||
# define mul_add(r,a,w,c) { \
|
||||
BN_ULONG high,low,ret,tmp=(a); \
|
||||
ret = (r); \
|
||||
BN_UMULT_LOHI(low,high,w,tmp); \
|
||||
ret += (c); \
|
||||
(c) = (ret<(c))?1:0; \
|
||||
(c) += high; \
|
||||
ret += low; \
|
||||
(c) += (ret<low)?1:0; \
|
||||
(r) = ret; \
|
||||
}
|
||||
|
||||
# define mul(r,a,w,c) { \
|
||||
BN_ULONG high,low,ret,ta=(a); \
|
||||
BN_UMULT_LOHI(low,high,w,ta); \
|
||||
ret = low + (c); \
|
||||
(c) = high; \
|
||||
(c) += (ret<low)?1:0; \
|
||||
(r) = ret; \
|
||||
}
|
||||
|
||||
# define sqr(r0,r1,a) { \
|
||||
BN_ULONG tmp=(a); \
|
||||
BN_UMULT_LOHI(r0,r1,tmp,tmp); \
|
||||
}
|
||||
|
||||
# elif defined(BN_UMULT_HIGH)
|
||||
# define mul_add(r,a,w,c) { \
|
||||
BN_ULONG high,low,ret,tmp=(a); \
|
||||
ret = (r); \
|
||||
high= BN_UMULT_HIGH(w,tmp); \
|
||||
ret += (c); \
|
||||
low = (w) * tmp; \
|
||||
(c) = (ret<(c))?1:0; \
|
||||
(c) += high; \
|
||||
ret += low; \
|
||||
(c) += (ret<low)?1:0; \
|
||||
(r) = ret; \
|
||||
}
|
||||
|
||||
# define mul(r,a,w,c) { \
|
||||
BN_ULONG high,low,ret,ta=(a); \
|
||||
low = (w) * ta; \
|
||||
high= BN_UMULT_HIGH(w,ta); \
|
||||
ret = low + (c); \
|
||||
(c) = high; \
|
||||
(c) += (ret<low)?1:0; \
|
||||
(r) = ret; \
|
||||
}
|
||||
|
||||
# define sqr(r0,r1,a) { \
|
||||
BN_ULONG tmp=(a); \
|
||||
(r0) = tmp * tmp; \
|
||||
(r1) = BN_UMULT_HIGH(tmp,tmp); \
|
||||
}
|
||||
|
||||
# else
|
||||
/*************************************************************
|
||||
* No long long type
|
||||
*/
|
||||
|
||||
# define LBITS(a) ((a)&BN_MASK2l)
|
||||
# define HBITS(a) (((a)>>BN_BITS4)&BN_MASK2l)
|
||||
# define L2HBITS(a) (((a)<<BN_BITS4)&BN_MASK2)
|
||||
|
||||
# define LLBITS(a) ((a)&BN_MASKl)
|
||||
# define LHBITS(a) (((a)>>BN_BITS2)&BN_MASKl)
|
||||
# define LL2HBITS(a) ((BN_ULLONG)((a)&BN_MASKl)<<BN_BITS2)
|
||||
|
||||
# define mul64(l,h,bl,bh) \
|
||||
{ \
|
||||
BN_ULONG m,m1,lt,ht; \
|
||||
\
|
||||
lt=l; \
|
||||
ht=h; \
|
||||
m =(bh)*(lt); \
|
||||
lt=(bl)*(lt); \
|
||||
m1=(bl)*(ht); \
|
||||
ht =(bh)*(ht); \
|
||||
m=(m+m1)&BN_MASK2; if (m < m1) ht+=L2HBITS((BN_ULONG)1); \
|
||||
ht+=HBITS(m); \
|
||||
m1=L2HBITS(m); \
|
||||
lt=(lt+m1)&BN_MASK2; if (lt < m1) ht++; \
|
||||
(l)=lt; \
|
||||
(h)=ht; \
|
||||
}
|
||||
|
||||
# define sqr64(lo,ho,in) \
|
||||
{ \
|
||||
BN_ULONG l,h,m; \
|
||||
\
|
||||
h=(in); \
|
||||
l=LBITS(h); \
|
||||
h=HBITS(h); \
|
||||
m =(l)*(h); \
|
||||
l*=l; \
|
||||
h*=h; \
|
||||
h+=(m&BN_MASK2h1)>>(BN_BITS4-1); \
|
||||
m =(m&BN_MASK2l)<<(BN_BITS4+1); \
|
||||
l=(l+m)&BN_MASK2; if (l < m) h++; \
|
||||
(lo)=l; \
|
||||
(ho)=h; \
|
||||
}
|
||||
|
||||
# define mul_add(r,a,bl,bh,c) { \
|
||||
BN_ULONG l,h; \
|
||||
\
|
||||
h= (a); \
|
||||
l=LBITS(h); \
|
||||
h=HBITS(h); \
|
||||
mul64(l,h,(bl),(bh)); \
|
||||
\
|
||||
/* non-multiply part */ \
|
||||
l=(l+(c))&BN_MASK2; if (l < (c)) h++; \
|
||||
(c)=(r); \
|
||||
l=(l+(c))&BN_MASK2; if (l < (c)) h++; \
|
||||
(c)=h&BN_MASK2; \
|
||||
(r)=l; \
|
||||
}
|
||||
|
||||
# define mul(r,a,bl,bh,c) { \
|
||||
BN_ULONG l,h; \
|
||||
\
|
||||
h= (a); \
|
||||
l=LBITS(h); \
|
||||
h=HBITS(h); \
|
||||
mul64(l,h,(bl),(bh)); \
|
||||
\
|
||||
/* non-multiply part */ \
|
||||
l+=(c); if ((l&BN_MASK2) < (c)) h++; \
|
||||
(c)=h&BN_MASK2; \
|
||||
(r)=l&BN_MASK2; \
|
||||
}
|
||||
# endif /* !BN_LLONG */
|
||||
|
||||
void bn_mul_normal(BN_ULONG *r, BN_ULONG *a, int na, BN_ULONG *b, int nb);
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b);
|
||||
void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp);
|
||||
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a);
|
||||
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a);
|
||||
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n);
|
||||
int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl);
|
||||
void bn_mul_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
|
||||
int dna, int dnb, BN_ULONG *t);
|
||||
void bn_mul_part_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b,
|
||||
int n, int tna, int tnb, BN_ULONG *t);
|
||||
void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t);
|
||||
void bn_mul_low_normal(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n);
|
||||
void bn_mul_low_recursive(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n2,
|
||||
BN_ULONG *t);
|
||||
void bn_mul_high(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, BN_ULONG *l, int n2,
|
||||
BN_ULONG *t);
|
||||
BN_ULONG bn_add_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int cl, int dl);
|
||||
BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
|
||||
int cl, int dl);
|
||||
int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
|
||||
const BN_ULONG *np, const BN_ULONG *n0, int num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,854 @@
|
||||
/* crypto/bn/bn_lib.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#ifndef BN_DEBUG
|
||||
# undef NDEBUG /* avoid conflicting definitions */
|
||||
# define NDEBUG
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
const char BN_version[] = "Big Number" OPENSSL_VERSION_PTEXT;
|
||||
|
||||
/* This stuff appears to be completely unused, so is deprecated */
|
||||
#ifndef OPENSSL_NO_DEPRECATED
|
||||
/*-
|
||||
* For a 32 bit machine
|
||||
* 2 - 4 == 128
|
||||
* 3 - 8 == 256
|
||||
* 4 - 16 == 512
|
||||
* 5 - 32 == 1024
|
||||
* 6 - 64 == 2048
|
||||
* 7 - 128 == 4096
|
||||
* 8 - 256 == 8192
|
||||
*/
|
||||
static int bn_limit_bits = 0;
|
||||
static int bn_limit_num = 8; /* (1<<bn_limit_bits) */
|
||||
static int bn_limit_bits_low = 0;
|
||||
static int bn_limit_num_low = 8; /* (1<<bn_limit_bits_low) */
|
||||
static int bn_limit_bits_high = 0;
|
||||
static int bn_limit_num_high = 8; /* (1<<bn_limit_bits_high) */
|
||||
static int bn_limit_bits_mont = 0;
|
||||
static int bn_limit_num_mont = 8; /* (1<<bn_limit_bits_mont) */
|
||||
|
||||
void BN_set_params(int mult, int high, int low, int mont)
|
||||
{
|
||||
if (mult >= 0) {
|
||||
if (mult > (int)(sizeof(int) * 8) - 1)
|
||||
mult = sizeof(int) * 8 - 1;
|
||||
bn_limit_bits = mult;
|
||||
bn_limit_num = 1 << mult;
|
||||
}
|
||||
if (high >= 0) {
|
||||
if (high > (int)(sizeof(int) * 8) - 1)
|
||||
high = sizeof(int) * 8 - 1;
|
||||
bn_limit_bits_high = high;
|
||||
bn_limit_num_high = 1 << high;
|
||||
}
|
||||
if (low >= 0) {
|
||||
if (low > (int)(sizeof(int) * 8) - 1)
|
||||
low = sizeof(int) * 8 - 1;
|
||||
bn_limit_bits_low = low;
|
||||
bn_limit_num_low = 1 << low;
|
||||
}
|
||||
if (mont >= 0) {
|
||||
if (mont > (int)(sizeof(int) * 8) - 1)
|
||||
mont = sizeof(int) * 8 - 1;
|
||||
bn_limit_bits_mont = mont;
|
||||
bn_limit_num_mont = 1 << mont;
|
||||
}
|
||||
}
|
||||
|
||||
int BN_get_params(int which)
|
||||
{
|
||||
if (which == 0)
|
||||
return (bn_limit_bits);
|
||||
else if (which == 1)
|
||||
return (bn_limit_bits_high);
|
||||
else if (which == 2)
|
||||
return (bn_limit_bits_low);
|
||||
else if (which == 3)
|
||||
return (bn_limit_bits_mont);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
#endif
|
||||
|
||||
const BIGNUM *BN_value_one(void)
|
||||
{
|
||||
static BN_ULONG data_one = 1L;
|
||||
static BIGNUM const_one = { &data_one, 1, 1, 0, BN_FLG_STATIC_DATA };
|
||||
|
||||
return (&const_one);
|
||||
}
|
||||
|
||||
int BN_num_bits_word(BN_ULONG l)
|
||||
{
|
||||
static const char bits[256] = {
|
||||
0, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8,
|
||||
};
|
||||
|
||||
#if defined(SIXTY_FOUR_BIT_LONG)
|
||||
if (l & 0xffffffff00000000L) {
|
||||
if (l & 0xffff000000000000L) {
|
||||
if (l & 0xff00000000000000L) {
|
||||
return (bits[(int)(l >> 56)] + 56);
|
||||
} else
|
||||
return (bits[(int)(l >> 48)] + 48);
|
||||
} else {
|
||||
if (l & 0x0000ff0000000000L) {
|
||||
return (bits[(int)(l >> 40)] + 40);
|
||||
} else
|
||||
return (bits[(int)(l >> 32)] + 32);
|
||||
}
|
||||
} else
|
||||
#else
|
||||
# ifdef SIXTY_FOUR_BIT
|
||||
if (l & 0xffffffff00000000LL) {
|
||||
if (l & 0xffff000000000000LL) {
|
||||
if (l & 0xff00000000000000LL) {
|
||||
return (bits[(int)(l >> 56)] + 56);
|
||||
} else
|
||||
return (bits[(int)(l >> 48)] + 48);
|
||||
} else {
|
||||
if (l & 0x0000ff0000000000LL) {
|
||||
return (bits[(int)(l >> 40)] + 40);
|
||||
} else
|
||||
return (bits[(int)(l >> 32)] + 32);
|
||||
}
|
||||
} else
|
||||
# endif
|
||||
#endif
|
||||
{
|
||||
#if defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
|
||||
if (l & 0xffff0000L) {
|
||||
if (l & 0xff000000L)
|
||||
return (bits[(int)(l >> 24L)] + 24);
|
||||
else
|
||||
return (bits[(int)(l >> 16L)] + 16);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
#if defined(SIXTEEN_BIT) || defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
|
||||
if (l & 0xff00L)
|
||||
return (bits[(int)(l >> 8)] + 8);
|
||||
else
|
||||
#endif
|
||||
return (bits[(int)(l)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int BN_num_bits(const BIGNUM *a)
|
||||
{
|
||||
int i = a->top - 1;
|
||||
bn_check_top(a);
|
||||
|
||||
if (BN_is_zero(a))
|
||||
return 0;
|
||||
return ((i * BN_BITS2) + BN_num_bits_word(a->d[i]));
|
||||
}
|
||||
|
||||
void BN_clear_free(BIGNUM *a)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (a == NULL)
|
||||
return;
|
||||
bn_check_top(a);
|
||||
if (a->d != NULL) {
|
||||
OPENSSL_cleanse(a->d, a->dmax * sizeof(a->d[0]));
|
||||
if (!(BN_get_flags(a, BN_FLG_STATIC_DATA)))
|
||||
OPENSSL_free(a->d);
|
||||
}
|
||||
i = BN_get_flags(a, BN_FLG_MALLOCED);
|
||||
OPENSSL_cleanse(a, sizeof(BIGNUM));
|
||||
if (i)
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
|
||||
void BN_free(BIGNUM *a)
|
||||
{
|
||||
if (a == NULL)
|
||||
return;
|
||||
bn_check_top(a);
|
||||
if ((a->d != NULL) && !(BN_get_flags(a, BN_FLG_STATIC_DATA)))
|
||||
OPENSSL_free(a->d);
|
||||
if (a->flags & BN_FLG_MALLOCED)
|
||||
OPENSSL_free(a);
|
||||
else {
|
||||
#ifndef OPENSSL_NO_DEPRECATED
|
||||
a->flags |= BN_FLG_FREE;
|
||||
#endif
|
||||
a->d = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void BN_init(BIGNUM *a)
|
||||
{
|
||||
memset(a, 0, sizeof(BIGNUM));
|
||||
bn_check_top(a);
|
||||
}
|
||||
|
||||
BIGNUM *BN_new(void)
|
||||
{
|
||||
BIGNUM *ret;
|
||||
|
||||
if ((ret = (BIGNUM *)OPENSSL_malloc(sizeof(BIGNUM))) == NULL) {
|
||||
BNerr(BN_F_BN_NEW, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
ret->flags = BN_FLG_MALLOCED;
|
||||
ret->top = 0;
|
||||
ret->neg = 0;
|
||||
ret->dmax = 0;
|
||||
ret->d = NULL;
|
||||
bn_check_top(ret);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* This is used both by bn_expand2() and bn_dup_expand() */
|
||||
/* The caller MUST check that words > b->dmax before calling this */
|
||||
static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words)
|
||||
{
|
||||
BN_ULONG *A, *a = NULL;
|
||||
const BN_ULONG *B;
|
||||
int i;
|
||||
|
||||
bn_check_top(b);
|
||||
|
||||
if (words > (INT_MAX / (4 * BN_BITS2))) {
|
||||
BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_BIGNUM_TOO_LONG);
|
||||
return NULL;
|
||||
}
|
||||
if (BN_get_flags(b, BN_FLG_STATIC_DATA)) {
|
||||
BNerr(BN_F_BN_EXPAND_INTERNAL, BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
|
||||
return (NULL);
|
||||
}
|
||||
a = A = (BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG) * words);
|
||||
if (A == NULL) {
|
||||
BNerr(BN_F_BN_EXPAND_INTERNAL, ERR_R_MALLOC_FAILURE);
|
||||
return (NULL);
|
||||
}
|
||||
#ifdef PURIFY
|
||||
/*
|
||||
* Valgrind complains in BN_consttime_swap because we process the whole
|
||||
* array even if it's not initialised yet. This doesn't matter in that
|
||||
* function - what's important is constant time operation (we're not
|
||||
* actually going to use the data)
|
||||
*/
|
||||
memset(a, 0, sizeof(BN_ULONG) * words);
|
||||
#endif
|
||||
|
||||
#if 1
|
||||
B = b->d;
|
||||
/* Check if the previous number needs to be copied */
|
||||
if (B != NULL) {
|
||||
for (i = b->top >> 2; i > 0; i--, A += 4, B += 4) {
|
||||
/*
|
||||
* The fact that the loop is unrolled
|
||||
* 4-wise is a tribute to Intel. It's
|
||||
* the one that doesn't have enough
|
||||
* registers to accomodate more data.
|
||||
* I'd unroll it 8-wise otherwise:-)
|
||||
*
|
||||
* <appro@fy.chalmers.se>
|
||||
*/
|
||||
BN_ULONG a0, a1, a2, a3;
|
||||
a0 = B[0];
|
||||
a1 = B[1];
|
||||
a2 = B[2];
|
||||
a3 = B[3];
|
||||
A[0] = a0;
|
||||
A[1] = a1;
|
||||
A[2] = a2;
|
||||
A[3] = a3;
|
||||
}
|
||||
/*
|
||||
* workaround for ultrix cc: without 'case 0', the optimizer does
|
||||
* the switch table by doing a=top&3; a--; goto jump_table[a];
|
||||
* which fails for top== 0
|
||||
*/
|
||||
switch (b->top & 3) {
|
||||
case 3:
|
||||
A[2] = B[2];
|
||||
case 2:
|
||||
A[1] = B[1];
|
||||
case 1:
|
||||
A[0] = B[0];
|
||||
case 0:
|
||||
;
|
||||
}
|
||||
}
|
||||
#else
|
||||
memset(A, 0, sizeof(BN_ULONG) * words);
|
||||
memcpy(A, b->d, sizeof(b->d[0]) * b->top);
|
||||
#endif
|
||||
|
||||
return (a);
|
||||
}
|
||||
|
||||
/*
|
||||
* This is an internal function that can be used instead of bn_expand2() when
|
||||
* there is a need to copy BIGNUMs instead of only expanding the data part,
|
||||
* while still expanding them. Especially useful when needing to expand
|
||||
* BIGNUMs that are declared 'const' and should therefore not be changed. The
|
||||
* reason to use this instead of a BN_dup() followed by a bn_expand2() is
|
||||
* memory allocation overhead. A BN_dup() followed by a bn_expand2() will
|
||||
* allocate new memory for the BIGNUM data twice, and free it once, while
|
||||
* bn_dup_expand() makes sure allocation is made only once.
|
||||
*/
|
||||
|
||||
#ifndef OPENSSL_NO_DEPRECATED
|
||||
BIGNUM *bn_dup_expand(const BIGNUM *b, int words)
|
||||
{
|
||||
BIGNUM *r = NULL;
|
||||
|
||||
bn_check_top(b);
|
||||
|
||||
/*
|
||||
* This function does not work if words <= b->dmax && top < words because
|
||||
* BN_dup() does not preserve 'dmax'! (But bn_dup_expand() is not used
|
||||
* anywhere yet.)
|
||||
*/
|
||||
|
||||
if (words > b->dmax) {
|
||||
BN_ULONG *a = bn_expand_internal(b, words);
|
||||
|
||||
if (a) {
|
||||
r = BN_new();
|
||||
if (r) {
|
||||
r->top = b->top;
|
||||
r->dmax = words;
|
||||
r->neg = b->neg;
|
||||
r->d = a;
|
||||
} else {
|
||||
/* r == NULL, BN_new failure */
|
||||
OPENSSL_free(a);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* If a == NULL, there was an error in allocation in
|
||||
* bn_expand_internal(), and NULL should be returned
|
||||
*/
|
||||
} else {
|
||||
r = BN_dup(b);
|
||||
}
|
||||
|
||||
bn_check_top(r);
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is an internal function that should not be used in applications. It
|
||||
* ensures that 'b' has enough room for a 'words' word number and initialises
|
||||
* any unused part of b->d with leading zeros. It is mostly used by the
|
||||
* various BIGNUM routines. If there is an error, NULL is returned. If not,
|
||||
* 'b' is returned.
|
||||
*/
|
||||
|
||||
BIGNUM *bn_expand2(BIGNUM *b, int words)
|
||||
{
|
||||
bn_check_top(b);
|
||||
|
||||
if (words > b->dmax) {
|
||||
BN_ULONG *a = bn_expand_internal(b, words);
|
||||
if (!a)
|
||||
return NULL;
|
||||
if (b->d)
|
||||
OPENSSL_free(b->d);
|
||||
b->d = a;
|
||||
b->dmax = words;
|
||||
}
|
||||
|
||||
/* None of this should be necessary because of what b->top means! */
|
||||
#if 0
|
||||
/*
|
||||
* NB: bn_wexpand() calls this only if the BIGNUM really has to grow
|
||||
*/
|
||||
if (b->top < b->dmax) {
|
||||
int i;
|
||||
BN_ULONG *A = &(b->d[b->top]);
|
||||
for (i = (b->dmax - b->top) >> 3; i > 0; i--, A += 8) {
|
||||
A[0] = 0;
|
||||
A[1] = 0;
|
||||
A[2] = 0;
|
||||
A[3] = 0;
|
||||
A[4] = 0;
|
||||
A[5] = 0;
|
||||
A[6] = 0;
|
||||
A[7] = 0;
|
||||
}
|
||||
for (i = (b->dmax - b->top) & 7; i > 0; i--, A++)
|
||||
A[0] = 0;
|
||||
assert(A == &(b->d[b->dmax]));
|
||||
}
|
||||
#endif
|
||||
bn_check_top(b);
|
||||
return b;
|
||||
}
|
||||
|
||||
BIGNUM *BN_dup(const BIGNUM *a)
|
||||
{
|
||||
BIGNUM *t;
|
||||
|
||||
if (a == NULL)
|
||||
return NULL;
|
||||
bn_check_top(a);
|
||||
|
||||
t = BN_new();
|
||||
if (t == NULL)
|
||||
return NULL;
|
||||
if (!BN_copy(t, a)) {
|
||||
BN_free(t);
|
||||
return NULL;
|
||||
}
|
||||
bn_check_top(t);
|
||||
return t;
|
||||
}
|
||||
|
||||
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
int i;
|
||||
BN_ULONG *A;
|
||||
const BN_ULONG *B;
|
||||
|
||||
bn_check_top(b);
|
||||
|
||||
if (a == b)
|
||||
return (a);
|
||||
if (bn_wexpand(a, b->top) == NULL)
|
||||
return (NULL);
|
||||
|
||||
#if 1
|
||||
A = a->d;
|
||||
B = b->d;
|
||||
for (i = b->top >> 2; i > 0; i--, A += 4, B += 4) {
|
||||
BN_ULONG a0, a1, a2, a3;
|
||||
a0 = B[0];
|
||||
a1 = B[1];
|
||||
a2 = B[2];
|
||||
a3 = B[3];
|
||||
A[0] = a0;
|
||||
A[1] = a1;
|
||||
A[2] = a2;
|
||||
A[3] = a3;
|
||||
}
|
||||
/* ultrix cc workaround, see comments in bn_expand_internal */
|
||||
switch (b->top & 3) {
|
||||
case 3:
|
||||
A[2] = B[2];
|
||||
case 2:
|
||||
A[1] = B[1];
|
||||
case 1:
|
||||
A[0] = B[0];
|
||||
case 0:;
|
||||
}
|
||||
#else
|
||||
memcpy(a->d, b->d, sizeof(b->d[0]) * b->top);
|
||||
#endif
|
||||
|
||||
a->top = b->top;
|
||||
a->neg = b->neg;
|
||||
bn_check_top(a);
|
||||
return (a);
|
||||
}
|
||||
|
||||
void BN_swap(BIGNUM *a, BIGNUM *b)
|
||||
{
|
||||
int flags_old_a, flags_old_b;
|
||||
BN_ULONG *tmp_d;
|
||||
int tmp_top, tmp_dmax, tmp_neg;
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
|
||||
flags_old_a = a->flags;
|
||||
flags_old_b = b->flags;
|
||||
|
||||
tmp_d = a->d;
|
||||
tmp_top = a->top;
|
||||
tmp_dmax = a->dmax;
|
||||
tmp_neg = a->neg;
|
||||
|
||||
a->d = b->d;
|
||||
a->top = b->top;
|
||||
a->dmax = b->dmax;
|
||||
a->neg = b->neg;
|
||||
|
||||
b->d = tmp_d;
|
||||
b->top = tmp_top;
|
||||
b->dmax = tmp_dmax;
|
||||
b->neg = tmp_neg;
|
||||
|
||||
a->flags =
|
||||
(flags_old_a & BN_FLG_MALLOCED) | (flags_old_b & BN_FLG_STATIC_DATA);
|
||||
b->flags =
|
||||
(flags_old_b & BN_FLG_MALLOCED) | (flags_old_a & BN_FLG_STATIC_DATA);
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
}
|
||||
|
||||
void BN_clear(BIGNUM *a)
|
||||
{
|
||||
bn_check_top(a);
|
||||
if (a->d != NULL)
|
||||
memset(a->d, 0, a->dmax * sizeof(a->d[0]));
|
||||
a->top = 0;
|
||||
a->neg = 0;
|
||||
}
|
||||
|
||||
BN_ULONG BN_get_word(const BIGNUM *a)
|
||||
{
|
||||
if (a->top > 1)
|
||||
return BN_MASK2;
|
||||
else if (a->top == 1)
|
||||
return a->d[0];
|
||||
/* a->top == 0 */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BN_set_word(BIGNUM *a, BN_ULONG w)
|
||||
{
|
||||
bn_check_top(a);
|
||||
if (bn_expand(a, (int)sizeof(BN_ULONG) * 8) == NULL)
|
||||
return (0);
|
||||
a->neg = 0;
|
||||
a->d[0] = w;
|
||||
a->top = (w ? 1 : 0);
|
||||
bn_check_top(a);
|
||||
return (1);
|
||||
}
|
||||
|
||||
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
|
||||
{
|
||||
unsigned int i, m;
|
||||
unsigned int n;
|
||||
BN_ULONG l;
|
||||
BIGNUM *bn = NULL;
|
||||
|
||||
if (ret == NULL)
|
||||
ret = bn = BN_new();
|
||||
if (ret == NULL)
|
||||
return (NULL);
|
||||
bn_check_top(ret);
|
||||
l = 0;
|
||||
n = len;
|
||||
if (n == 0) {
|
||||
ret->top = 0;
|
||||
return (ret);
|
||||
}
|
||||
i = ((n - 1) / BN_BYTES) + 1;
|
||||
m = ((n - 1) % (BN_BYTES));
|
||||
if (bn_wexpand(ret, (int)i) == NULL) {
|
||||
if (bn)
|
||||
BN_free(bn);
|
||||
return NULL;
|
||||
}
|
||||
ret->top = i;
|
||||
ret->neg = 0;
|
||||
while (n--) {
|
||||
l = (l << 8L) | *(s++);
|
||||
if (m-- == 0) {
|
||||
ret->d[--i] = l;
|
||||
l = 0;
|
||||
m = BN_BYTES - 1;
|
||||
}
|
||||
}
|
||||
/*
|
||||
* need to call this due to clear byte at top if avoiding having the top
|
||||
* bit set (-ve number)
|
||||
*/
|
||||
bn_correct_top(ret);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* ignore negative */
|
||||
int BN_bn2bin(const BIGNUM *a, unsigned char *to)
|
||||
{
|
||||
int n, i;
|
||||
BN_ULONG l;
|
||||
|
||||
bn_check_top(a);
|
||||
n = i = BN_num_bytes(a);
|
||||
while (i--) {
|
||||
l = a->d[i / BN_BYTES];
|
||||
*(to++) = (unsigned char)(l >> (8 * (i % BN_BYTES))) & 0xff;
|
||||
}
|
||||
return (n);
|
||||
}
|
||||
|
||||
int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
int i;
|
||||
BN_ULONG t1, t2, *ap, *bp;
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
|
||||
i = a->top - b->top;
|
||||
if (i != 0)
|
||||
return (i);
|
||||
ap = a->d;
|
||||
bp = b->d;
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
t1 = ap[i];
|
||||
t2 = bp[i];
|
||||
if (t1 != t2)
|
||||
return ((t1 > t2) ? 1 : -1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int BN_cmp(const BIGNUM *a, const BIGNUM *b)
|
||||
{
|
||||
int i;
|
||||
int gt, lt;
|
||||
BN_ULONG t1, t2;
|
||||
|
||||
if ((a == NULL) || (b == NULL)) {
|
||||
if (a != NULL)
|
||||
return (-1);
|
||||
else if (b != NULL)
|
||||
return (1);
|
||||
else
|
||||
return (0);
|
||||
}
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
|
||||
if (a->neg != b->neg) {
|
||||
if (a->neg)
|
||||
return (-1);
|
||||
else
|
||||
return (1);
|
||||
}
|
||||
if (a->neg == 0) {
|
||||
gt = 1;
|
||||
lt = -1;
|
||||
} else {
|
||||
gt = -1;
|
||||
lt = 1;
|
||||
}
|
||||
|
||||
if (a->top > b->top)
|
||||
return (gt);
|
||||
if (a->top < b->top)
|
||||
return (lt);
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
t1 = a->d[i];
|
||||
t2 = b->d[i];
|
||||
if (t1 > t2)
|
||||
return (gt);
|
||||
if (t1 < t2)
|
||||
return (lt);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
int BN_set_bit(BIGNUM *a, int n)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
if (n < 0)
|
||||
return 0;
|
||||
|
||||
i = n / BN_BITS2;
|
||||
j = n % BN_BITS2;
|
||||
if (a->top <= i) {
|
||||
if (bn_wexpand(a, i + 1) == NULL)
|
||||
return (0);
|
||||
for (k = a->top; k < i + 1; k++)
|
||||
a->d[k] = 0;
|
||||
a->top = i + 1;
|
||||
}
|
||||
|
||||
a->d[i] |= (((BN_ULONG)1) << j);
|
||||
bn_check_top(a);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int BN_clear_bit(BIGNUM *a, int n)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
bn_check_top(a);
|
||||
if (n < 0)
|
||||
return 0;
|
||||
|
||||
i = n / BN_BITS2;
|
||||
j = n % BN_BITS2;
|
||||
if (a->top <= i)
|
||||
return (0);
|
||||
|
||||
a->d[i] &= (~(((BN_ULONG)1) << j));
|
||||
bn_correct_top(a);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int BN_is_bit_set(const BIGNUM *a, int n)
|
||||
{
|
||||
int i, j;
|
||||
|
||||
bn_check_top(a);
|
||||
if (n < 0)
|
||||
return 0;
|
||||
i = n / BN_BITS2;
|
||||
j = n % BN_BITS2;
|
||||
if (a->top <= i)
|
||||
return 0;
|
||||
return (((a->d[i]) >> j) & ((BN_ULONG)1));
|
||||
}
|
||||
|
||||
int BN_mask_bits(BIGNUM *a, int n)
|
||||
{
|
||||
int b, w;
|
||||
|
||||
bn_check_top(a);
|
||||
if (n < 0)
|
||||
return 0;
|
||||
|
||||
w = n / BN_BITS2;
|
||||
b = n % BN_BITS2;
|
||||
if (w >= a->top)
|
||||
return 0;
|
||||
if (b == 0)
|
||||
a->top = w;
|
||||
else {
|
||||
a->top = w + 1;
|
||||
a->d[w] &= ~(BN_MASK2 << b);
|
||||
}
|
||||
bn_correct_top(a);
|
||||
return (1);
|
||||
}
|
||||
|
||||
void BN_set_negative(BIGNUM *a, int b)
|
||||
{
|
||||
if (b && !BN_is_zero(a))
|
||||
a->neg = 1;
|
||||
else
|
||||
a->neg = 0;
|
||||
}
|
||||
|
||||
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
|
||||
{
|
||||
int i;
|
||||
BN_ULONG aa, bb;
|
||||
|
||||
aa = a[n - 1];
|
||||
bb = b[n - 1];
|
||||
if (aa != bb)
|
||||
return ((aa > bb) ? 1 : -1);
|
||||
for (i = n - 2; i >= 0; i--) {
|
||||
aa = a[i];
|
||||
bb = b[i];
|
||||
if (aa != bb)
|
||||
return ((aa > bb) ? 1 : -1);
|
||||
}
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Here follows a specialised variants of bn_cmp_words(). It has the
|
||||
* property of performing the operation on arrays of different sizes. The
|
||||
* sizes of those arrays is expressed through cl, which is the common length
|
||||
* ( basicall, min(len(a),len(b)) ), and dl, which is the delta between the
|
||||
* two lengths, calculated as len(a)-len(b). All lengths are the number of
|
||||
* BN_ULONGs...
|
||||
*/
|
||||
|
||||
int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, int cl, int dl)
|
||||
{
|
||||
int n, i;
|
||||
n = cl - 1;
|
||||
|
||||
if (dl < 0) {
|
||||
for (i = dl; i < 0; i++) {
|
||||
if (b[n - i] != 0)
|
||||
return -1; /* a < b */
|
||||
}
|
||||
}
|
||||
if (dl > 0) {
|
||||
for (i = dl; i > 0; i--) {
|
||||
if (a[n + i] != 0)
|
||||
return 1; /* a > b */
|
||||
}
|
||||
}
|
||||
return bn_cmp_words(a, b, cl);
|
||||
}
|
||||
@@ -0,0 +1,319 @@
|
||||
/* crypto/bn/bn_mod.c */
|
||||
/*
|
||||
* Includes code written by Lenka Fibikova <fibikova@exp-math.uni-essen.de>
|
||||
* for the OpenSSL project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
#if 0 /* now just a #define */
|
||||
int BN_mod(BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
|
||||
{
|
||||
return (BN_div(NULL, rem, m, d, ctx));
|
||||
/* note that rem->neg == m->neg (unless the remainder is zero) */
|
||||
}
|
||||
#endif
|
||||
|
||||
int BN_nnmod(BIGNUM *r, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx)
|
||||
{
|
||||
/*
|
||||
* like BN_mod, but returns non-negative remainder (i.e., 0 <= r < |d|
|
||||
* always holds)
|
||||
*/
|
||||
|
||||
if (!(BN_mod(r, m, d, ctx)))
|
||||
return 0;
|
||||
if (!r->neg)
|
||||
return 1;
|
||||
/* now -|d| < r < 0, so we have to set r := r + |d| */
|
||||
return (d->neg ? BN_sub : BN_add) (r, r, d);
|
||||
}
|
||||
|
||||
int BN_mod_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
if (!BN_add(r, a, b))
|
||||
return 0;
|
||||
return BN_nnmod(r, r, m, ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* BN_mod_add variant that may be used if both a and b are non-negative and
|
||||
* less than m
|
||||
*/
|
||||
int BN_mod_add_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
const BIGNUM *m)
|
||||
{
|
||||
if (!BN_uadd(r, a, b))
|
||||
return 0;
|
||||
if (BN_ucmp(r, m) >= 0)
|
||||
return BN_usub(r, r, m);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_mod_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
if (!BN_sub(r, a, b))
|
||||
return 0;
|
||||
return BN_nnmod(r, r, m, ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* BN_mod_sub variant that may be used if both a and b are non-negative and
|
||||
* less than m
|
||||
*/
|
||||
int BN_mod_sub_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
const BIGNUM *m)
|
||||
{
|
||||
if (!BN_sub(r, a, b))
|
||||
return 0;
|
||||
if (r->neg)
|
||||
return BN_add(r, r, m);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* slow but works */
|
||||
int BN_mod_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, const BIGNUM *m,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *t;
|
||||
int ret = 0;
|
||||
|
||||
bn_check_top(a);
|
||||
bn_check_top(b);
|
||||
bn_check_top(m);
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if ((t = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
if (a == b) {
|
||||
if (!BN_sqr(t, a, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_mul(t, a, b, ctx))
|
||||
goto err;
|
||||
}
|
||||
if (!BN_nnmod(r, t, m, ctx))
|
||||
goto err;
|
||||
bn_check_top(r);
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int BN_mod_sqr(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
|
||||
{
|
||||
if (!BN_sqr(r, a, ctx))
|
||||
return 0;
|
||||
/* r->neg == 0, thus we don't need BN_nnmod */
|
||||
return BN_mod(r, r, m, ctx);
|
||||
}
|
||||
|
||||
int BN_mod_lshift1(BIGNUM *r, const BIGNUM *a, const BIGNUM *m, BN_CTX *ctx)
|
||||
{
|
||||
if (!BN_lshift1(r, a))
|
||||
return 0;
|
||||
bn_check_top(r);
|
||||
return BN_nnmod(r, r, m, ctx);
|
||||
}
|
||||
|
||||
/*
|
||||
* BN_mod_lshift1 variant that may be used if a is non-negative and less than
|
||||
* m
|
||||
*/
|
||||
int BN_mod_lshift1_quick(BIGNUM *r, const BIGNUM *a, const BIGNUM *m)
|
||||
{
|
||||
if (!BN_lshift1(r, a)) return 0;
|
||||
bn_check_top(r);
|
||||
if (BN_cmp(r, m) >= 0)
|
||||
return BN_sub(r, r, m);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int BN_mod_lshift(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m, BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *abs_m = NULL;
|
||||
int ret;
|
||||
|
||||
if (!BN_nnmod(r, a, m, ctx)) return 0;
|
||||
|
||||
if (m->neg)
|
||||
{
|
||||
abs_m = BN_dup(m);
|
||||
if (abs_m == NULL) return 0;
|
||||
abs_m->neg = 0;
|
||||
}
|
||||
|
||||
ret = BN_mod_lshift_quick(r, r, n, (abs_m ? abs_m : m));
|
||||
bn_check_top(r);
|
||||
|
||||
if (abs_m)
|
||||
BN_free(abs_m);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* BN_mod_lshift variant that may be used if a is non-negative and less than
|
||||
* m
|
||||
*/
|
||||
int BN_mod_lshift_quick(BIGNUM *r, const BIGNUM *a, int n, const BIGNUM *m)
|
||||
{
|
||||
if (r != a)
|
||||
{
|
||||
if (BN_copy(r, a) == NULL) return 0;
|
||||
}
|
||||
|
||||
while (n > 0)
|
||||
{
|
||||
int max_shift;
|
||||
|
||||
/* 0 < r < m */
|
||||
max_shift = BN_num_bits(m) - BN_num_bits(r);
|
||||
/* max_shift >= 0 */
|
||||
|
||||
if (max_shift < 0)
|
||||
{
|
||||
BNerr(BN_F_BN_MOD_LSHIFT_QUICK, BN_R_INPUT_NOT_REDUCED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (max_shift > n)
|
||||
max_shift = n;
|
||||
|
||||
if (max_shift)
|
||||
{
|
||||
if (!BN_lshift(r, r, max_shift)) return 0;
|
||||
n -= max_shift;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!BN_lshift1(r, r)) return 0;
|
||||
--n;
|
||||
}
|
||||
|
||||
/* BN_num_bits(r) <= BN_num_bits(m) */
|
||||
|
||||
if (BN_cmp(r, m) >= 0)
|
||||
{
|
||||
if (!BN_sub(r, r, m)) return 0;
|
||||
}
|
||||
}
|
||||
bn_check_top(r);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,768 @@
|
||||
/* crypto/bn/bn_mont.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2006 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Details about Montgomery multiplication algorithms can be found at
|
||||
* http://security.ece.orst.edu/publications.html, e.g.
|
||||
* http://security.ece.orst.edu/koc/papers/j37acmon.pdf and
|
||||
* sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
#define MONT_WORD /* use the faster word-based algorithm */
|
||||
|
||||
#if defined(MONT_WORD) && defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)
|
||||
/*
|
||||
* This condition means we have a specific non-default build: In the 0.9.8
|
||||
* branch, OPENSSL_BN_ASM_MONT is normally not set for any BN_BITS2<=32
|
||||
* platform; an explicit "enable-montasm" is required. I.e., if we are here,
|
||||
* the user intentionally deviates from the normal stable build to get better
|
||||
* Montgomery performance from the 0.9.9-dev backport. In this case only, we
|
||||
* also enable BN_from_montgomery_word() (another non-stable feature from
|
||||
* 0.9.9-dev).
|
||||
*/
|
||||
# define MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
|
||||
#endif
|
||||
|
||||
#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
|
||||
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
|
||||
#endif
|
||||
|
||||
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
|
||||
BN_MONT_CTX *mont, BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *tmp;
|
||||
int ret = 0;
|
||||
#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
|
||||
int num = mont->N.top;
|
||||
|
||||
if (num > 1 && a->top == num && b->top == num) {
|
||||
if (bn_wexpand(r, num) == NULL)
|
||||
return (0);
|
||||
# if 0 /* for OpenSSL 0.9.9 mont->n0 */
|
||||
if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num))
|
||||
# else
|
||||
if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, &mont->n0, num))
|
||||
# endif
|
||||
{
|
||||
r->neg = a->neg ^ b->neg;
|
||||
r->top = num;
|
||||
bn_correct_top(r);
|
||||
return (1);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
if (tmp == NULL)
|
||||
goto err;
|
||||
|
||||
bn_check_top(tmp);
|
||||
if (a == b) {
|
||||
if (!BN_sqr(tmp, a, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_mul(tmp, a, b, ctx))
|
||||
goto err;
|
||||
}
|
||||
/* reduce from aRR to aR */
|
||||
#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
|
||||
if (!BN_from_montgomery_word(r, tmp, mont))
|
||||
goto err;
|
||||
#else
|
||||
if (!BN_from_montgomery(r, tmp, mont, ctx))
|
||||
goto err;
|
||||
#endif
|
||||
bn_check_top(r);
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
#ifdef MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD
|
||||
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
|
||||
{
|
||||
BIGNUM *n;
|
||||
BN_ULONG *ap, *np, *rp, n0, v, *nrp;
|
||||
int al, nl, max, i, x, ri;
|
||||
|
||||
n = &(mont->N);
|
||||
/*
|
||||
* mont->ri is the size of mont->N in bits (rounded up to the word size)
|
||||
*/
|
||||
al = ri = mont->ri / BN_BITS2;
|
||||
|
||||
nl = n->top;
|
||||
if ((al == 0) || (nl == 0)) {
|
||||
ret->top = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
max = (nl + al + 1); /* allow for overflow (no?) XXX */
|
||||
if (bn_wexpand(r, max) == NULL)
|
||||
return (0);
|
||||
|
||||
r->neg ^= n->neg;
|
||||
np = n->d;
|
||||
rp = r->d;
|
||||
nrp = &(r->d[nl]);
|
||||
|
||||
/* clear the top words of T */
|
||||
for (i = r->top; i < max; i++) /* memset? XXX */
|
||||
r->d[i] = 0;
|
||||
|
||||
r->top = max;
|
||||
# if 0 /* for OpenSSL 0.9.9 mont->n0 */
|
||||
n0 = mont->n0[0];
|
||||
# else
|
||||
n0 = mont->n0;
|
||||
# endif
|
||||
|
||||
#ifdef BN_COUNT
|
||||
fprintf(stderr,"word BN_from_montgomery_word %d * %d\n",nl,nl);
|
||||
#endif
|
||||
for (i=0; i<nl; i++)
|
||||
{
|
||||
#ifdef __TANDEM
|
||||
{
|
||||
long long t1;
|
||||
long long t2;
|
||||
long long t3;
|
||||
t1 = rp[0] * (n0 & 0177777);
|
||||
t2 = 037777600000l;
|
||||
t2 = n0 & t2;
|
||||
t3 = rp[0] & 0177777;
|
||||
t2 = (t3 * t2) & BN_MASK2;
|
||||
t1 = t1 + t2;
|
||||
v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
|
||||
}
|
||||
#else
|
||||
v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
|
||||
#endif
|
||||
nrp++;
|
||||
rp++;
|
||||
if (((nrp[-1]+=v)&BN_MASK2) >= v)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
if (((++nrp[0])&BN_MASK2) != 0) continue;
|
||||
if (((++nrp[1])&BN_MASK2) != 0) continue;
|
||||
for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
|
||||
}
|
||||
}
|
||||
bn_correct_top(r);
|
||||
|
||||
/* mont->ri will be a multiple of the word size and below code
|
||||
* is kind of BN_rshift(ret,r,mont->ri) equivalent */
|
||||
if (r->top <= ri)
|
||||
{
|
||||
ret->top=0;
|
||||
return(1);
|
||||
}
|
||||
al=r->top-ri;
|
||||
|
||||
if (bn_wexpand(ret,ri) == NULL) return(0);
|
||||
x=0-(((al-ri)>>(sizeof(al)*8-1))&1);
|
||||
ret->top=x=(ri&~x)|(al&x); /* min(ri,al) */
|
||||
ret->neg=r->neg;
|
||||
|
||||
rp=ret->d;
|
||||
ap=&(r->d[ri]);
|
||||
|
||||
{
|
||||
size_t m1,m2;
|
||||
|
||||
v=bn_sub_words(rp,ap,np,ri);
|
||||
/* this ----------------^^ works even in al<ri case
|
||||
* thanks to zealous zeroing of top of the vector in the
|
||||
* beginning. */
|
||||
|
||||
/* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
|
||||
/* in other words if subtraction result is real, then
|
||||
* trick unconditional memcpy below to perform in-place
|
||||
* "refresh" instead of actual copy. */
|
||||
m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1); /* al<ri */
|
||||
m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1); /* al>ri */
|
||||
m1|=m2; /* (al!=ri) */
|
||||
m1|=(0-(size_t)v); /* (al!=ri || v) */
|
||||
m1&=~m2; /* (al!=ri || v) && !al>ri */
|
||||
nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1));
|
||||
}
|
||||
|
||||
/* 'i<ri' is chosen to eliminate dependency on input data, even
|
||||
* though it results in redundant copy in al<ri case. */
|
||||
for (i=0,ri-=4; i<ri; i+=4)
|
||||
{
|
||||
BN_ULONG t1,t2,t3,t4;
|
||||
|
||||
t1=nrp[i+0];
|
||||
t2=nrp[i+1];
|
||||
t3=nrp[i+2]; ap[i+0]=0;
|
||||
t4=nrp[i+3]; ap[i+1]=0;
|
||||
rp[i+0]=t1; ap[i+2]=0;
|
||||
rp[i+1]=t2; ap[i+3]=0;
|
||||
rp[i+2]=t3;
|
||||
rp[i+3]=t4;
|
||||
}
|
||||
for (ri+=4; i<ri; i++)
|
||||
rp[i]=nrp[i], ap[i]=0;
|
||||
bn_correct_top(r);
|
||||
bn_correct_top(ret);
|
||||
bn_check_top(ret);
|
||||
|
||||
return (1);
|
||||
}
|
||||
|
||||
int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int retn = 0;
|
||||
BIGNUM *t;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if ((t = BN_CTX_get(ctx)) && BN_copy(t, a))
|
||||
retn = BN_from_montgomery_word(ret, t, mont);
|
||||
BN_CTX_end(ctx);
|
||||
return retn;
|
||||
}
|
||||
|
||||
#else /* !MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD */
|
||||
|
||||
int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int retn=0;
|
||||
|
||||
#ifdef MONT_WORD
|
||||
BIGNUM *n,*r;
|
||||
BN_ULONG *ap,*np,*rp,n0,v,*nrp;
|
||||
int al,nl,max,i,x,ri;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if ((r = BN_CTX_get(ctx)) == NULL) goto err;
|
||||
|
||||
if (!BN_copy(r,a)) goto err;
|
||||
n= &(mont->N);
|
||||
|
||||
ap=a->d;
|
||||
/* mont->ri is the size of mont->N in bits (rounded up
|
||||
to the word size) */
|
||||
al=ri=mont->ri/BN_BITS2;
|
||||
|
||||
nl=n->top;
|
||||
if ((al == 0) || (nl == 0)) { r->top=0; return(1); }
|
||||
|
||||
max=(nl+al+1); /* allow for overflow (no?) XXX */
|
||||
if (bn_wexpand(r,max) == NULL) goto err;
|
||||
|
||||
r->neg=a->neg^n->neg;
|
||||
np=n->d;
|
||||
rp=r->d;
|
||||
nrp= &(r->d[nl]);
|
||||
|
||||
/* clear the top words of T */
|
||||
#if 1
|
||||
for (i=r->top; i<max; i++) /* memset? XXX */
|
||||
r->d[i]=0;
|
||||
#else
|
||||
memset(&(r->d[r->top]),0,(max-r->top)*sizeof(BN_ULONG));
|
||||
#endif
|
||||
|
||||
r->top=max;
|
||||
n0=mont->n0;
|
||||
|
||||
#ifdef BN_COUNT
|
||||
fprintf(stderr,"word BN_from_montgomery %d * %d\n",nl,nl);
|
||||
#endif
|
||||
for (i=0; i<nl; i++)
|
||||
{
|
||||
#ifdef __TANDEM
|
||||
{
|
||||
long long t1;
|
||||
long long t2;
|
||||
long long t3;
|
||||
t1 = rp[0] * (n0 & 0177777);
|
||||
t2 = 037777600000l;
|
||||
t2 = n0 & t2;
|
||||
t3 = rp[0] & 0177777;
|
||||
t2 = (t3 * t2) & BN_MASK2;
|
||||
t1 = t1 + t2;
|
||||
v=bn_mul_add_words(rp,np,nl,(BN_ULONG) t1);
|
||||
}
|
||||
#else
|
||||
v=bn_mul_add_words(rp,np,nl,(rp[0]*n0)&BN_MASK2);
|
||||
#endif
|
||||
nrp++;
|
||||
rp++;
|
||||
if (((nrp[-1]+=v)&BN_MASK2) >= v)
|
||||
continue;
|
||||
else
|
||||
{
|
||||
if (((++nrp[0])&BN_MASK2) != 0) continue;
|
||||
if (((++nrp[1])&BN_MASK2) != 0) continue;
|
||||
for (x=2; (((++nrp[x])&BN_MASK2) == 0); x++) ;
|
||||
}
|
||||
}
|
||||
bn_correct_top(r);
|
||||
|
||||
/* mont->ri will be a multiple of the word size and below code
|
||||
* is kind of BN_rshift(ret,r,mont->ri) equivalent */
|
||||
if (r->top <= ri)
|
||||
{
|
||||
ret->top=0;
|
||||
retn=1;
|
||||
goto err;
|
||||
}
|
||||
al=r->top-ri;
|
||||
|
||||
# define BRANCH_FREE 1
|
||||
# if BRANCH_FREE
|
||||
if (bn_wexpand(ret,ri) == NULL) goto err;
|
||||
x=0-(((al-ri)>>(sizeof(al)*8-1))&1);
|
||||
ret->top=x=(ri&~x)|(al&x); /* min(ri,al) */
|
||||
ret->neg=r->neg;
|
||||
|
||||
rp=ret->d;
|
||||
ap=&(r->d[ri]);
|
||||
|
||||
{
|
||||
size_t m1,m2;
|
||||
|
||||
v=bn_sub_words(rp,ap,np,ri);
|
||||
/* this ----------------^^ works even in al<ri case
|
||||
* thanks to zealous zeroing of top of the vector in the
|
||||
* beginning. */
|
||||
|
||||
/* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
|
||||
/* in other words if subtraction result is real, then
|
||||
* trick unconditional memcpy below to perform in-place
|
||||
* "refresh" instead of actual copy. */
|
||||
m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1); /* al<ri */
|
||||
m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1); /* al>ri */
|
||||
m1|=m2; /* (al!=ri) */
|
||||
m1|=(0-(size_t)v); /* (al!=ri || v) */
|
||||
m1&=~m2; /* (al!=ri || v) && !al>ri */
|
||||
nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1));
|
||||
}
|
||||
|
||||
/* 'i<ri' is chosen to eliminate dependency on input data, even
|
||||
* though it results in redundant copy in al<ri case. */
|
||||
for (i=0,ri-=4; i<ri; i+=4)
|
||||
{
|
||||
BN_ULONG t1,t2,t3,t4;
|
||||
|
||||
t1=nrp[i+0];
|
||||
t2=nrp[i+1];
|
||||
t3=nrp[i+2]; ap[i+0]=0;
|
||||
t4=nrp[i+3]; ap[i+1]=0;
|
||||
rp[i+0]=t1; ap[i+2]=0;
|
||||
rp[i+1]=t2; ap[i+3]=0;
|
||||
rp[i+2]=t3;
|
||||
rp[i+3]=t4;
|
||||
}
|
||||
for (ri+=4; i<ri; i++)
|
||||
rp[i]=nrp[i], ap[i]=0;
|
||||
bn_correct_top(r);
|
||||
bn_correct_top(ret);
|
||||
# else
|
||||
if (bn_wexpand(ret,al) == NULL) goto err;
|
||||
ret->top=al;
|
||||
ret->neg=r->neg;
|
||||
|
||||
rp=ret->d;
|
||||
ap=&(r->d[ri]);
|
||||
al-=4;
|
||||
for (i=0; i<al; i+=4)
|
||||
{
|
||||
BN_ULONG t1,t2,t3,t4;
|
||||
|
||||
t1=ap[i+0];
|
||||
t2=ap[i+1];
|
||||
t3=ap[i+2];
|
||||
t4=ap[i+3];
|
||||
rp[i+0]=t1;
|
||||
rp[i+1]=t2;
|
||||
rp[i+2]=t3;
|
||||
rp[i+3]=t4;
|
||||
}
|
||||
al+=4;
|
||||
for (; i<al; i++)
|
||||
rp[i]=ap[i];
|
||||
# endif
|
||||
#else /* !MONT_WORD */
|
||||
BIGNUM *t1,*t2;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
t1 = BN_CTX_get(ctx);
|
||||
t2 = BN_CTX_get(ctx);
|
||||
if (t1 == NULL || t2 == NULL) goto err;
|
||||
|
||||
if (!BN_copy(t1,a)) goto err;
|
||||
BN_mask_bits(t1,mont->ri);
|
||||
|
||||
if (!BN_mul(t2,t1,&mont->Ni,ctx)) goto err;
|
||||
BN_mask_bits(t2,mont->ri);
|
||||
|
||||
if (!BN_mul(t1,t2,&mont->N,ctx)) goto err;
|
||||
if (!BN_add(t2,a,t1)) goto err;
|
||||
if (!BN_rshift(ret,t2,mont->ri)) goto err;
|
||||
#endif /* MONT_WORD */
|
||||
|
||||
#if !defined(BRANCH_FREE) || BRANCH_FREE==0
|
||||
if (BN_ucmp(ret, &(mont->N)) >= 0)
|
||||
{
|
||||
if (!BN_usub(ret,ret,&(mont->N))) goto err;
|
||||
}
|
||||
#endif
|
||||
retn=1;
|
||||
bn_check_top(ret);
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return (retn);
|
||||
}
|
||||
#endif /* MONT_FROM_WORD___NON_DEFAULT_0_9_8_BUILD */
|
||||
|
||||
BN_MONT_CTX *BN_MONT_CTX_new(void)
|
||||
{
|
||||
BN_MONT_CTX *ret;
|
||||
|
||||
if ((ret = (BN_MONT_CTX *)OPENSSL_malloc(sizeof(BN_MONT_CTX))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
BN_MONT_CTX_init(ret);
|
||||
ret->flags = BN_FLG_MALLOCED;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void BN_MONT_CTX_init(BN_MONT_CTX *ctx)
|
||||
{
|
||||
ctx->ri = 0;
|
||||
BN_init(&(ctx->RR));
|
||||
BN_init(&(ctx->N));
|
||||
BN_init(&(ctx->Ni));
|
||||
#if 0 /* for OpenSSL 0.9.9 mont->n0 */
|
||||
ctx->n0[0] = ctx->n0[1] = 0;
|
||||
#else
|
||||
ctx->n0 = 0;
|
||||
#endif
|
||||
ctx->flags = 0;
|
||||
}
|
||||
|
||||
void BN_MONT_CTX_free(BN_MONT_CTX *mont)
|
||||
{
|
||||
if (mont == NULL)
|
||||
return;
|
||||
|
||||
BN_free(&(mont->RR));
|
||||
BN_free(&(mont->N));
|
||||
BN_free(&(mont->Ni));
|
||||
if (mont->flags & BN_FLG_MALLOCED)
|
||||
OPENSSL_free(mont);
|
||||
}
|
||||
|
||||
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
BIGNUM *Ri, *R;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if ((Ri = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
R = &(mont->RR); /* grab RR as a temp */
|
||||
if (!BN_copy(&(mont->N), mod))
|
||||
goto err; /* Set N */
|
||||
mont->N.neg = 0;
|
||||
|
||||
#ifdef MONT_WORD
|
||||
{
|
||||
BIGNUM tmod;
|
||||
BN_ULONG buf[2];
|
||||
|
||||
mont->ri = (BN_num_bits(mod) + (BN_BITS2 - 1)) / BN_BITS2 * BN_BITS2;
|
||||
BN_zero(R);
|
||||
# if 0 /* for OpenSSL 0.9.9 mont->n0, would be "#if
|
||||
* defined(OPENSSL_BN_ASM_MONT) &&
|
||||
* (BN_BITS2<=32)", only certain BN_BITS2<=32
|
||||
* platforms actually need this */
|
||||
if (!(BN_set_bit(R, 2 * BN_BITS2)))
|
||||
goto err; /* R */
|
||||
# else
|
||||
if (!(BN_set_bit(R, BN_BITS2)))
|
||||
goto err; /* R */
|
||||
# endif
|
||||
|
||||
buf[0] = mod->d[0]; /* tmod = N mod word size */
|
||||
buf[1] = 0;
|
||||
|
||||
BN_init(&tmod);
|
||||
tmod.d = buf;
|
||||
tmod.top = buf[0] != 0 ? 1 : 0;
|
||||
tmod.dmax = 2;
|
||||
tmod.neg = 0;
|
||||
|
||||
# if 0 /* for OpenSSL 0.9.9 mont->n0, would be "#if
|
||||
* defined(OPENSSL_BN_ASM_MONT) &&
|
||||
* (BN_BITS2<=32)"; only certain BN_BITS2<=32
|
||||
* platforms actually need this */
|
||||
tmod.top = 0;
|
||||
if ((buf[0] = mod->d[0]))
|
||||
tmod.top = 1;
|
||||
if ((buf[1] = mod->top > 1 ? mod->d[1] : 0))
|
||||
tmod.top = 2;
|
||||
|
||||
if ((BN_mod_inverse(Ri, R, &tmod, ctx)) == NULL)
|
||||
goto err;
|
||||
if (!BN_lshift(Ri, Ri, 2 * BN_BITS2))
|
||||
goto err; /* R*Ri */
|
||||
if (!BN_is_zero(Ri)) {
|
||||
if (!BN_sub_word(Ri, 1))
|
||||
goto err;
|
||||
} else { /* if N mod word size == 1 */
|
||||
|
||||
if (bn_expand(Ri, (int)sizeof(BN_ULONG) * 2) == NULL)
|
||||
goto err;
|
||||
/* Ri-- (mod double word size) */
|
||||
Ri->neg = 0;
|
||||
Ri->d[0] = BN_MASK2;
|
||||
Ri->d[1] = BN_MASK2;
|
||||
Ri->top = 2;
|
||||
}
|
||||
if (!BN_div(Ri, NULL, Ri, &tmod, ctx))
|
||||
goto err;
|
||||
/*
|
||||
* Ni = (R*Ri-1)/N, keep only couple of least significant words:
|
||||
*/
|
||||
mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
|
||||
mont->n0[1] = (Ri->top > 1) ? Ri->d[1] : 0;
|
||||
# else
|
||||
/* Ri = R^-1 mod N */
|
||||
if ((BN_mod_inverse(Ri, R, &tmod, ctx)) == NULL)
|
||||
goto err;
|
||||
if (!BN_lshift(Ri, Ri, BN_BITS2))
|
||||
goto err; /* R*Ri */
|
||||
if (!BN_is_zero(Ri)) {
|
||||
if (!BN_sub_word(Ri, 1))
|
||||
goto err;
|
||||
} else { /* if N mod word size == 1 */
|
||||
|
||||
if (!BN_set_word(Ri, BN_MASK2))
|
||||
goto err; /* Ri-- (mod word size) */
|
||||
}
|
||||
if (!BN_div(Ri, NULL, Ri, &tmod, ctx))
|
||||
goto err;
|
||||
/*
|
||||
* Ni = (R*Ri-1)/N, keep only least significant word:
|
||||
*/
|
||||
# if 0 /* for OpenSSL 0.9.9 mont->n0 */
|
||||
mont->n0[0] = (Ri->top > 0) ? Ri->d[0] : 0;
|
||||
mont->n0[1] = 0;
|
||||
# else
|
||||
mont->n0 = (Ri->top > 0) ? Ri->d[0] : 0;
|
||||
# endif
|
||||
# endif
|
||||
}
|
||||
#else /* !MONT_WORD */
|
||||
{ /* bignum version */
|
||||
mont->ri = BN_num_bits(&mont->N);
|
||||
BN_zero(R);
|
||||
if (!BN_set_bit(R, mont->ri))
|
||||
goto err; /* R = 2^ri */
|
||||
/* Ri = R^-1 mod N */
|
||||
if ((BN_mod_inverse(Ri, R, &mont->N, ctx)) == NULL)
|
||||
goto err;
|
||||
if (!BN_lshift(Ri, Ri, mont->ri))
|
||||
goto err; /* R*Ri */
|
||||
if (!BN_sub_word(Ri, 1))
|
||||
goto err;
|
||||
/*
|
||||
* Ni = (R*Ri-1) / N
|
||||
*/
|
||||
if (!BN_div(&(mont->Ni), NULL, Ri, &mont->N, ctx))
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* setup RR for conversions */
|
||||
BN_zero(&(mont->RR));
|
||||
if (!BN_set_bit(&(mont->RR), mont->ri * 2))
|
||||
goto err;
|
||||
if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx))
|
||||
goto err;
|
||||
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_MONT_CTX *BN_MONT_CTX_copy(BN_MONT_CTX *to, BN_MONT_CTX *from)
|
||||
{
|
||||
if (to == from)
|
||||
return (to);
|
||||
|
||||
if (!BN_copy(&(to->RR), &(from->RR)))
|
||||
return NULL;
|
||||
if (!BN_copy(&(to->N), &(from->N)))
|
||||
return NULL;
|
||||
if (!BN_copy(&(to->Ni), &(from->Ni)))
|
||||
return NULL;
|
||||
to->ri = from->ri;
|
||||
#if 0 /* for OpenSSL 0.9.9 mont->n0 */
|
||||
to->n0[0] = from->n0[0];
|
||||
to->n0[1] = from->n0[1];
|
||||
#else
|
||||
to->n0 = from->n0;
|
||||
#endif
|
||||
return (to);
|
||||
}
|
||||
|
||||
BN_MONT_CTX *BN_MONT_CTX_set_locked(BN_MONT_CTX **pmont, int lock,
|
||||
const BIGNUM *mod, BN_CTX *ctx)
|
||||
{
|
||||
BN_MONT_CTX *ret;
|
||||
|
||||
CRYPTO_r_lock(lock);
|
||||
ret = *pmont;
|
||||
CRYPTO_r_unlock(lock);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* We don't want to serialise globally while doing our lazy-init math in
|
||||
* BN_MONT_CTX_set. That punishes threads that are doing independent
|
||||
* things. Instead, punish the case where more than one thread tries to
|
||||
* lazy-init the same 'pmont', by having each do the lazy-init math work
|
||||
* independently and only use the one from the thread that wins the race
|
||||
* (the losers throw away the work they've done).
|
||||
*/
|
||||
ret = BN_MONT_CTX_new();
|
||||
if (!ret)
|
||||
return NULL;
|
||||
if (!BN_MONT_CTX_set(ret, mod, ctx)) {
|
||||
BN_MONT_CTX_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* The locked compare-and-set, after the local work is done. */
|
||||
CRYPTO_w_lock(lock);
|
||||
if (*pmont) {
|
||||
BN_MONT_CTX_free(ret);
|
||||
ret = *pmont;
|
||||
} else
|
||||
*pmont = ret;
|
||||
CRYPTO_w_unlock(lock);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,128 @@
|
||||
/* crypto/bn/bn_mpi.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
int BN_bn2mpi(const BIGNUM *a, unsigned char *d)
|
||||
{
|
||||
int bits;
|
||||
int num = 0;
|
||||
int ext = 0;
|
||||
long l;
|
||||
|
||||
bits = BN_num_bits(a);
|
||||
num = (bits + 7) / 8;
|
||||
if (bits > 0) {
|
||||
ext = ((bits & 0x07) == 0);
|
||||
}
|
||||
if (d == NULL)
|
||||
return (num + 4 + ext);
|
||||
|
||||
l = num + ext;
|
||||
d[0] = (unsigned char)(l >> 24) & 0xff;
|
||||
d[1] = (unsigned char)(l >> 16) & 0xff;
|
||||
d[2] = (unsigned char)(l >> 8) & 0xff;
|
||||
d[3] = (unsigned char)(l) & 0xff;
|
||||
if (ext)
|
||||
d[4] = 0;
|
||||
num = BN_bn2bin(a, &(d[4 + ext]));
|
||||
if (a->neg)
|
||||
d[4] |= 0x80;
|
||||
return (num + 4 + ext);
|
||||
}
|
||||
|
||||
BIGNUM *BN_mpi2bn(const unsigned char *d, int n, BIGNUM *a)
|
||||
{
|
||||
long len;
|
||||
int neg = 0;
|
||||
|
||||
if (n < 4) {
|
||||
BNerr(BN_F_BN_MPI2BN, BN_R_INVALID_LENGTH);
|
||||
return (NULL);
|
||||
}
|
||||
len = ((long)d[0] << 24) | ((long)d[1] << 16) | ((int)d[2] << 8) | (int)
|
||||
d[3];
|
||||
if ((len + 4) != n) {
|
||||
BNerr(BN_F_BN_MPI2BN, BN_R_ENCODING_ERROR);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
if (a == NULL)
|
||||
a = BN_new();
|
||||
if (a == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (len == 0) {
|
||||
a->neg = 0;
|
||||
a->top = 0;
|
||||
return (a);
|
||||
}
|
||||
d += 4;
|
||||
if ((*d) & 0x80)
|
||||
neg = 1;
|
||||
if (BN_bin2bn(d, (int)len, a) == NULL)
|
||||
return (NULL);
|
||||
a->neg = neg;
|
||||
if (neg) {
|
||||
BN_clear_bit(a, BN_num_bits(a) - 1);
|
||||
}
|
||||
bn_check_top(a);
|
||||
return (a);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,876 @@
|
||||
/* crypto/bn/bn_nist.c */
|
||||
/*
|
||||
* Written by Nils Larsch for the OpenSSL project
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "bn_lcl.h"
|
||||
#include "cryptlib.h"
|
||||
|
||||
#define BN_NIST_192_TOP (192+BN_BITS2-1)/BN_BITS2
|
||||
#define BN_NIST_224_TOP (224+BN_BITS2-1)/BN_BITS2
|
||||
#define BN_NIST_256_TOP (256+BN_BITS2-1)/BN_BITS2
|
||||
#define BN_NIST_384_TOP (384+BN_BITS2-1)/BN_BITS2
|
||||
#define BN_NIST_521_TOP (521+BN_BITS2-1)/BN_BITS2
|
||||
|
||||
/* pre-computed tables are "carry-less" values of modulus*(i+1) */
|
||||
#if BN_BITS2 == 64
|
||||
static const BN_ULONG _nist_p_192[][BN_NIST_192_TOP] = {
|
||||
{0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFFULL},
|
||||
{0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFFULL},
|
||||
{0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFCULL, 0xFFFFFFFFFFFFFFFFULL}
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_192_sqr[] = {
|
||||
0x0000000000000001ULL, 0x0000000000000002ULL, 0x0000000000000001ULL,
|
||||
0xFFFFFFFFFFFFFFFEULL, 0xFFFFFFFFFFFFFFFDULL, 0xFFFFFFFFFFFFFFFFULL
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_224[][BN_NIST_224_TOP] = {
|
||||
{0x0000000000000001ULL, 0xFFFFFFFF00000000ULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0x00000000FFFFFFFFULL},
|
||||
{0x0000000000000002ULL, 0xFFFFFFFE00000000ULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0x00000001FFFFFFFFULL} /* this one is
|
||||
* "carry-full" */
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_224_sqr[] = {
|
||||
0x0000000000000001ULL, 0xFFFFFFFE00000000ULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0x0000000200000000ULL,
|
||||
0x0000000000000000ULL, 0xFFFFFFFFFFFFFFFEULL,
|
||||
0xFFFFFFFFFFFFFFFFULL
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_256[][BN_NIST_256_TOP] = {
|
||||
{0xFFFFFFFFFFFFFFFFULL, 0x00000000FFFFFFFFULL,
|
||||
0x0000000000000000ULL, 0xFFFFFFFF00000001ULL},
|
||||
{0xFFFFFFFFFFFFFFFEULL, 0x00000001FFFFFFFFULL,
|
||||
0x0000000000000000ULL, 0xFFFFFFFE00000002ULL},
|
||||
{0xFFFFFFFFFFFFFFFDULL, 0x00000002FFFFFFFFULL,
|
||||
0x0000000000000000ULL, 0xFFFFFFFD00000003ULL},
|
||||
{0xFFFFFFFFFFFFFFFCULL, 0x00000003FFFFFFFFULL,
|
||||
0x0000000000000000ULL, 0xFFFFFFFC00000004ULL},
|
||||
{0xFFFFFFFFFFFFFFFBULL, 0x00000004FFFFFFFFULL,
|
||||
0x0000000000000000ULL, 0xFFFFFFFB00000005ULL},
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_256_sqr[] = {
|
||||
0x0000000000000001ULL, 0xFFFFFFFE00000000ULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0x00000001FFFFFFFEULL,
|
||||
0x00000001FFFFFFFEULL, 0x00000001FFFFFFFEULL,
|
||||
0xFFFFFFFE00000001ULL, 0xFFFFFFFE00000002ULL
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_384[][BN_NIST_384_TOP] = {
|
||||
{0x00000000FFFFFFFFULL, 0xFFFFFFFF00000000ULL, 0xFFFFFFFFFFFFFFFEULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL},
|
||||
{0x00000001FFFFFFFEULL, 0xFFFFFFFE00000000ULL, 0xFFFFFFFFFFFFFFFDULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL},
|
||||
{0x00000002FFFFFFFDULL, 0xFFFFFFFD00000000ULL, 0xFFFFFFFFFFFFFFFCULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL},
|
||||
{0x00000003FFFFFFFCULL, 0xFFFFFFFC00000000ULL, 0xFFFFFFFFFFFFFFFBULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL},
|
||||
{0x00000004FFFFFFFBULL, 0xFFFFFFFB00000000ULL, 0xFFFFFFFFFFFFFFFAULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL},
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_384_sqr[] = {
|
||||
0xFFFFFFFE00000001ULL, 0x0000000200000000ULL, 0xFFFFFFFE00000000ULL,
|
||||
0x0000000200000000ULL, 0x0000000000000001ULL, 0x0000000000000000ULL,
|
||||
0x00000001FFFFFFFEULL, 0xFFFFFFFE00000000ULL, 0xFFFFFFFFFFFFFFFDULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_521[] =
|
||||
{ 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
|
||||
0x00000000000001FFULL
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_521_sqr[] = {
|
||||
0x0000000000000001ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
|
||||
0x0000000000000000ULL, 0x0000000000000000ULL, 0x0000000000000000ULL,
|
||||
0x0000000000000000ULL, 0x0000000000000000ULL, 0xFFFFFFFFFFFFFC00ULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL, 0xFFFFFFFFFFFFFFFFULL,
|
||||
0xFFFFFFFFFFFFFFFFULL, 0x000000000003FFFFULL
|
||||
};
|
||||
#elif BN_BITS2 == 32
|
||||
static const BN_ULONG _nist_p_192[][BN_NIST_192_TOP] = {
|
||||
{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
|
||||
{0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
|
||||
{0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_192_sqr[] = {
|
||||
0x00000001, 0x00000000, 0x00000002, 0x00000000, 0x00000001, 0x00000000,
|
||||
0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_224[][BN_NIST_224_TOP] = {
|
||||
{0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
|
||||
{0x00000002, 0x00000000, 0x00000000, 0xFFFFFFFE,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF}
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_224_sqr[] = {
|
||||
0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0x00000000, 0x00000002,
|
||||
0x00000000, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_256[][BN_NIST_256_TOP] = {
|
||||
{0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000001, 0xFFFFFFFF},
|
||||
{0xFFFFFFFE, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000001,
|
||||
0x00000000, 0x00000000, 0x00000002, 0xFFFFFFFE},
|
||||
{0xFFFFFFFD, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000002,
|
||||
0x00000000, 0x00000000, 0x00000003, 0xFFFFFFFD},
|
||||
{0xFFFFFFFC, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000003,
|
||||
0x00000000, 0x00000000, 0x00000004, 0xFFFFFFFC},
|
||||
{0xFFFFFFFB, 0xFFFFFFFF, 0xFFFFFFFF, 0x00000004,
|
||||
0x00000000, 0x00000000, 0x00000005, 0xFFFFFFFB},
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_256_sqr[] = {
|
||||
0x00000001, 0x00000000, 0x00000000, 0xFFFFFFFE,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0x00000001,
|
||||
0xFFFFFFFE, 0x00000001, 0xFFFFFFFE, 0x00000001,
|
||||
0x00000001, 0xFFFFFFFE, 0x00000002, 0xFFFFFFFE
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_384[][BN_NIST_384_TOP] = {
|
||||
{0xFFFFFFFF, 0x00000000, 0x00000000, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
|
||||
{0xFFFFFFFE, 0x00000001, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
|
||||
{0xFFFFFFFD, 0x00000002, 0x00000000, 0xFFFFFFFD, 0xFFFFFFFC, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
|
||||
{0xFFFFFFFC, 0x00000003, 0x00000000, 0xFFFFFFFC, 0xFFFFFFFB, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
|
||||
{0xFFFFFFFB, 0x00000004, 0x00000000, 0xFFFFFFFB, 0xFFFFFFFA, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF},
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_384_sqr[] = {
|
||||
0x00000001, 0xFFFFFFFE, 0x00000000, 0x00000002, 0x00000000, 0xFFFFFFFE,
|
||||
0x00000000, 0x00000002, 0x00000001, 0x00000000, 0x00000000, 0x00000000,
|
||||
0xFFFFFFFE, 0x00000001, 0x00000000, 0xFFFFFFFE, 0xFFFFFFFD, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_521[] = { 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0x000001FF
|
||||
};
|
||||
|
||||
static const BN_ULONG _nist_p_521_sqr[] = {
|
||||
0x00000001, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
|
||||
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0xFFFFFC00, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
|
||||
0xFFFFFFFF, 0xFFFFFFFF, 0x0003FFFF
|
||||
};
|
||||
#else
|
||||
# error "unsupported BN_BITS2"
|
||||
#endif
|
||||
|
||||
static const BIGNUM _bignum_nist_p_192 = {
|
||||
(BN_ULONG *)_nist_p_192[0],
|
||||
BN_NIST_192_TOP,
|
||||
BN_NIST_192_TOP,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BIGNUM _bignum_nist_p_224 = {
|
||||
(BN_ULONG *)_nist_p_224[0],
|
||||
BN_NIST_224_TOP,
|
||||
BN_NIST_224_TOP,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BIGNUM _bignum_nist_p_256 = {
|
||||
(BN_ULONG *)_nist_p_256[0],
|
||||
BN_NIST_256_TOP,
|
||||
BN_NIST_256_TOP,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BIGNUM _bignum_nist_p_384 = {
|
||||
(BN_ULONG *)_nist_p_384[0],
|
||||
BN_NIST_384_TOP,
|
||||
BN_NIST_384_TOP,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
static const BIGNUM _bignum_nist_p_521 = {
|
||||
(BN_ULONG *)_nist_p_521,
|
||||
BN_NIST_521_TOP,
|
||||
BN_NIST_521_TOP,
|
||||
0,
|
||||
BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
const BIGNUM *BN_get0_nist_prime_192(void)
|
||||
{
|
||||
return &_bignum_nist_p_192;
|
||||
}
|
||||
|
||||
const BIGNUM *BN_get0_nist_prime_224(void)
|
||||
{
|
||||
return &_bignum_nist_p_224;
|
||||
}
|
||||
|
||||
const BIGNUM *BN_get0_nist_prime_256(void)
|
||||
{
|
||||
return &_bignum_nist_p_256;
|
||||
}
|
||||
|
||||
const BIGNUM *BN_get0_nist_prime_384(void)
|
||||
{
|
||||
return &_bignum_nist_p_384;
|
||||
}
|
||||
|
||||
const BIGNUM *BN_get0_nist_prime_521(void)
|
||||
{
|
||||
return &_bignum_nist_p_521;
|
||||
}
|
||||
|
||||
static void nist_cp_bn_0(BN_ULONG *buf, BN_ULONG *a, int top, int max)
|
||||
{
|
||||
int i;
|
||||
BN_ULONG *_tmp1 = (buf), *_tmp2 = (a);
|
||||
|
||||
#ifdef BN_DEBUG
|
||||
OPENSSL_assert(top <= max);
|
||||
#endif
|
||||
for (i = (top); i != 0; i--)
|
||||
*_tmp1++ = *_tmp2++;
|
||||
for (i = (max) - (top); i != 0; i--)
|
||||
*_tmp1++ = (BN_ULONG)0;
|
||||
}
|
||||
|
||||
static void nist_cp_bn(BN_ULONG *buf, BN_ULONG *a, int top)
|
||||
{
|
||||
int i;
|
||||
BN_ULONG *_tmp1 = (buf), *_tmp2 = (a);
|
||||
for (i = (top); i != 0; i--)
|
||||
*_tmp1++ = *_tmp2++;
|
||||
}
|
||||
|
||||
#if BN_BITS2 == 64
|
||||
# define bn_cp_64(to, n, from, m) (to)[n] = (m>=0)?((from)[m]):0;
|
||||
# define bn_64_set_0(to, n) (to)[n] = (BN_ULONG)0;
|
||||
/*
|
||||
* two following macros are implemented under assumption that they
|
||||
* are called in a sequence with *ascending* n, i.e. as they are...
|
||||
*/
|
||||
# define bn_cp_32_naked(to, n, from, m) (((n)&1)?(to[(n)/2]|=((m)&1)?(from[(m)/2]&BN_MASK2h):(from[(m)/2]<<32))\
|
||||
:(to[(n)/2] =((m)&1)?(from[(m)/2]>>32):(from[(m)/2]&BN_MASK2l)))
|
||||
# define bn_32_set_0(to, n) (((n)&1)?(to[(n)/2]&=BN_MASK2l):(to[(n)/2]=0));
|
||||
# define bn_cp_32(to,n,from,m) ((m)>=0)?bn_cp_32_naked(to,n,from,m):bn_32_set_0(to,n)
|
||||
#else
|
||||
# define bn_cp_64(to, n, from, m) \
|
||||
{ \
|
||||
bn_cp_32(to, (n)*2, from, (m)*2); \
|
||||
bn_cp_32(to, (n)*2+1, from, (m)*2+1); \
|
||||
}
|
||||
# define bn_64_set_0(to, n) \
|
||||
{ \
|
||||
bn_32_set_0(to, (n)*2); \
|
||||
bn_32_set_0(to, (n)*2+1); \
|
||||
}
|
||||
# if BN_BITS2 == 32
|
||||
# define bn_cp_32(to, n, from, m) (to)[n] = (m>=0)?((from)[m]):0;
|
||||
# define bn_32_set_0(to, n) (to)[n] = (BN_ULONG)0;
|
||||
# endif
|
||||
#endif /* BN_BITS2 != 64 */
|
||||
|
||||
#define nist_set_192(to, from, a1, a2, a3) \
|
||||
{ \
|
||||
bn_cp_64(to, 0, from, (a3) - 3) \
|
||||
bn_cp_64(to, 1, from, (a2) - 3) \
|
||||
bn_cp_64(to, 2, from, (a1) - 3) \
|
||||
}
|
||||
|
||||
int BN_nist_mod_192(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int top = a->top, i;
|
||||
int carry;
|
||||
register BN_ULONG *r_d, *a_d = a->d;
|
||||
BN_ULONG t_d[BN_NIST_192_TOP],
|
||||
buf[BN_NIST_192_TOP], c_d[BN_NIST_192_TOP], *res;
|
||||
size_t mask;
|
||||
static const BIGNUM _bignum_nist_p_192_sqr = {
|
||||
(BN_ULONG *)_nist_p_192_sqr,
|
||||
sizeof(_nist_p_192_sqr) / sizeof(_nist_p_192_sqr[0]),
|
||||
sizeof(_nist_p_192_sqr) / sizeof(_nist_p_192_sqr[0]),
|
||||
0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
field = &_bignum_nist_p_192; /* just to make sure */
|
||||
|
||||
if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_192_sqr) >= 0)
|
||||
return BN_nnmod(r, a, field, ctx);
|
||||
|
||||
i = BN_ucmp(field, a);
|
||||
if (i == 0) {
|
||||
BN_zero(r);
|
||||
return 1;
|
||||
} else if (i > 0)
|
||||
return (r == a) ? 1 : (BN_copy(r, a) != NULL);
|
||||
|
||||
if (r != a) {
|
||||
if (!bn_wexpand(r, BN_NIST_192_TOP))
|
||||
return 0;
|
||||
r_d = r->d;
|
||||
nist_cp_bn(r_d, a_d, BN_NIST_192_TOP);
|
||||
} else
|
||||
r_d = a_d;
|
||||
|
||||
nist_cp_bn_0(buf, a_d + BN_NIST_192_TOP, top - BN_NIST_192_TOP,
|
||||
BN_NIST_192_TOP);
|
||||
|
||||
nist_set_192(t_d, buf, 0, 3, 3);
|
||||
carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
|
||||
nist_set_192(t_d, buf, 4, 4, 0);
|
||||
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
|
||||
nist_set_192(t_d, buf, 5, 5, 5)
|
||||
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_192_TOP);
|
||||
|
||||
if (carry > 0)
|
||||
carry =
|
||||
(int)bn_sub_words(r_d, r_d, _nist_p_192[carry - 1],
|
||||
BN_NIST_192_TOP);
|
||||
else
|
||||
carry = 1;
|
||||
|
||||
/*
|
||||
* we need 'if (carry==0 || result>=modulus) result-=modulus;'
|
||||
* as comparison implies subtraction, we can write
|
||||
* 'tmp=result-modulus; if (!carry || !borrow) result=tmp;'
|
||||
* this is what happens below, but without explicit if:-) a.
|
||||
*/
|
||||
mask =
|
||||
0 - (size_t)bn_sub_words(c_d, r_d, _nist_p_192[0], BN_NIST_192_TOP);
|
||||
mask &= 0 - (size_t)carry;
|
||||
res = (BN_ULONG *)(((size_t)c_d & ~mask) | ((size_t)r_d & mask));
|
||||
nist_cp_bn(r_d, res, BN_NIST_192_TOP);
|
||||
r->top = BN_NIST_192_TOP;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef BN_ULONG (*bn_addsub_f) (BN_ULONG *, const BN_ULONG *,
|
||||
const BN_ULONG *, int);
|
||||
|
||||
#define nist_set_224(to, from, a1, a2, a3, a4, a5, a6, a7) \
|
||||
{ \
|
||||
bn_cp_32(to, 0, from, (a7) - 7) \
|
||||
bn_cp_32(to, 1, from, (a6) - 7) \
|
||||
bn_cp_32(to, 2, from, (a5) - 7) \
|
||||
bn_cp_32(to, 3, from, (a4) - 7) \
|
||||
bn_cp_32(to, 4, from, (a3) - 7) \
|
||||
bn_cp_32(to, 5, from, (a2) - 7) \
|
||||
bn_cp_32(to, 6, from, (a1) - 7) \
|
||||
}
|
||||
|
||||
int BN_nist_mod_224(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int top = a->top, i;
|
||||
int carry;
|
||||
BN_ULONG *r_d, *a_d = a->d;
|
||||
BN_ULONG t_d[BN_NIST_224_TOP],
|
||||
buf[BN_NIST_224_TOP], c_d[BN_NIST_224_TOP], *res;
|
||||
size_t mask;
|
||||
union {
|
||||
bn_addsub_f f;
|
||||
size_t p;
|
||||
} u;
|
||||
static const BIGNUM _bignum_nist_p_224_sqr = {
|
||||
(BN_ULONG *)_nist_p_224_sqr,
|
||||
sizeof(_nist_p_224_sqr) / sizeof(_nist_p_224_sqr[0]),
|
||||
sizeof(_nist_p_224_sqr) / sizeof(_nist_p_224_sqr[0]),
|
||||
0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
field = &_bignum_nist_p_224; /* just to make sure */
|
||||
|
||||
if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_224_sqr) >= 0)
|
||||
return BN_nnmod(r, a, field, ctx);
|
||||
|
||||
i = BN_ucmp(field, a);
|
||||
if (i == 0) {
|
||||
BN_zero(r);
|
||||
return 1;
|
||||
} else if (i > 0)
|
||||
return (r == a) ? 1 : (BN_copy(r, a) != NULL);
|
||||
|
||||
if (r != a) {
|
||||
if (!bn_wexpand(r, BN_NIST_224_TOP))
|
||||
return 0;
|
||||
r_d = r->d;
|
||||
nist_cp_bn(r_d, a_d, BN_NIST_224_TOP);
|
||||
} else
|
||||
r_d = a_d;
|
||||
|
||||
#if BN_BITS2==64
|
||||
/* copy upper 256 bits of 448 bit number ... */
|
||||
nist_cp_bn_0(t_d, a_d + (BN_NIST_224_TOP - 1),
|
||||
top - (BN_NIST_224_TOP - 1), BN_NIST_224_TOP);
|
||||
/* ... and right shift by 32 to obtain upper 224 bits */
|
||||
nist_set_224(buf, t_d, 14, 13, 12, 11, 10, 9, 8);
|
||||
/* truncate lower part to 224 bits too */
|
||||
r_d[BN_NIST_224_TOP - 1] &= BN_MASK2l;
|
||||
#else
|
||||
nist_cp_bn_0(buf, a_d + BN_NIST_224_TOP, top - BN_NIST_224_TOP,
|
||||
BN_NIST_224_TOP);
|
||||
#endif
|
||||
nist_set_224(t_d, buf, 10, 9, 8, 7, 0, 0, 0);
|
||||
carry = (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP);
|
||||
nist_set_224(t_d, buf, 0, 13, 12, 11, 0, 0, 0);
|
||||
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_224_TOP);
|
||||
nist_set_224(t_d, buf, 13, 12, 11, 10, 9, 8, 7);
|
||||
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP);
|
||||
nist_set_224(t_d, buf, 0, 0, 0, 0, 13, 12, 11);
|
||||
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_224_TOP);
|
||||
|
||||
#if BN_BITS2==64
|
||||
carry = (int)(r_d[BN_NIST_224_TOP - 1] >> 32);
|
||||
#endif
|
||||
u.f = bn_sub_words;
|
||||
if (carry > 0) {
|
||||
carry =
|
||||
(int)bn_sub_words(r_d, r_d, _nist_p_224[carry - 1],
|
||||
BN_NIST_224_TOP);
|
||||
#if BN_BITS2==64
|
||||
carry = (int)(~(r_d[BN_NIST_224_TOP - 1] >> 32)) & 1;
|
||||
#endif
|
||||
} else if (carry < 0) {
|
||||
/*
|
||||
* it's a bit more comlicated logic in this case. if bn_add_words
|
||||
* yields no carry, then result has to be adjusted by unconditionally
|
||||
* *adding* the modulus. but if it does, then result has to be
|
||||
* compared to the modulus and conditionally adjusted by
|
||||
* *subtracting* the latter.
|
||||
*/
|
||||
carry =
|
||||
(int)bn_add_words(r_d, r_d, _nist_p_224[-carry - 1],
|
||||
BN_NIST_224_TOP);
|
||||
mask = 0 - (size_t)carry;
|
||||
u.p = ((size_t)bn_sub_words & mask) | ((size_t)bn_add_words & ~mask);
|
||||
} else
|
||||
carry = 1;
|
||||
|
||||
/* otherwise it's effectively same as in BN_nist_mod_192... */
|
||||
mask = 0 - (size_t)(*u.f) (c_d, r_d, _nist_p_224[0], BN_NIST_224_TOP);
|
||||
mask &= 0 - (size_t)carry;
|
||||
res = (BN_ULONG *)(((size_t)c_d & ~mask) | ((size_t)r_d & mask));
|
||||
nist_cp_bn(r_d, res, BN_NIST_224_TOP);
|
||||
r->top = BN_NIST_224_TOP;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define nist_set_256(to, from, a1, a2, a3, a4, a5, a6, a7, a8) \
|
||||
{ \
|
||||
bn_cp_32(to, 0, from, (a8) - 8) \
|
||||
bn_cp_32(to, 1, from, (a7) - 8) \
|
||||
bn_cp_32(to, 2, from, (a6) - 8) \
|
||||
bn_cp_32(to, 3, from, (a5) - 8) \
|
||||
bn_cp_32(to, 4, from, (a4) - 8) \
|
||||
bn_cp_32(to, 5, from, (a3) - 8) \
|
||||
bn_cp_32(to, 6, from, (a2) - 8) \
|
||||
bn_cp_32(to, 7, from, (a1) - 8) \
|
||||
}
|
||||
|
||||
int BN_nist_mod_256(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int i, top = a->top;
|
||||
int carry = 0;
|
||||
register BN_ULONG *a_d = a->d, *r_d;
|
||||
BN_ULONG t_d[BN_NIST_256_TOP],
|
||||
buf[BN_NIST_256_TOP], c_d[BN_NIST_256_TOP], *res;
|
||||
size_t mask;
|
||||
union {
|
||||
bn_addsub_f f;
|
||||
size_t p;
|
||||
} u;
|
||||
static const BIGNUM _bignum_nist_p_256_sqr = {
|
||||
(BN_ULONG *)_nist_p_256_sqr,
|
||||
sizeof(_nist_p_256_sqr) / sizeof(_nist_p_256_sqr[0]),
|
||||
sizeof(_nist_p_256_sqr) / sizeof(_nist_p_256_sqr[0]),
|
||||
0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
field = &_bignum_nist_p_256; /* just to make sure */
|
||||
|
||||
if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_256_sqr) >= 0)
|
||||
return BN_nnmod(r, a, field, ctx);
|
||||
|
||||
i = BN_ucmp(field, a);
|
||||
if (i == 0) {
|
||||
BN_zero(r);
|
||||
return 1;
|
||||
} else if (i > 0)
|
||||
return (r == a) ? 1 : (BN_copy(r, a) != NULL);
|
||||
|
||||
if (r != a) {
|
||||
if (!bn_wexpand(r, BN_NIST_256_TOP))
|
||||
return 0;
|
||||
r_d = r->d;
|
||||
nist_cp_bn(r_d, a_d, BN_NIST_256_TOP);
|
||||
} else
|
||||
r_d = a_d;
|
||||
|
||||
nist_cp_bn_0(buf, a_d + BN_NIST_256_TOP, top - BN_NIST_256_TOP,
|
||||
BN_NIST_256_TOP);
|
||||
|
||||
/*
|
||||
* S1
|
||||
*/
|
||||
nist_set_256(t_d, buf, 15, 14, 13, 12, 11, 0, 0, 0);
|
||||
/*
|
||||
* S2
|
||||
*/
|
||||
nist_set_256(c_d, buf, 0, 15, 14, 13, 12, 0, 0, 0);
|
||||
carry = (int)bn_add_words(t_d, t_d, c_d, BN_NIST_256_TOP);
|
||||
/* left shift */
|
||||
{
|
||||
register BN_ULONG *ap, t, c;
|
||||
ap = t_d;
|
||||
c = 0;
|
||||
for (i = BN_NIST_256_TOP; i != 0; --i) {
|
||||
t = *ap;
|
||||
*(ap++) = ((t << 1) | c) & BN_MASK2;
|
||||
c = (t & BN_TBIT) ? 1 : 0;
|
||||
}
|
||||
carry <<= 1;
|
||||
carry |= c;
|
||||
}
|
||||
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
|
||||
/*
|
||||
* S3
|
||||
*/
|
||||
nist_set_256(t_d, buf, 15, 14, 0, 0, 0, 10, 9, 8);
|
||||
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
|
||||
/*
|
||||
* S4
|
||||
*/
|
||||
nist_set_256(t_d, buf, 8, 13, 15, 14, 13, 11, 10, 9);
|
||||
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_256_TOP);
|
||||
/*
|
||||
* D1
|
||||
*/
|
||||
nist_set_256(t_d, buf, 10, 8, 0, 0, 0, 13, 12, 11);
|
||||
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
|
||||
/*
|
||||
* D2
|
||||
*/
|
||||
nist_set_256(t_d, buf, 11, 9, 0, 0, 15, 14, 13, 12);
|
||||
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
|
||||
/*
|
||||
* D3
|
||||
*/
|
||||
nist_set_256(t_d, buf, 12, 0, 10, 9, 8, 15, 14, 13);
|
||||
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
|
||||
/*
|
||||
* D4
|
||||
*/
|
||||
nist_set_256(t_d, buf, 13, 0, 11, 10, 9, 0, 15, 14);
|
||||
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_256_TOP);
|
||||
|
||||
/* see BN_nist_mod_224 for explanation */
|
||||
u.f = bn_sub_words;
|
||||
if (carry > 0)
|
||||
carry =
|
||||
(int)bn_sub_words(r_d, r_d, _nist_p_256[carry - 1],
|
||||
BN_NIST_256_TOP);
|
||||
else if (carry < 0) {
|
||||
carry =
|
||||
(int)bn_add_words(r_d, r_d, _nist_p_256[-carry - 1],
|
||||
BN_NIST_256_TOP);
|
||||
mask = 0 - (size_t)carry;
|
||||
u.p = ((size_t)bn_sub_words & mask) | ((size_t)bn_add_words & ~mask);
|
||||
} else
|
||||
carry = 1;
|
||||
|
||||
mask = 0 - (size_t)(*u.f) (c_d, r_d, _nist_p_256[0], BN_NIST_256_TOP);
|
||||
mask &= 0 - (size_t)carry;
|
||||
res = (BN_ULONG *)(((size_t)c_d & ~mask) | ((size_t)r_d & mask));
|
||||
nist_cp_bn(r_d, res, BN_NIST_256_TOP);
|
||||
r->top = BN_NIST_256_TOP;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define nist_set_384(to,from,a1,a2,a3,a4,a5,a6,a7,a8,a9,a10,a11,a12) \
|
||||
{ \
|
||||
bn_cp_32(to, 0, from, (a12) - 12) \
|
||||
bn_cp_32(to, 1, from, (a11) - 12) \
|
||||
bn_cp_32(to, 2, from, (a10) - 12) \
|
||||
bn_cp_32(to, 3, from, (a9) - 12) \
|
||||
bn_cp_32(to, 4, from, (a8) - 12) \
|
||||
bn_cp_32(to, 5, from, (a7) - 12) \
|
||||
bn_cp_32(to, 6, from, (a6) - 12) \
|
||||
bn_cp_32(to, 7, from, (a5) - 12) \
|
||||
bn_cp_32(to, 8, from, (a4) - 12) \
|
||||
bn_cp_32(to, 9, from, (a3) - 12) \
|
||||
bn_cp_32(to, 10, from, (a2) - 12) \
|
||||
bn_cp_32(to, 11, from, (a1) - 12) \
|
||||
}
|
||||
|
||||
int BN_nist_mod_384(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int i, top = a->top;
|
||||
int carry = 0;
|
||||
register BN_ULONG *r_d, *a_d = a->d;
|
||||
BN_ULONG t_d[BN_NIST_384_TOP],
|
||||
buf[BN_NIST_384_TOP], c_d[BN_NIST_384_TOP], *res;
|
||||
size_t mask;
|
||||
union {
|
||||
bn_addsub_f f;
|
||||
size_t p;
|
||||
} u;
|
||||
static const BIGNUM _bignum_nist_p_384_sqr = {
|
||||
(BN_ULONG *)_nist_p_384_sqr,
|
||||
sizeof(_nist_p_384_sqr) / sizeof(_nist_p_384_sqr[0]),
|
||||
sizeof(_nist_p_384_sqr) / sizeof(_nist_p_384_sqr[0]),
|
||||
0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
field = &_bignum_nist_p_384; /* just to make sure */
|
||||
|
||||
if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_384_sqr) >= 0)
|
||||
return BN_nnmod(r, a, field, ctx);
|
||||
|
||||
i = BN_ucmp(field, a);
|
||||
if (i == 0) {
|
||||
BN_zero(r);
|
||||
return 1;
|
||||
} else if (i > 0)
|
||||
return (r == a) ? 1 : (BN_copy(r, a) != NULL);
|
||||
|
||||
if (r != a) {
|
||||
if (!bn_wexpand(r, BN_NIST_384_TOP))
|
||||
return 0;
|
||||
r_d = r->d;
|
||||
nist_cp_bn(r_d, a_d, BN_NIST_384_TOP);
|
||||
} else
|
||||
r_d = a_d;
|
||||
|
||||
nist_cp_bn_0(buf, a_d + BN_NIST_384_TOP, top - BN_NIST_384_TOP,
|
||||
BN_NIST_384_TOP);
|
||||
|
||||
/*
|
||||
* S1
|
||||
*/
|
||||
nist_set_256(t_d, buf, 0, 0, 0, 0, 0, 23 - 4, 22 - 4, 21 - 4);
|
||||
/* left shift */
|
||||
{
|
||||
register BN_ULONG *ap, t, c;
|
||||
ap = t_d;
|
||||
c = 0;
|
||||
for (i = 3; i != 0; --i) {
|
||||
t = *ap;
|
||||
*(ap++) = ((t << 1) | c) & BN_MASK2;
|
||||
c = (t & BN_TBIT) ? 1 : 0;
|
||||
}
|
||||
*ap = c;
|
||||
}
|
||||
carry = (int)bn_add_words(r_d + (128 / BN_BITS2), r_d + (128 / BN_BITS2),
|
||||
t_d, BN_NIST_256_TOP);
|
||||
/*
|
||||
* S2
|
||||
*/
|
||||
carry += (int)bn_add_words(r_d, r_d, buf, BN_NIST_384_TOP);
|
||||
/*
|
||||
* S3
|
||||
*/
|
||||
nist_set_384(t_d, buf, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23, 22, 21);
|
||||
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
|
||||
/*
|
||||
* S4
|
||||
*/
|
||||
nist_set_384(t_d, buf, 19, 18, 17, 16, 15, 14, 13, 12, 20, 0, 23, 0);
|
||||
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
|
||||
/*
|
||||
* S5
|
||||
*/
|
||||
nist_set_384(t_d, buf, 0, 0, 0, 0, 23, 22, 21, 20, 0, 0, 0, 0);
|
||||
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
|
||||
/*
|
||||
* S6
|
||||
*/
|
||||
nist_set_384(t_d, buf, 0, 0, 0, 0, 0, 0, 23, 22, 21, 0, 0, 20);
|
||||
carry += (int)bn_add_words(r_d, r_d, t_d, BN_NIST_384_TOP);
|
||||
/*
|
||||
* D1
|
||||
*/
|
||||
nist_set_384(t_d, buf, 22, 21, 20, 19, 18, 17, 16, 15, 14, 13, 12, 23);
|
||||
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
|
||||
/*
|
||||
* D2
|
||||
*/
|
||||
nist_set_384(t_d, buf, 0, 0, 0, 0, 0, 0, 0, 23, 22, 21, 20, 0);
|
||||
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
|
||||
/*
|
||||
* D3
|
||||
*/
|
||||
nist_set_384(t_d, buf, 0, 0, 0, 0, 0, 0, 0, 23, 23, 0, 0, 0);
|
||||
carry -= (int)bn_sub_words(r_d, r_d, t_d, BN_NIST_384_TOP);
|
||||
|
||||
/* see BN_nist_mod_224 for explanation */
|
||||
u.f = bn_sub_words;
|
||||
if (carry > 0)
|
||||
carry =
|
||||
(int)bn_sub_words(r_d, r_d, _nist_p_384[carry - 1],
|
||||
BN_NIST_384_TOP);
|
||||
else if (carry < 0) {
|
||||
carry =
|
||||
(int)bn_add_words(r_d, r_d, _nist_p_384[-carry - 1],
|
||||
BN_NIST_384_TOP);
|
||||
mask = 0 - (size_t)carry;
|
||||
u.p = ((size_t)bn_sub_words & mask) | ((size_t)bn_add_words & ~mask);
|
||||
} else
|
||||
carry = 1;
|
||||
|
||||
mask = 0 - (size_t)(*u.f) (c_d, r_d, _nist_p_384[0], BN_NIST_384_TOP);
|
||||
mask &= 0 - (size_t)carry;
|
||||
res = (BN_ULONG *)(((size_t)c_d & ~mask) | ((size_t)r_d & mask));
|
||||
nist_cp_bn(r_d, res, BN_NIST_384_TOP);
|
||||
r->top = BN_NIST_384_TOP;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define BN_NIST_521_RSHIFT (521%BN_BITS2)
|
||||
#define BN_NIST_521_LSHIFT (BN_BITS2-BN_NIST_521_RSHIFT)
|
||||
#define BN_NIST_521_TOP_MASK ((BN_ULONG)BN_MASK2>>BN_NIST_521_LSHIFT)
|
||||
|
||||
int BN_nist_mod_521(BIGNUM *r, const BIGNUM *a, const BIGNUM *field,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int top = a->top, i;
|
||||
BN_ULONG *r_d, *a_d = a->d, t_d[BN_NIST_521_TOP], val, tmp, *res;
|
||||
size_t mask;
|
||||
static const BIGNUM _bignum_nist_p_521_sqr = {
|
||||
(BN_ULONG *)_nist_p_521_sqr,
|
||||
sizeof(_nist_p_521_sqr) / sizeof(_nist_p_521_sqr[0]),
|
||||
sizeof(_nist_p_521_sqr) / sizeof(_nist_p_521_sqr[0]),
|
||||
0, BN_FLG_STATIC_DATA
|
||||
};
|
||||
|
||||
field = &_bignum_nist_p_521; /* just to make sure */
|
||||
|
||||
if (BN_is_negative(a) || BN_ucmp(a, &_bignum_nist_p_521_sqr) >= 0)
|
||||
return BN_nnmod(r, a, field, ctx);
|
||||
|
||||
i = BN_ucmp(field, a);
|
||||
if (i == 0) {
|
||||
BN_zero(r);
|
||||
return 1;
|
||||
} else if (i > 0)
|
||||
return (r == a) ? 1 : (BN_copy(r, a) != NULL);
|
||||
|
||||
if (r != a) {
|
||||
if (!bn_wexpand(r, BN_NIST_521_TOP))
|
||||
return 0;
|
||||
r_d = r->d;
|
||||
nist_cp_bn(r_d, a_d, BN_NIST_521_TOP);
|
||||
} else
|
||||
r_d = a_d;
|
||||
|
||||
/* upper 521 bits, copy ... */
|
||||
nist_cp_bn_0(t_d, a_d + (BN_NIST_521_TOP - 1),
|
||||
top - (BN_NIST_521_TOP - 1), BN_NIST_521_TOP);
|
||||
/* ... and right shift */
|
||||
for (val = t_d[0], i = 0; i < BN_NIST_521_TOP - 1; i++) {
|
||||
tmp = val >> BN_NIST_521_RSHIFT;
|
||||
val = t_d[i + 1];
|
||||
t_d[i] = (tmp | val << BN_NIST_521_LSHIFT) & BN_MASK2;
|
||||
}
|
||||
t_d[i] = val >> BN_NIST_521_RSHIFT;
|
||||
/* lower 521 bits */
|
||||
r_d[i] &= BN_NIST_521_TOP_MASK;
|
||||
|
||||
bn_add_words(r_d, r_d, t_d, BN_NIST_521_TOP);
|
||||
mask = 0 - (size_t)bn_sub_words(t_d, r_d, _nist_p_521, BN_NIST_521_TOP);
|
||||
res = (BN_ULONG *)(((size_t)t_d & ~mask) | ((size_t)r_d & mask));
|
||||
nist_cp_bn(r_d, res, BN_NIST_521_TOP);
|
||||
r->top = BN_NIST_521_TOP;
|
||||
bn_correct_top(r);
|
||||
|
||||
return 1;
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/* crypto/bn/bn_opt.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#ifndef BN_DEBUG
|
||||
# undef NDEBUG /* avoid conflicting definitions */
|
||||
# define NDEBUG
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
char *BN_options(void)
|
||||
{
|
||||
static int init = 0;
|
||||
static char data[16];
|
||||
|
||||
if (!init) {
|
||||
init++;
|
||||
#ifdef BN_LLONG
|
||||
BIO_snprintf(data, sizeof data, "bn(%d,%d)",
|
||||
(int)sizeof(BN_ULLONG) * 8, (int)sizeof(BN_ULONG) * 8);
|
||||
#else
|
||||
BIO_snprintf(data, sizeof data, "bn(%d,%d)",
|
||||
(int)sizeof(BN_ULONG) * 8, (int)sizeof(BN_ULONG) * 8);
|
||||
#endif
|
||||
}
|
||||
return (data);
|
||||
}
|
||||
@@ -0,0 +1,515 @@
|
||||
/* crypto/bn/bn_prime.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
#include <openssl/rand.h>
|
||||
|
||||
/*
|
||||
* NB: these functions have been "upgraded", the deprecated versions (which
|
||||
* are compatibility wrappers using these functions) are in bn_depr.c. -
|
||||
* Geoff
|
||||
*/
|
||||
|
||||
/*
|
||||
* The quick sieve algorithm approach to weeding out primes is Philip
|
||||
* Zimmermann's, as implemented in PGP. I have had a read of his comments
|
||||
* and implemented my own version.
|
||||
*/
|
||||
#include "bn_prime.h"
|
||||
|
||||
static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
|
||||
const BIGNUM *a1_odd, int k, BN_CTX *ctx,
|
||||
BN_MONT_CTX *mont);
|
||||
static int probable_prime(BIGNUM *rnd, int bits);
|
||||
static int probable_prime_dh(BIGNUM *rnd, int bits,
|
||||
const BIGNUM *add, const BIGNUM *rem,
|
||||
BN_CTX *ctx);
|
||||
static int probable_prime_dh_safe(BIGNUM *rnd, int bits, const BIGNUM *add,
|
||||
const BIGNUM *rem, BN_CTX *ctx);
|
||||
|
||||
int BN_GENCB_call(BN_GENCB *cb, int a, int b)
|
||||
{
|
||||
/* No callback means continue */
|
||||
if (!cb)
|
||||
return 1;
|
||||
switch (cb->ver) {
|
||||
case 1:
|
||||
/* Deprecated-style callbacks */
|
||||
if (!cb->cb.cb_1)
|
||||
return 1;
|
||||
cb->cb.cb_1(a, b, cb->arg);
|
||||
return 1;
|
||||
case 2:
|
||||
/* New-style callbacks */
|
||||
return cb->cb.cb_2(a, b, cb);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/* Unrecognised callback type */
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BN_generate_prime_ex(BIGNUM *ret, int bits, int safe,
|
||||
const BIGNUM *add, const BIGNUM *rem, BN_GENCB *cb)
|
||||
{
|
||||
BIGNUM *t;
|
||||
int found = 0;
|
||||
int i, j, c1 = 0;
|
||||
BN_CTX *ctx;
|
||||
int checks = BN_prime_checks_for_size(bits);
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
if (ctx == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
t = BN_CTX_get(ctx);
|
||||
if (!t)
|
||||
goto err;
|
||||
loop:
|
||||
/* make a random number and set the top and bottom bits */
|
||||
if (add == NULL) {
|
||||
if (!probable_prime(ret, bits))
|
||||
goto err;
|
||||
} else {
|
||||
if (safe) {
|
||||
if (!probable_prime_dh_safe(ret, bits, add, rem, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
if (!probable_prime_dh(ret, bits, add, rem, ctx))
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
/* if (BN_mod_word(ret,(BN_ULONG)3) == 1) goto loop; */
|
||||
if (!BN_GENCB_call(cb, 0, c1++))
|
||||
/* aborted */
|
||||
goto err;
|
||||
|
||||
if (!safe) {
|
||||
i = BN_is_prime_fasttest_ex(ret, checks, ctx, 0, cb);
|
||||
if (i == -1)
|
||||
goto err;
|
||||
if (i == 0)
|
||||
goto loop;
|
||||
} else {
|
||||
/*
|
||||
* for "safe prime" generation, check that (p-1)/2 is prime. Since a
|
||||
* prime is odd, We just need to divide by 2
|
||||
*/
|
||||
if (!BN_rshift1(t, ret))
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < checks; i++) {
|
||||
j = BN_is_prime_fasttest_ex(ret, 1, ctx, 0, cb);
|
||||
if (j == -1)
|
||||
goto err;
|
||||
if (j == 0)
|
||||
goto loop;
|
||||
|
||||
j = BN_is_prime_fasttest_ex(t, 1, ctx, 0, cb);
|
||||
if (j == -1)
|
||||
goto err;
|
||||
if (j == 0)
|
||||
goto loop;
|
||||
|
||||
if (!BN_GENCB_call(cb, 2, c1 - 1))
|
||||
goto err;
|
||||
/* We have a safe prime test pass */
|
||||
}
|
||||
}
|
||||
/* we have a prime :-) */
|
||||
found = 1;
|
||||
err:
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
bn_check_top(ret);
|
||||
return found;
|
||||
}
|
||||
|
||||
int BN_is_prime_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
return BN_is_prime_fasttest_ex(a, checks, ctx_passed, 0, cb);
|
||||
}
|
||||
|
||||
int BN_is_prime_fasttest_ex(const BIGNUM *a, int checks, BN_CTX *ctx_passed,
|
||||
int do_trial_division, BN_GENCB *cb)
|
||||
{
|
||||
int i, j, ret = -1;
|
||||
int k;
|
||||
BN_CTX *ctx = NULL;
|
||||
BIGNUM *A1, *A1_odd, *check; /* taken from ctx */
|
||||
BN_MONT_CTX *mont = NULL;
|
||||
const BIGNUM *A = NULL;
|
||||
|
||||
if (BN_cmp(a, BN_value_one()) <= 0)
|
||||
return 0;
|
||||
|
||||
if (checks == BN_prime_checks)
|
||||
checks = BN_prime_checks_for_size(BN_num_bits(a));
|
||||
|
||||
/* first look for small factors */
|
||||
if (!BN_is_odd(a))
|
||||
/* a is even => a is prime if and only if a == 2 */
|
||||
return BN_is_word(a, 2);
|
||||
if (do_trial_division) {
|
||||
for (i = 1; i < NUMPRIMES; i++)
|
||||
if (BN_mod_word(a, primes[i]) == 0)
|
||||
return 0;
|
||||
if (!BN_GENCB_call(cb, 1, -1))
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (ctx_passed != NULL)
|
||||
ctx = ctx_passed;
|
||||
else if ((ctx = BN_CTX_new()) == NULL)
|
||||
goto err;
|
||||
BN_CTX_start(ctx);
|
||||
|
||||
/* A := abs(a) */
|
||||
if (a->neg) {
|
||||
BIGNUM *t;
|
||||
if ((t = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
BN_copy(t, a);
|
||||
t->neg = 0;
|
||||
A = t;
|
||||
} else
|
||||
A = a;
|
||||
A1 = BN_CTX_get(ctx);
|
||||
A1_odd = BN_CTX_get(ctx);
|
||||
check = BN_CTX_get(ctx);
|
||||
if (check == NULL)
|
||||
goto err;
|
||||
|
||||
/* compute A1 := A - 1 */
|
||||
if (!BN_copy(A1, A))
|
||||
goto err;
|
||||
if (!BN_sub_word(A1, 1))
|
||||
goto err;
|
||||
if (BN_is_zero(A1)) {
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* write A1 as A1_odd * 2^k */
|
||||
k = 1;
|
||||
while (!BN_is_bit_set(A1, k))
|
||||
k++;
|
||||
if (!BN_rshift(A1_odd, A1, k))
|
||||
goto err;
|
||||
|
||||
/* Montgomery setup for computations mod A */
|
||||
mont = BN_MONT_CTX_new();
|
||||
if (mont == NULL)
|
||||
goto err;
|
||||
if (!BN_MONT_CTX_set(mont, A, ctx))
|
||||
goto err;
|
||||
|
||||
for (i = 0; i < checks; i++) {
|
||||
if (!BN_pseudo_rand_range(check, A1))
|
||||
goto err;
|
||||
if (!BN_add_word(check, 1))
|
||||
goto err;
|
||||
/* now 1 <= check < A */
|
||||
|
||||
j = witness(check, A, A1, A1_odd, k, ctx, mont);
|
||||
if (j == -1)
|
||||
goto err;
|
||||
if (j) {
|
||||
ret = 0;
|
||||
goto err;
|
||||
}
|
||||
if (!BN_GENCB_call(cb, 1, i))
|
||||
goto err;
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
if (ctx != NULL) {
|
||||
BN_CTX_end(ctx);
|
||||
if (ctx_passed == NULL)
|
||||
BN_CTX_free(ctx);
|
||||
}
|
||||
if (mont != NULL)
|
||||
BN_MONT_CTX_free(mont);
|
||||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int witness(BIGNUM *w, const BIGNUM *a, const BIGNUM *a1,
|
||||
const BIGNUM *a1_odd, int k, BN_CTX *ctx,
|
||||
BN_MONT_CTX *mont)
|
||||
{
|
||||
if (!BN_mod_exp_mont(w, w, a1_odd, a, ctx, mont)) /* w := w^a1_odd mod a */
|
||||
return -1;
|
||||
if (BN_is_one(w))
|
||||
return 0; /* probably prime */
|
||||
if (BN_cmp(w, a1) == 0)
|
||||
return 0; /* w == -1 (mod a), 'a' is probably prime */
|
||||
while (--k) {
|
||||
if (!BN_mod_mul(w, w, w, a, ctx)) /* w := w^2 mod a */
|
||||
return -1;
|
||||
if (BN_is_one(w))
|
||||
return 1; /* 'a' is composite, otherwise a previous 'w'
|
||||
* would have been == -1 (mod 'a') */
|
||||
if (BN_cmp(w, a1) == 0)
|
||||
return 0; /* w == -1 (mod a), 'a' is probably prime */
|
||||
}
|
||||
/*
|
||||
* If we get here, 'w' is the (a-1)/2-th power of the original 'w', and
|
||||
* it is neither -1 nor +1 -- so 'a' cannot be prime
|
||||
*/
|
||||
bn_check_top(w);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int probable_prime(BIGNUM *rnd, int bits)
|
||||
{
|
||||
int i;
|
||||
prime_t mods[NUMPRIMES];
|
||||
BN_ULONG delta, maxdelta;
|
||||
|
||||
again:
|
||||
if (!BN_rand(rnd, bits, 1, 1))
|
||||
return (0);
|
||||
/* we now have a random number 'rand' to test. */
|
||||
for (i = 1; i < NUMPRIMES; i++)
|
||||
mods[i] = (prime_t) BN_mod_word(rnd, (BN_ULONG)primes[i]);
|
||||
maxdelta = BN_MASK2 - primes[NUMPRIMES - 1];
|
||||
delta = 0;
|
||||
loop:for (i = 1; i < NUMPRIMES; i++) {
|
||||
/*
|
||||
* check that rnd is not a prime and also that gcd(rnd-1,primes) == 1
|
||||
* (except for 2)
|
||||
*/
|
||||
if (((mods[i] + delta) % primes[i]) <= 1) {
|
||||
delta += 2;
|
||||
if (delta > maxdelta)
|
||||
goto again;
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
if (!BN_add_word(rnd, delta))
|
||||
return (0);
|
||||
bn_check_top(rnd);
|
||||
return (1);
|
||||
}
|
||||
|
||||
static int probable_prime_dh(BIGNUM *rnd, int bits,
|
||||
const BIGNUM *add, const BIGNUM *rem,
|
||||
BN_CTX *ctx)
|
||||
{
|
||||
int i, ret = 0;
|
||||
BIGNUM *t1;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if ((t1 = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_rand(rnd, bits, 0, 1))
|
||||
goto err;
|
||||
|
||||
/* we need ((rnd-rem) % add) == 0 */
|
||||
|
||||
if (!BN_mod(t1, rnd, add, ctx))
|
||||
goto err;
|
||||
if (!BN_sub(rnd, rnd, t1))
|
||||
goto err;
|
||||
if (rem == NULL) {
|
||||
if (!BN_add_word(rnd, 1))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_add(rnd, rnd, rem))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* we now have a random number 'rand' to test. */
|
||||
|
||||
loop:for (i = 1; i < NUMPRIMES; i++) {
|
||||
/* check that rnd is a prime */
|
||||
if (BN_mod_word(rnd, (BN_ULONG)primes[i]) <= 1) {
|
||||
if (!BN_add(rnd, rnd, add))
|
||||
goto err;
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(rnd);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
static int probable_prime_dh_safe(BIGNUM *p, int bits, const BIGNUM *padd,
|
||||
const BIGNUM *rem, BN_CTX *ctx)
|
||||
{
|
||||
int i, ret = 0;
|
||||
BIGNUM *t1, *qadd, *q;
|
||||
|
||||
bits--;
|
||||
BN_CTX_start(ctx);
|
||||
t1 = BN_CTX_get(ctx);
|
||||
q = BN_CTX_get(ctx);
|
||||
qadd = BN_CTX_get(ctx);
|
||||
if (qadd == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_rshift1(qadd, padd))
|
||||
goto err;
|
||||
|
||||
if (!BN_rand(q, bits, 0, 1))
|
||||
goto err;
|
||||
|
||||
/* we need ((rnd-rem) % add) == 0 */
|
||||
if (!BN_mod(t1, q, qadd, ctx))
|
||||
goto err;
|
||||
if (!BN_sub(q, q, t1))
|
||||
goto err;
|
||||
if (rem == NULL) {
|
||||
if (!BN_add_word(q, 1))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_rshift1(t1, rem))
|
||||
goto err;
|
||||
if (!BN_add(q, q, t1))
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* we now have a random number 'rand' to test. */
|
||||
if (!BN_lshift1(p, q))
|
||||
goto err;
|
||||
if (!BN_add_word(p, 1))
|
||||
goto err;
|
||||
|
||||
loop:for (i = 1; i < NUMPRIMES; i++) {
|
||||
/* check that p and q are prime */
|
||||
/*
|
||||
* check that for p and q gcd(p-1,primes) == 1 (except for 2)
|
||||
*/
|
||||
if ((BN_mod_word(p, (BN_ULONG)primes[i]) == 0) ||
|
||||
(BN_mod_word(q, (BN_ULONG)primes[i]) == 0)) {
|
||||
if (!BN_add(p, p, padd))
|
||||
goto err;
|
||||
if (!BN_add(q, q, qadd))
|
||||
goto err;
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(p);
|
||||
return (ret);
|
||||
}
|
||||
@@ -0,0 +1,326 @@
|
||||
/* Auto generated by bn_prime.pl */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#ifndef EIGHT_BIT
|
||||
# define NUMPRIMES 2048
|
||||
typedef unsigned short prime_t;
|
||||
#else
|
||||
# define NUMPRIMES 54
|
||||
typedef unsigned char prime_t;
|
||||
#endif
|
||||
static const prime_t primes[NUMPRIMES] = {
|
||||
2, 3, 5, 7, 11, 13, 17, 19,
|
||||
23, 29, 31, 37, 41, 43, 47, 53,
|
||||
59, 61, 67, 71, 73, 79, 83, 89,
|
||||
97, 101, 103, 107, 109, 113, 127, 131,
|
||||
137, 139, 149, 151, 157, 163, 167, 173,
|
||||
179, 181, 191, 193, 197, 199, 211, 223,
|
||||
227, 229, 233, 239, 241, 251,
|
||||
#ifndef EIGHT_BIT
|
||||
257, 263,
|
||||
269, 271, 277, 281, 283, 293, 307, 311,
|
||||
313, 317, 331, 337, 347, 349, 353, 359,
|
||||
367, 373, 379, 383, 389, 397, 401, 409,
|
||||
419, 421, 431, 433, 439, 443, 449, 457,
|
||||
461, 463, 467, 479, 487, 491, 499, 503,
|
||||
509, 521, 523, 541, 547, 557, 563, 569,
|
||||
571, 577, 587, 593, 599, 601, 607, 613,
|
||||
617, 619, 631, 641, 643, 647, 653, 659,
|
||||
661, 673, 677, 683, 691, 701, 709, 719,
|
||||
727, 733, 739, 743, 751, 757, 761, 769,
|
||||
773, 787, 797, 809, 811, 821, 823, 827,
|
||||
829, 839, 853, 857, 859, 863, 877, 881,
|
||||
883, 887, 907, 911, 919, 929, 937, 941,
|
||||
947, 953, 967, 971, 977, 983, 991, 997,
|
||||
1009, 1013, 1019, 1021, 1031, 1033, 1039, 1049,
|
||||
1051, 1061, 1063, 1069, 1087, 1091, 1093, 1097,
|
||||
1103, 1109, 1117, 1123, 1129, 1151, 1153, 1163,
|
||||
1171, 1181, 1187, 1193, 1201, 1213, 1217, 1223,
|
||||
1229, 1231, 1237, 1249, 1259, 1277, 1279, 1283,
|
||||
1289, 1291, 1297, 1301, 1303, 1307, 1319, 1321,
|
||||
1327, 1361, 1367, 1373, 1381, 1399, 1409, 1423,
|
||||
1427, 1429, 1433, 1439, 1447, 1451, 1453, 1459,
|
||||
1471, 1481, 1483, 1487, 1489, 1493, 1499, 1511,
|
||||
1523, 1531, 1543, 1549, 1553, 1559, 1567, 1571,
|
||||
1579, 1583, 1597, 1601, 1607, 1609, 1613, 1619,
|
||||
1621, 1627, 1637, 1657, 1663, 1667, 1669, 1693,
|
||||
1697, 1699, 1709, 1721, 1723, 1733, 1741, 1747,
|
||||
1753, 1759, 1777, 1783, 1787, 1789, 1801, 1811,
|
||||
1823, 1831, 1847, 1861, 1867, 1871, 1873, 1877,
|
||||
1879, 1889, 1901, 1907, 1913, 1931, 1933, 1949,
|
||||
1951, 1973, 1979, 1987, 1993, 1997, 1999, 2003,
|
||||
2011, 2017, 2027, 2029, 2039, 2053, 2063, 2069,
|
||||
2081, 2083, 2087, 2089, 2099, 2111, 2113, 2129,
|
||||
2131, 2137, 2141, 2143, 2153, 2161, 2179, 2203,
|
||||
2207, 2213, 2221, 2237, 2239, 2243, 2251, 2267,
|
||||
2269, 2273, 2281, 2287, 2293, 2297, 2309, 2311,
|
||||
2333, 2339, 2341, 2347, 2351, 2357, 2371, 2377,
|
||||
2381, 2383, 2389, 2393, 2399, 2411, 2417, 2423,
|
||||
2437, 2441, 2447, 2459, 2467, 2473, 2477, 2503,
|
||||
2521, 2531, 2539, 2543, 2549, 2551, 2557, 2579,
|
||||
2591, 2593, 2609, 2617, 2621, 2633, 2647, 2657,
|
||||
2659, 2663, 2671, 2677, 2683, 2687, 2689, 2693,
|
||||
2699, 2707, 2711, 2713, 2719, 2729, 2731, 2741,
|
||||
2749, 2753, 2767, 2777, 2789, 2791, 2797, 2801,
|
||||
2803, 2819, 2833, 2837, 2843, 2851, 2857, 2861,
|
||||
2879, 2887, 2897, 2903, 2909, 2917, 2927, 2939,
|
||||
2953, 2957, 2963, 2969, 2971, 2999, 3001, 3011,
|
||||
3019, 3023, 3037, 3041, 3049, 3061, 3067, 3079,
|
||||
3083, 3089, 3109, 3119, 3121, 3137, 3163, 3167,
|
||||
3169, 3181, 3187, 3191, 3203, 3209, 3217, 3221,
|
||||
3229, 3251, 3253, 3257, 3259, 3271, 3299, 3301,
|
||||
3307, 3313, 3319, 3323, 3329, 3331, 3343, 3347,
|
||||
3359, 3361, 3371, 3373, 3389, 3391, 3407, 3413,
|
||||
3433, 3449, 3457, 3461, 3463, 3467, 3469, 3491,
|
||||
3499, 3511, 3517, 3527, 3529, 3533, 3539, 3541,
|
||||
3547, 3557, 3559, 3571, 3581, 3583, 3593, 3607,
|
||||
3613, 3617, 3623, 3631, 3637, 3643, 3659, 3671,
|
||||
3673, 3677, 3691, 3697, 3701, 3709, 3719, 3727,
|
||||
3733, 3739, 3761, 3767, 3769, 3779, 3793, 3797,
|
||||
3803, 3821, 3823, 3833, 3847, 3851, 3853, 3863,
|
||||
3877, 3881, 3889, 3907, 3911, 3917, 3919, 3923,
|
||||
3929, 3931, 3943, 3947, 3967, 3989, 4001, 4003,
|
||||
4007, 4013, 4019, 4021, 4027, 4049, 4051, 4057,
|
||||
4073, 4079, 4091, 4093, 4099, 4111, 4127, 4129,
|
||||
4133, 4139, 4153, 4157, 4159, 4177, 4201, 4211,
|
||||
4217, 4219, 4229, 4231, 4241, 4243, 4253, 4259,
|
||||
4261, 4271, 4273, 4283, 4289, 4297, 4327, 4337,
|
||||
4339, 4349, 4357, 4363, 4373, 4391, 4397, 4409,
|
||||
4421, 4423, 4441, 4447, 4451, 4457, 4463, 4481,
|
||||
4483, 4493, 4507, 4513, 4517, 4519, 4523, 4547,
|
||||
4549, 4561, 4567, 4583, 4591, 4597, 4603, 4621,
|
||||
4637, 4639, 4643, 4649, 4651, 4657, 4663, 4673,
|
||||
4679, 4691, 4703, 4721, 4723, 4729, 4733, 4751,
|
||||
4759, 4783, 4787, 4789, 4793, 4799, 4801, 4813,
|
||||
4817, 4831, 4861, 4871, 4877, 4889, 4903, 4909,
|
||||
4919, 4931, 4933, 4937, 4943, 4951, 4957, 4967,
|
||||
4969, 4973, 4987, 4993, 4999, 5003, 5009, 5011,
|
||||
5021, 5023, 5039, 5051, 5059, 5077, 5081, 5087,
|
||||
5099, 5101, 5107, 5113, 5119, 5147, 5153, 5167,
|
||||
5171, 5179, 5189, 5197, 5209, 5227, 5231, 5233,
|
||||
5237, 5261, 5273, 5279, 5281, 5297, 5303, 5309,
|
||||
5323, 5333, 5347, 5351, 5381, 5387, 5393, 5399,
|
||||
5407, 5413, 5417, 5419, 5431, 5437, 5441, 5443,
|
||||
5449, 5471, 5477, 5479, 5483, 5501, 5503, 5507,
|
||||
5519, 5521, 5527, 5531, 5557, 5563, 5569, 5573,
|
||||
5581, 5591, 5623, 5639, 5641, 5647, 5651, 5653,
|
||||
5657, 5659, 5669, 5683, 5689, 5693, 5701, 5711,
|
||||
5717, 5737, 5741, 5743, 5749, 5779, 5783, 5791,
|
||||
5801, 5807, 5813, 5821, 5827, 5839, 5843, 5849,
|
||||
5851, 5857, 5861, 5867, 5869, 5879, 5881, 5897,
|
||||
5903, 5923, 5927, 5939, 5953, 5981, 5987, 6007,
|
||||
6011, 6029, 6037, 6043, 6047, 6053, 6067, 6073,
|
||||
6079, 6089, 6091, 6101, 6113, 6121, 6131, 6133,
|
||||
6143, 6151, 6163, 6173, 6197, 6199, 6203, 6211,
|
||||
6217, 6221, 6229, 6247, 6257, 6263, 6269, 6271,
|
||||
6277, 6287, 6299, 6301, 6311, 6317, 6323, 6329,
|
||||
6337, 6343, 6353, 6359, 6361, 6367, 6373, 6379,
|
||||
6389, 6397, 6421, 6427, 6449, 6451, 6469, 6473,
|
||||
6481, 6491, 6521, 6529, 6547, 6551, 6553, 6563,
|
||||
6569, 6571, 6577, 6581, 6599, 6607, 6619, 6637,
|
||||
6653, 6659, 6661, 6673, 6679, 6689, 6691, 6701,
|
||||
6703, 6709, 6719, 6733, 6737, 6761, 6763, 6779,
|
||||
6781, 6791, 6793, 6803, 6823, 6827, 6829, 6833,
|
||||
6841, 6857, 6863, 6869, 6871, 6883, 6899, 6907,
|
||||
6911, 6917, 6947, 6949, 6959, 6961, 6967, 6971,
|
||||
6977, 6983, 6991, 6997, 7001, 7013, 7019, 7027,
|
||||
7039, 7043, 7057, 7069, 7079, 7103, 7109, 7121,
|
||||
7127, 7129, 7151, 7159, 7177, 7187, 7193, 7207,
|
||||
7211, 7213, 7219, 7229, 7237, 7243, 7247, 7253,
|
||||
7283, 7297, 7307, 7309, 7321, 7331, 7333, 7349,
|
||||
7351, 7369, 7393, 7411, 7417, 7433, 7451, 7457,
|
||||
7459, 7477, 7481, 7487, 7489, 7499, 7507, 7517,
|
||||
7523, 7529, 7537, 7541, 7547, 7549, 7559, 7561,
|
||||
7573, 7577, 7583, 7589, 7591, 7603, 7607, 7621,
|
||||
7639, 7643, 7649, 7669, 7673, 7681, 7687, 7691,
|
||||
7699, 7703, 7717, 7723, 7727, 7741, 7753, 7757,
|
||||
7759, 7789, 7793, 7817, 7823, 7829, 7841, 7853,
|
||||
7867, 7873, 7877, 7879, 7883, 7901, 7907, 7919,
|
||||
7927, 7933, 7937, 7949, 7951, 7963, 7993, 8009,
|
||||
8011, 8017, 8039, 8053, 8059, 8069, 8081, 8087,
|
||||
8089, 8093, 8101, 8111, 8117, 8123, 8147, 8161,
|
||||
8167, 8171, 8179, 8191, 8209, 8219, 8221, 8231,
|
||||
8233, 8237, 8243, 8263, 8269, 8273, 8287, 8291,
|
||||
8293, 8297, 8311, 8317, 8329, 8353, 8363, 8369,
|
||||
8377, 8387, 8389, 8419, 8423, 8429, 8431, 8443,
|
||||
8447, 8461, 8467, 8501, 8513, 8521, 8527, 8537,
|
||||
8539, 8543, 8563, 8573, 8581, 8597, 8599, 8609,
|
||||
8623, 8627, 8629, 8641, 8647, 8663, 8669, 8677,
|
||||
8681, 8689, 8693, 8699, 8707, 8713, 8719, 8731,
|
||||
8737, 8741, 8747, 8753, 8761, 8779, 8783, 8803,
|
||||
8807, 8819, 8821, 8831, 8837, 8839, 8849, 8861,
|
||||
8863, 8867, 8887, 8893, 8923, 8929, 8933, 8941,
|
||||
8951, 8963, 8969, 8971, 8999, 9001, 9007, 9011,
|
||||
9013, 9029, 9041, 9043, 9049, 9059, 9067, 9091,
|
||||
9103, 9109, 9127, 9133, 9137, 9151, 9157, 9161,
|
||||
9173, 9181, 9187, 9199, 9203, 9209, 9221, 9227,
|
||||
9239, 9241, 9257, 9277, 9281, 9283, 9293, 9311,
|
||||
9319, 9323, 9337, 9341, 9343, 9349, 9371, 9377,
|
||||
9391, 9397, 9403, 9413, 9419, 9421, 9431, 9433,
|
||||
9437, 9439, 9461, 9463, 9467, 9473, 9479, 9491,
|
||||
9497, 9511, 9521, 9533, 9539, 9547, 9551, 9587,
|
||||
9601, 9613, 9619, 9623, 9629, 9631, 9643, 9649,
|
||||
9661, 9677, 9679, 9689, 9697, 9719, 9721, 9733,
|
||||
9739, 9743, 9749, 9767, 9769, 9781, 9787, 9791,
|
||||
9803, 9811, 9817, 9829, 9833, 9839, 9851, 9857,
|
||||
9859, 9871, 9883, 9887, 9901, 9907, 9923, 9929,
|
||||
9931, 9941, 9949, 9967, 9973, 10007, 10009, 10037,
|
||||
10039, 10061, 10067, 10069, 10079, 10091, 10093, 10099,
|
||||
10103, 10111, 10133, 10139, 10141, 10151, 10159, 10163,
|
||||
10169, 10177, 10181, 10193, 10211, 10223, 10243, 10247,
|
||||
10253, 10259, 10267, 10271, 10273, 10289, 10301, 10303,
|
||||
10313, 10321, 10331, 10333, 10337, 10343, 10357, 10369,
|
||||
10391, 10399, 10427, 10429, 10433, 10453, 10457, 10459,
|
||||
10463, 10477, 10487, 10499, 10501, 10513, 10529, 10531,
|
||||
10559, 10567, 10589, 10597, 10601, 10607, 10613, 10627,
|
||||
10631, 10639, 10651, 10657, 10663, 10667, 10687, 10691,
|
||||
10709, 10711, 10723, 10729, 10733, 10739, 10753, 10771,
|
||||
10781, 10789, 10799, 10831, 10837, 10847, 10853, 10859,
|
||||
10861, 10867, 10883, 10889, 10891, 10903, 10909, 10937,
|
||||
10939, 10949, 10957, 10973, 10979, 10987, 10993, 11003,
|
||||
11027, 11047, 11057, 11059, 11069, 11071, 11083, 11087,
|
||||
11093, 11113, 11117, 11119, 11131, 11149, 11159, 11161,
|
||||
11171, 11173, 11177, 11197, 11213, 11239, 11243, 11251,
|
||||
11257, 11261, 11273, 11279, 11287, 11299, 11311, 11317,
|
||||
11321, 11329, 11351, 11353, 11369, 11383, 11393, 11399,
|
||||
11411, 11423, 11437, 11443, 11447, 11467, 11471, 11483,
|
||||
11489, 11491, 11497, 11503, 11519, 11527, 11549, 11551,
|
||||
11579, 11587, 11593, 11597, 11617, 11621, 11633, 11657,
|
||||
11677, 11681, 11689, 11699, 11701, 11717, 11719, 11731,
|
||||
11743, 11777, 11779, 11783, 11789, 11801, 11807, 11813,
|
||||
11821, 11827, 11831, 11833, 11839, 11863, 11867, 11887,
|
||||
11897, 11903, 11909, 11923, 11927, 11933, 11939, 11941,
|
||||
11953, 11959, 11969, 11971, 11981, 11987, 12007, 12011,
|
||||
12037, 12041, 12043, 12049, 12071, 12073, 12097, 12101,
|
||||
12107, 12109, 12113, 12119, 12143, 12149, 12157, 12161,
|
||||
12163, 12197, 12203, 12211, 12227, 12239, 12241, 12251,
|
||||
12253, 12263, 12269, 12277, 12281, 12289, 12301, 12323,
|
||||
12329, 12343, 12347, 12373, 12377, 12379, 12391, 12401,
|
||||
12409, 12413, 12421, 12433, 12437, 12451, 12457, 12473,
|
||||
12479, 12487, 12491, 12497, 12503, 12511, 12517, 12527,
|
||||
12539, 12541, 12547, 12553, 12569, 12577, 12583, 12589,
|
||||
12601, 12611, 12613, 12619, 12637, 12641, 12647, 12653,
|
||||
12659, 12671, 12689, 12697, 12703, 12713, 12721, 12739,
|
||||
12743, 12757, 12763, 12781, 12791, 12799, 12809, 12821,
|
||||
12823, 12829, 12841, 12853, 12889, 12893, 12899, 12907,
|
||||
12911, 12917, 12919, 12923, 12941, 12953, 12959, 12967,
|
||||
12973, 12979, 12983, 13001, 13003, 13007, 13009, 13033,
|
||||
13037, 13043, 13049, 13063, 13093, 13099, 13103, 13109,
|
||||
13121, 13127, 13147, 13151, 13159, 13163, 13171, 13177,
|
||||
13183, 13187, 13217, 13219, 13229, 13241, 13249, 13259,
|
||||
13267, 13291, 13297, 13309, 13313, 13327, 13331, 13337,
|
||||
13339, 13367, 13381, 13397, 13399, 13411, 13417, 13421,
|
||||
13441, 13451, 13457, 13463, 13469, 13477, 13487, 13499,
|
||||
13513, 13523, 13537, 13553, 13567, 13577, 13591, 13597,
|
||||
13613, 13619, 13627, 13633, 13649, 13669, 13679, 13681,
|
||||
13687, 13691, 13693, 13697, 13709, 13711, 13721, 13723,
|
||||
13729, 13751, 13757, 13759, 13763, 13781, 13789, 13799,
|
||||
13807, 13829, 13831, 13841, 13859, 13873, 13877, 13879,
|
||||
13883, 13901, 13903, 13907, 13913, 13921, 13931, 13933,
|
||||
13963, 13967, 13997, 13999, 14009, 14011, 14029, 14033,
|
||||
14051, 14057, 14071, 14081, 14083, 14087, 14107, 14143,
|
||||
14149, 14153, 14159, 14173, 14177, 14197, 14207, 14221,
|
||||
14243, 14249, 14251, 14281, 14293, 14303, 14321, 14323,
|
||||
14327, 14341, 14347, 14369, 14387, 14389, 14401, 14407,
|
||||
14411, 14419, 14423, 14431, 14437, 14447, 14449, 14461,
|
||||
14479, 14489, 14503, 14519, 14533, 14537, 14543, 14549,
|
||||
14551, 14557, 14561, 14563, 14591, 14593, 14621, 14627,
|
||||
14629, 14633, 14639, 14653, 14657, 14669, 14683, 14699,
|
||||
14713, 14717, 14723, 14731, 14737, 14741, 14747, 14753,
|
||||
14759, 14767, 14771, 14779, 14783, 14797, 14813, 14821,
|
||||
14827, 14831, 14843, 14851, 14867, 14869, 14879, 14887,
|
||||
14891, 14897, 14923, 14929, 14939, 14947, 14951, 14957,
|
||||
14969, 14983, 15013, 15017, 15031, 15053, 15061, 15073,
|
||||
15077, 15083, 15091, 15101, 15107, 15121, 15131, 15137,
|
||||
15139, 15149, 15161, 15173, 15187, 15193, 15199, 15217,
|
||||
15227, 15233, 15241, 15259, 15263, 15269, 15271, 15277,
|
||||
15287, 15289, 15299, 15307, 15313, 15319, 15329, 15331,
|
||||
15349, 15359, 15361, 15373, 15377, 15383, 15391, 15401,
|
||||
15413, 15427, 15439, 15443, 15451, 15461, 15467, 15473,
|
||||
15493, 15497, 15511, 15527, 15541, 15551, 15559, 15569,
|
||||
15581, 15583, 15601, 15607, 15619, 15629, 15641, 15643,
|
||||
15647, 15649, 15661, 15667, 15671, 15679, 15683, 15727,
|
||||
15731, 15733, 15737, 15739, 15749, 15761, 15767, 15773,
|
||||
15787, 15791, 15797, 15803, 15809, 15817, 15823, 15859,
|
||||
15877, 15881, 15887, 15889, 15901, 15907, 15913, 15919,
|
||||
15923, 15937, 15959, 15971, 15973, 15991, 16001, 16007,
|
||||
16033, 16057, 16061, 16063, 16067, 16069, 16073, 16087,
|
||||
16091, 16097, 16103, 16111, 16127, 16139, 16141, 16183,
|
||||
16187, 16189, 16193, 16217, 16223, 16229, 16231, 16249,
|
||||
16253, 16267, 16273, 16301, 16319, 16333, 16339, 16349,
|
||||
16361, 16363, 16369, 16381, 16411, 16417, 16421, 16427,
|
||||
16433, 16447, 16451, 16453, 16477, 16481, 16487, 16493,
|
||||
16519, 16529, 16547, 16553, 16561, 16567, 16573, 16603,
|
||||
16607, 16619, 16631, 16633, 16649, 16651, 16657, 16661,
|
||||
16673, 16691, 16693, 16699, 16703, 16729, 16741, 16747,
|
||||
16759, 16763, 16787, 16811, 16823, 16829, 16831, 16843,
|
||||
16871, 16879, 16883, 16889, 16901, 16903, 16921, 16927,
|
||||
16931, 16937, 16943, 16963, 16979, 16981, 16987, 16993,
|
||||
17011, 17021, 17027, 17029, 17033, 17041, 17047, 17053,
|
||||
17077, 17093, 17099, 17107, 17117, 17123, 17137, 17159,
|
||||
17167, 17183, 17189, 17191, 17203, 17207, 17209, 17231,
|
||||
17239, 17257, 17291, 17293, 17299, 17317, 17321, 17327,
|
||||
17333, 17341, 17351, 17359, 17377, 17383, 17387, 17389,
|
||||
17393, 17401, 17417, 17419, 17431, 17443, 17449, 17467,
|
||||
17471, 17477, 17483, 17489, 17491, 17497, 17509, 17519,
|
||||
17539, 17551, 17569, 17573, 17579, 17581, 17597, 17599,
|
||||
17609, 17623, 17627, 17657, 17659, 17669, 17681, 17683,
|
||||
17707, 17713, 17729, 17737, 17747, 17749, 17761, 17783,
|
||||
17789, 17791, 17807, 17827, 17837, 17839, 17851, 17863,
|
||||
#endif
|
||||
};
|
||||
@@ -0,0 +1,352 @@
|
||||
/* crypto/bn/bn_print.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ctype.h>
|
||||
#include "cryptlib.h"
|
||||
#include <openssl/buffer.h>
|
||||
#include "bn_lcl.h"
|
||||
|
||||
static const char Hex[] = "0123456789ABCDEF";
|
||||
|
||||
/* Must 'OPENSSL_free' the returned data */
|
||||
char *BN_bn2hex(const BIGNUM *a)
|
||||
{
|
||||
int i, j, v, z = 0;
|
||||
char *buf;
|
||||
char *p;
|
||||
|
||||
if (a->neg && BN_is_zero(a)) {
|
||||
/* "-0" == 3 bytes including NULL terminator */
|
||||
buf = OPENSSL_malloc(3);
|
||||
} else {
|
||||
buf = OPENSSL_malloc(a->top * BN_BYTES * 2 + 2);
|
||||
}
|
||||
if (buf == NULL) {
|
||||
BNerr(BN_F_BN_BN2HEX, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
p = buf;
|
||||
if (a->neg)
|
||||
*(p++) = '-';
|
||||
if (BN_is_zero(a))
|
||||
*(p++) = '0';
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
for (j = BN_BITS2 - 8; j >= 0; j -= 8) {
|
||||
/* strip leading zeros */
|
||||
v = ((int)(a->d[i] >> (long)j)) & 0xff;
|
||||
if (z || (v != 0)) {
|
||||
*(p++) = Hex[v >> 4];
|
||||
*(p++) = Hex[v & 0x0f];
|
||||
z = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
err:
|
||||
return (buf);
|
||||
}
|
||||
|
||||
/* Must 'OPENSSL_free' the returned data */
|
||||
char *BN_bn2dec(const BIGNUM *a)
|
||||
{
|
||||
int i = 0, num, ok = 0;
|
||||
char *buf = NULL;
|
||||
char *p;
|
||||
BIGNUM *t = NULL;
|
||||
BN_ULONG *bn_data = NULL, *lp;
|
||||
|
||||
/*-
|
||||
* get an upper bound for the length of the decimal integer
|
||||
* num <= (BN_num_bits(a) + 1) * log(2)
|
||||
* <= 3 * BN_num_bits(a) * 0.1001 + log(2) + 1 (rounding error)
|
||||
* <= BN_num_bits(a)/10 + BN_num_bits/1000 + 1 + 1
|
||||
*/
|
||||
i = BN_num_bits(a) * 3;
|
||||
num = (i / 10 + i / 1000 + 1) + 1;
|
||||
bn_data =
|
||||
(BN_ULONG *)OPENSSL_malloc((num / BN_DEC_NUM + 1) * sizeof(BN_ULONG));
|
||||
buf = (char *)OPENSSL_malloc(num + 3);
|
||||
if ((buf == NULL) || (bn_data == NULL)) {
|
||||
BNerr(BN_F_BN_BN2DEC, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
if ((t = BN_dup(a)) == NULL)
|
||||
goto err;
|
||||
|
||||
#define BUF_REMAIN (num+3 - (size_t)(p - buf))
|
||||
p = buf;
|
||||
lp = bn_data;
|
||||
if (BN_is_zero(t)) {
|
||||
*(p++) = '0';
|
||||
*(p++) = '\0';
|
||||
} else {
|
||||
if (BN_is_negative(t))
|
||||
*p++ = '-';
|
||||
|
||||
i = 0;
|
||||
while (!BN_is_zero(t)) {
|
||||
*lp = BN_div_word(t, BN_DEC_CONV);
|
||||
lp++;
|
||||
}
|
||||
lp--;
|
||||
/*
|
||||
* We now have a series of blocks, BN_DEC_NUM chars in length, where
|
||||
* the last one needs truncation. The blocks need to be reversed in
|
||||
* order.
|
||||
*/
|
||||
BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT1, *lp);
|
||||
while (*p)
|
||||
p++;
|
||||
while (lp != bn_data) {
|
||||
lp--;
|
||||
BIO_snprintf(p, BUF_REMAIN, BN_DEC_FMT2, *lp);
|
||||
while (*p)
|
||||
p++;
|
||||
}
|
||||
}
|
||||
ok = 1;
|
||||
err:
|
||||
if (bn_data != NULL)
|
||||
OPENSSL_free(bn_data);
|
||||
if (t != NULL)
|
||||
BN_free(t);
|
||||
if (!ok && buf) {
|
||||
OPENSSL_free(buf);
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
return (buf);
|
||||
}
|
||||
|
||||
int BN_hex2bn(BIGNUM **bn, const char *a)
|
||||
{
|
||||
BIGNUM *ret = NULL;
|
||||
BN_ULONG l = 0;
|
||||
int neg = 0, h, m, i, j, k, c;
|
||||
int num;
|
||||
|
||||
if ((a == NULL) || (*a == '\0'))
|
||||
return (0);
|
||||
|
||||
if (*a == '-') {
|
||||
neg = 1;
|
||||
a++;
|
||||
}
|
||||
|
||||
for (i = 0; isxdigit((unsigned char)a[i]); i++) ;
|
||||
|
||||
num = i + neg;
|
||||
if (bn == NULL)
|
||||
return (num);
|
||||
|
||||
/* a is the start of the hex digits, and it is 'i' long */
|
||||
if (*bn == NULL) {
|
||||
if ((ret = BN_new()) == NULL)
|
||||
return (0);
|
||||
} else {
|
||||
ret = *bn;
|
||||
BN_zero(ret);
|
||||
}
|
||||
|
||||
/* i is the number of hex digests; */
|
||||
if (bn_expand(ret, i * 4) == NULL)
|
||||
goto err;
|
||||
|
||||
j = i; /* least significant 'hex' */
|
||||
m = 0;
|
||||
h = 0;
|
||||
while (j > 0) {
|
||||
m = ((BN_BYTES * 2) <= j) ? (BN_BYTES * 2) : j;
|
||||
l = 0;
|
||||
for (;;) {
|
||||
c = a[j - m];
|
||||
if ((c >= '0') && (c <= '9'))
|
||||
k = c - '0';
|
||||
else if ((c >= 'a') && (c <= 'f'))
|
||||
k = c - 'a' + 10;
|
||||
else if ((c >= 'A') && (c <= 'F'))
|
||||
k = c - 'A' + 10;
|
||||
else
|
||||
k = 0; /* paranoia */
|
||||
l = (l << 4) | k;
|
||||
|
||||
if (--m <= 0) {
|
||||
ret->d[h++] = l;
|
||||
break;
|
||||
}
|
||||
}
|
||||
j -= (BN_BYTES * 2);
|
||||
}
|
||||
ret->top = h;
|
||||
bn_correct_top(ret);
|
||||
ret->neg = neg;
|
||||
|
||||
*bn = ret;
|
||||
bn_check_top(ret);
|
||||
return (num);
|
||||
err:
|
||||
if (*bn == NULL)
|
||||
BN_free(ret);
|
||||
return (0);
|
||||
}
|
||||
|
||||
int BN_dec2bn(BIGNUM **bn, const char *a)
|
||||
{
|
||||
BIGNUM *ret = NULL;
|
||||
BN_ULONG l = 0;
|
||||
int neg = 0, i, j;
|
||||
int num;
|
||||
|
||||
if ((a == NULL) || (*a == '\0'))
|
||||
return (0);
|
||||
if (*a == '-') {
|
||||
neg = 1;
|
||||
a++;
|
||||
}
|
||||
|
||||
for (i = 0; isdigit((unsigned char)a[i]); i++) ;
|
||||
|
||||
num = i + neg;
|
||||
if (bn == NULL)
|
||||
return (num);
|
||||
|
||||
/*
|
||||
* a is the start of the digits, and it is 'i' long. We chop it into
|
||||
* BN_DEC_NUM digits at a time
|
||||
*/
|
||||
if (*bn == NULL) {
|
||||
if ((ret = BN_new()) == NULL)
|
||||
return (0);
|
||||
} else {
|
||||
ret = *bn;
|
||||
BN_zero(ret);
|
||||
}
|
||||
|
||||
/* i is the number of digests, a bit of an over expand; */
|
||||
if (bn_expand(ret, i * 4) == NULL)
|
||||
goto err;
|
||||
|
||||
j = BN_DEC_NUM - (i % BN_DEC_NUM);
|
||||
if (j == BN_DEC_NUM)
|
||||
j = 0;
|
||||
l = 0;
|
||||
while (*a) {
|
||||
l *= 10;
|
||||
l += *a - '0';
|
||||
a++;
|
||||
if (++j == BN_DEC_NUM) {
|
||||
BN_mul_word(ret, BN_DEC_CONV);
|
||||
BN_add_word(ret, l);
|
||||
l = 0;
|
||||
j = 0;
|
||||
}
|
||||
}
|
||||
ret->neg = neg;
|
||||
|
||||
bn_correct_top(ret);
|
||||
*bn = ret;
|
||||
bn_check_top(ret);
|
||||
return (num);
|
||||
err:
|
||||
if (*bn == NULL)
|
||||
BN_free(ret);
|
||||
return (0);
|
||||
}
|
||||
|
||||
#ifndef OPENSSL_NO_BIO
|
||||
# ifndef OPENSSL_NO_FP_API
|
||||
int BN_print_fp(FILE *fp, const BIGNUM *a)
|
||||
{
|
||||
BIO *b;
|
||||
int ret;
|
||||
|
||||
if ((b = BIO_new(BIO_s_file())) == NULL)
|
||||
return (0);
|
||||
BIO_set_fp(b, fp, BIO_NOCLOSE);
|
||||
ret = BN_print(b, a);
|
||||
BIO_free(b);
|
||||
return (ret);
|
||||
}
|
||||
# endif
|
||||
|
||||
int BN_print(BIO *bp, const BIGNUM *a)
|
||||
{
|
||||
int i, j, v, z = 0;
|
||||
int ret = 0;
|
||||
|
||||
if ((a->neg) && (BIO_write(bp, "-", 1) != 1))
|
||||
goto end;
|
||||
if (BN_is_zero(a) && (BIO_write(bp, "0", 1) != 1))
|
||||
goto end;
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
for (j = BN_BITS2 - 4; j >= 0; j -= 4) {
|
||||
/* strip leading zeros */
|
||||
v = ((int)(a->d[i] >> (long)j)) & 0x0f;
|
||||
if (z || (v != 0)) {
|
||||
if (BIO_write(bp, &(Hex[v]), 1) != 1)
|
||||
goto end;
|
||||
z = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
end:
|
||||
return (ret);
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,294 @@
|
||||
/* crypto/bn/bn_rand.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2001 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
#include <openssl/rand.h>
|
||||
|
||||
static int bnrand(int pseudorand, BIGNUM *rnd, int bits, int top, int bottom)
|
||||
{
|
||||
unsigned char *buf = NULL;
|
||||
int ret = 0, bit, bytes, mask;
|
||||
time_t tim;
|
||||
|
||||
if (bits < 0 || (bits == 1 && top > 0)) {
|
||||
BNerr(BN_F_BNRAND, BN_R_BITS_TOO_SMALL);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (bits == 0) {
|
||||
BN_zero(rnd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bytes = (bits + 7) / 8;
|
||||
bit = (bits - 1) % 8;
|
||||
mask = 0xff << (bit + 1);
|
||||
|
||||
buf = (unsigned char *)OPENSSL_malloc(bytes);
|
||||
if (buf == NULL) {
|
||||
BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* make a random number and set the top and bottom bits */
|
||||
time(&tim);
|
||||
RAND_add(&tim, sizeof(tim), 0.0);
|
||||
|
||||
if (pseudorand) {
|
||||
if (RAND_pseudo_bytes(buf, bytes) == -1)
|
||||
goto err;
|
||||
} else {
|
||||
if (RAND_bytes(buf, bytes) <= 0)
|
||||
goto err;
|
||||
}
|
||||
|
||||
#if 1
|
||||
if (pseudorand == 2) {
|
||||
/*
|
||||
* generate patterns that are more likely to trigger BN library bugs
|
||||
*/
|
||||
int i;
|
||||
unsigned char c;
|
||||
|
||||
for (i = 0; i < bytes; i++) {
|
||||
RAND_pseudo_bytes(&c, 1);
|
||||
if (c >= 128 && i > 0)
|
||||
buf[i] = buf[i - 1];
|
||||
else if (c < 42)
|
||||
buf[i] = 0;
|
||||
else if (c < 84)
|
||||
buf[i] = 255;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (top >= 0) {
|
||||
if (top) {
|
||||
if (bit == 0) {
|
||||
buf[0] = 1;
|
||||
buf[1] |= 0x80;
|
||||
} else {
|
||||
buf[0] |= (3 << (bit - 1));
|
||||
}
|
||||
} else {
|
||||
buf[0] |= (1 << bit);
|
||||
}
|
||||
}
|
||||
buf[0] &= ~mask;
|
||||
if (bottom) /* set bottom bit if requested */
|
||||
buf[bytes - 1] |= 1;
|
||||
if (!BN_bin2bn(buf, bytes, rnd))
|
||||
goto err;
|
||||
ret = 1;
|
||||
err:
|
||||
if (buf != NULL) {
|
||||
OPENSSL_cleanse(buf, bytes);
|
||||
OPENSSL_free(buf);
|
||||
}
|
||||
bn_check_top(rnd);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int BN_rand(BIGNUM *rnd, int bits, int top, int bottom)
|
||||
{
|
||||
return bnrand(0, rnd, bits, top, bottom);
|
||||
}
|
||||
|
||||
int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom)
|
||||
{
|
||||
return bnrand(1, rnd, bits, top, bottom);
|
||||
}
|
||||
|
||||
#if 1
|
||||
int BN_bntest_rand(BIGNUM *rnd, int bits, int top, int bottom)
|
||||
{
|
||||
return bnrand(2, rnd, bits, top, bottom);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* random number r: 0 <= r < range */
|
||||
static int bn_rand_range(int pseudo, BIGNUM *r, const BIGNUM *range)
|
||||
{
|
||||
int (*bn_rand) (BIGNUM *, int, int, int) =
|
||||
pseudo ? BN_pseudo_rand : BN_rand;
|
||||
int n;
|
||||
int count = 100;
|
||||
|
||||
if (range->neg || BN_is_zero(range)) {
|
||||
BNerr(BN_F_BN_RAND_RANGE, BN_R_INVALID_RANGE);
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = BN_num_bits(range); /* n > 0 */
|
||||
|
||||
/* BN_is_bit_set(range, n - 1) always holds */
|
||||
|
||||
if (n == 1)
|
||||
BN_zero(r);
|
||||
else if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
|
||||
/*
|
||||
* range = 100..._2, so 3*range (= 11..._2) is exactly one bit longer
|
||||
* than range
|
||||
*/
|
||||
do {
|
||||
if (!bn_rand(r, n + 1, -1, 0))
|
||||
return 0;
|
||||
/*
|
||||
* If r < 3*range, use r := r MOD range (which is either r, r -
|
||||
* range, or r - 2*range). Otherwise, iterate once more. Since
|
||||
* 3*range = 11..._2, each iteration succeeds with probability >=
|
||||
* .75.
|
||||
*/
|
||||
if (BN_cmp(r, range) >= 0) {
|
||||
if (!BN_sub(r, r, range))
|
||||
return 0;
|
||||
if (BN_cmp(r, range) >= 0)
|
||||
if (!BN_sub(r, r, range))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!--count) {
|
||||
BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
while (BN_cmp(r, range) >= 0);
|
||||
} else {
|
||||
do {
|
||||
/* range = 11..._2 or range = 101..._2 */
|
||||
if (!bn_rand(r, n, -1, 0))
|
||||
return 0;
|
||||
|
||||
if (!--count) {
|
||||
BNerr(BN_F_BN_RAND_RANGE, BN_R_TOO_MANY_ITERATIONS);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (BN_cmp(r, range) >= 0);
|
||||
}
|
||||
|
||||
bn_check_top(r);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_rand_range(BIGNUM *r, const BIGNUM *range)
|
||||
{
|
||||
return bn_rand_range(0, r, range);
|
||||
}
|
||||
|
||||
int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range)
|
||||
{
|
||||
return bn_rand_range(1, r, range);
|
||||
}
|
||||
@@ -0,0 +1,249 @@
|
||||
/* crypto/bn/bn_recp.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
void BN_RECP_CTX_init(BN_RECP_CTX *recp)
|
||||
{
|
||||
BN_init(&(recp->N));
|
||||
BN_init(&(recp->Nr));
|
||||
recp->num_bits = 0;
|
||||
recp->flags = 0;
|
||||
}
|
||||
|
||||
BN_RECP_CTX *BN_RECP_CTX_new(void)
|
||||
{
|
||||
BN_RECP_CTX *ret;
|
||||
|
||||
if ((ret = (BN_RECP_CTX *)OPENSSL_malloc(sizeof(BN_RECP_CTX))) == NULL)
|
||||
return (NULL);
|
||||
|
||||
BN_RECP_CTX_init(ret);
|
||||
ret->flags = BN_FLG_MALLOCED;
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void BN_RECP_CTX_free(BN_RECP_CTX *recp)
|
||||
{
|
||||
if (recp == NULL)
|
||||
return;
|
||||
|
||||
BN_free(&(recp->N));
|
||||
BN_free(&(recp->Nr));
|
||||
if (recp->flags & BN_FLG_MALLOCED)
|
||||
OPENSSL_free(recp);
|
||||
}
|
||||
|
||||
int BN_RECP_CTX_set(BN_RECP_CTX *recp, const BIGNUM *d, BN_CTX *ctx)
|
||||
{
|
||||
if (!BN_copy(&(recp->N), d))
|
||||
return 0;
|
||||
BN_zero(&(recp->Nr));
|
||||
recp->num_bits = BN_num_bits(d);
|
||||
recp->shift = 0;
|
||||
return (1);
|
||||
}
|
||||
|
||||
int BN_mod_mul_reciprocal(BIGNUM *r, const BIGNUM *x, const BIGNUM *y,
|
||||
BN_RECP_CTX *recp, BN_CTX *ctx)
|
||||
{
|
||||
int ret = 0;
|
||||
BIGNUM *a;
|
||||
const BIGNUM *ca;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if ((a = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
if (y != NULL) {
|
||||
if (x == y) {
|
||||
if (!BN_sqr(a, x, ctx))
|
||||
goto err;
|
||||
} else {
|
||||
if (!BN_mul(a, x, y, ctx))
|
||||
goto err;
|
||||
}
|
||||
ca = a;
|
||||
} else
|
||||
ca = x; /* Just do the mod */
|
||||
|
||||
ret = BN_div_recp(NULL, r, ca, recp, ctx);
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(r);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m,
|
||||
BN_RECP_CTX *recp, BN_CTX *ctx)
|
||||
{
|
||||
int i, j, ret = 0;
|
||||
BIGNUM *a, *b, *d, *r;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
a = BN_CTX_get(ctx);
|
||||
b = BN_CTX_get(ctx);
|
||||
if (dv != NULL)
|
||||
d = dv;
|
||||
else
|
||||
d = BN_CTX_get(ctx);
|
||||
if (rem != NULL)
|
||||
r = rem;
|
||||
else
|
||||
r = BN_CTX_get(ctx);
|
||||
if (a == NULL || b == NULL || d == NULL || r == NULL)
|
||||
goto err;
|
||||
|
||||
if (BN_ucmp(m, &(recp->N)) < 0) {
|
||||
BN_zero(d);
|
||||
if (!BN_copy(r, m))
|
||||
return 0;
|
||||
BN_CTX_end(ctx);
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* We want the remainder Given input of ABCDEF / ab we need multiply
|
||||
* ABCDEF by 3 digests of the reciprocal of ab
|
||||
*/
|
||||
|
||||
/* i := max(BN_num_bits(m), 2*BN_num_bits(N)) */
|
||||
i = BN_num_bits(m);
|
||||
j = recp->num_bits << 1;
|
||||
if (j > i)
|
||||
i = j;
|
||||
|
||||
/* Nr := round(2^i / N) */
|
||||
if (i != recp->shift)
|
||||
recp->shift = BN_reciprocal(&(recp->Nr), &(recp->N), i, ctx);
|
||||
/* BN_reciprocal could have returned -1 for an error */
|
||||
if (recp->shift == -1)
|
||||
goto err;
|
||||
|
||||
/*-
|
||||
* d := |round(round(m / 2^BN_num_bits(N)) * recp->Nr / 2^(i - BN_num_bits(N)))|
|
||||
* = |round(round(m / 2^BN_num_bits(N)) * round(2^i / N) / 2^(i - BN_num_bits(N)))|
|
||||
* <= |(m / 2^BN_num_bits(N)) * (2^i / N) * (2^BN_num_bits(N) / 2^i)|
|
||||
* = |m/N|
|
||||
*/
|
||||
if (!BN_rshift(a, m, recp->num_bits))
|
||||
goto err;
|
||||
if (!BN_mul(b, a, &(recp->Nr), ctx))
|
||||
goto err;
|
||||
if (!BN_rshift(d, b, i - recp->num_bits))
|
||||
goto err;
|
||||
d->neg = 0;
|
||||
|
||||
if (!BN_mul(b, &(recp->N), d, ctx))
|
||||
goto err;
|
||||
if (!BN_usub(r, m, b))
|
||||
goto err;
|
||||
r->neg = 0;
|
||||
|
||||
#if 1
|
||||
j = 0;
|
||||
while (BN_ucmp(r, &(recp->N)) >= 0) {
|
||||
if (j++ > 2) {
|
||||
BNerr(BN_F_BN_DIV_RECP, BN_R_BAD_RECIPROCAL);
|
||||
goto err;
|
||||
}
|
||||
if (!BN_usub(r, r, &(recp->N)))
|
||||
goto err;
|
||||
if (!BN_add_word(d, 1))
|
||||
goto err;
|
||||
}
|
||||
#endif
|
||||
|
||||
r->neg = BN_is_zero(r) ? 0 : m->neg;
|
||||
d->neg = m->neg ^ recp->N.neg;
|
||||
ret = 1;
|
||||
err:
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(dv);
|
||||
bn_check_top(rem);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/*
|
||||
* len is the expected size of the result We actually calculate with an extra
|
||||
* word of precision, so we can do faster division if the remainder is not
|
||||
* required.
|
||||
*/
|
||||
/* r := 2^len / m */
|
||||
int BN_reciprocal(BIGNUM *r, const BIGNUM *m, int len, BN_CTX *ctx)
|
||||
{
|
||||
int ret = -1;
|
||||
BIGNUM *t;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if ((t = BN_CTX_get(ctx)) == NULL)
|
||||
goto err;
|
||||
|
||||
if (!BN_set_bit(t, len))
|
||||
goto err;
|
||||
|
||||
if (!BN_div(r, NULL, t, m, ctx))
|
||||
goto err;
|
||||
|
||||
ret = len;
|
||||
err:
|
||||
bn_check_top(r);
|
||||
BN_CTX_end(ctx);
|
||||
return (ret);
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/* crypto/bn/bn_shift.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
int BN_lshift1(BIGNUM *r, const BIGNUM *a)
|
||||
{
|
||||
register BN_ULONG *ap, *rp, t, c;
|
||||
int i;
|
||||
|
||||
bn_check_top(r);
|
||||
bn_check_top(a);
|
||||
|
||||
if (r != a) {
|
||||
r->neg = a->neg;
|
||||
if (bn_wexpand(r, a->top + 1) == NULL)
|
||||
return (0);
|
||||
r->top = a->top;
|
||||
} else {
|
||||
if (bn_wexpand(r, a->top + 1) == NULL)
|
||||
return (0);
|
||||
}
|
||||
ap = a->d;
|
||||
rp = r->d;
|
||||
c = 0;
|
||||
for (i = 0; i < a->top; i++) {
|
||||
t = *(ap++);
|
||||
*(rp++) = ((t << 1) | c) & BN_MASK2;
|
||||
c = (t & BN_TBIT) ? 1 : 0;
|
||||
}
|
||||
if (c) {
|
||||
*rp = 1;
|
||||
r->top++;
|
||||
}
|
||||
bn_check_top(r);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int BN_rshift1(BIGNUM *r, const BIGNUM *a)
|
||||
{
|
||||
BN_ULONG *ap, *rp, t, c;
|
||||
int i;
|
||||
|
||||
bn_check_top(r);
|
||||
bn_check_top(a);
|
||||
|
||||
if (BN_is_zero(a)) {
|
||||
BN_zero(r);
|
||||
return (1);
|
||||
}
|
||||
if (a != r) {
|
||||
if (bn_wexpand(r, a->top) == NULL)
|
||||
return (0);
|
||||
r->top = a->top;
|
||||
r->neg = a->neg;
|
||||
}
|
||||
ap = a->d;
|
||||
rp = r->d;
|
||||
c = 0;
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
t = ap[i];
|
||||
rp[i] = ((t >> 1) & BN_MASK2) | c;
|
||||
c = (t & 1) ? BN_TBIT : 0;
|
||||
}
|
||||
bn_correct_top(r);
|
||||
bn_check_top(r);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int BN_lshift(BIGNUM *r, const BIGNUM *a, int n)
|
||||
{
|
||||
int i, nw, lb, rb;
|
||||
BN_ULONG *t, *f;
|
||||
BN_ULONG l;
|
||||
|
||||
bn_check_top(r);
|
||||
bn_check_top(a);
|
||||
|
||||
if (n < 0) {
|
||||
BNerr(BN_F_BN_LSHIFT, BN_R_INVALID_SHIFT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
r->neg = a->neg;
|
||||
nw = n / BN_BITS2;
|
||||
if (bn_wexpand(r, a->top + nw + 1) == NULL)
|
||||
return (0);
|
||||
lb = n % BN_BITS2;
|
||||
rb = BN_BITS2 - lb;
|
||||
f = a->d;
|
||||
t = r->d;
|
||||
t[a->top + nw] = 0;
|
||||
if (lb == 0)
|
||||
for (i = a->top - 1; i >= 0; i--)
|
||||
t[nw + i] = f[i];
|
||||
else
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
l = f[i];
|
||||
t[nw + i + 1] |= (l >> rb) & BN_MASK2;
|
||||
t[nw + i] = (l << lb) & BN_MASK2;
|
||||
}
|
||||
memset(t, 0, nw * sizeof(t[0]));
|
||||
/*
|
||||
* for (i=0; i<nw; i++) t[i]=0;
|
||||
*/
|
||||
r->top = a->top + nw + 1;
|
||||
bn_correct_top(r);
|
||||
bn_check_top(r);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int BN_rshift(BIGNUM *r, const BIGNUM *a, int n)
|
||||
{
|
||||
int i, j, nw, lb, rb;
|
||||
BN_ULONG *t, *f;
|
||||
BN_ULONG l, tmp;
|
||||
|
||||
bn_check_top(r);
|
||||
bn_check_top(a);
|
||||
|
||||
if (n < 0) {
|
||||
BNerr(BN_F_BN_RSHIFT, BN_R_INVALID_SHIFT);
|
||||
return 0;
|
||||
}
|
||||
|
||||
nw = n / BN_BITS2;
|
||||
rb = n % BN_BITS2;
|
||||
lb = BN_BITS2 - rb;
|
||||
if (nw >= a->top || a->top == 0) {
|
||||
BN_zero(r);
|
||||
return (1);
|
||||
}
|
||||
if (r != a) {
|
||||
r->neg = a->neg;
|
||||
if (bn_wexpand(r, a->top - nw + 1) == NULL)
|
||||
return (0);
|
||||
} else {
|
||||
if (n == 0)
|
||||
return 1; /* or the copying loop will go berserk */
|
||||
}
|
||||
|
||||
f = &(a->d[nw]);
|
||||
t = r->d;
|
||||
j = a->top - nw;
|
||||
r->top = j;
|
||||
|
||||
if (rb == 0) {
|
||||
for (i = j; i != 0; i--)
|
||||
*(t++) = *(f++);
|
||||
} else {
|
||||
l = *(f++);
|
||||
for (i = j - 1; i != 0; i--) {
|
||||
tmp = (l >> rb) & BN_MASK2;
|
||||
l = *(f++);
|
||||
*(t++) = (tmp | (l << lb)) & BN_MASK2;
|
||||
}
|
||||
*(t++) = (l >> rb) & BN_MASK2;
|
||||
}
|
||||
bn_correct_top(r);
|
||||
bn_check_top(r);
|
||||
return (1);
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
/* crypto/bn/bn_sqr.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
/* r must not be a */
|
||||
/*
|
||||
* I've just gone over this and it is now %20 faster on x86 - eay - 27 Jun 96
|
||||
*/
|
||||
int BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
|
||||
{
|
||||
int max, al;
|
||||
int ret = 0;
|
||||
BIGNUM *tmp, *rr;
|
||||
|
||||
#ifdef BN_COUNT
|
||||
fprintf(stderr, "BN_sqr %d * %d\n", a->top, a->top);
|
||||
#endif
|
||||
bn_check_top(a);
|
||||
|
||||
al = a->top;
|
||||
if (al <= 0) {
|
||||
r->top = 0;
|
||||
r->neg = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
rr = (a != r) ? r : BN_CTX_get(ctx);
|
||||
tmp = BN_CTX_get(ctx);
|
||||
if (!rr || !tmp)
|
||||
goto err;
|
||||
|
||||
max = 2 * al; /* Non-zero (from above) */
|
||||
if (bn_wexpand(rr, max) == NULL)
|
||||
goto err;
|
||||
|
||||
if (al == 4) {
|
||||
#ifndef BN_SQR_COMBA
|
||||
BN_ULONG t[8];
|
||||
bn_sqr_normal(rr->d, a->d, 4, t);
|
||||
#else
|
||||
bn_sqr_comba4(rr->d, a->d);
|
||||
#endif
|
||||
} else if (al == 8) {
|
||||
#ifndef BN_SQR_COMBA
|
||||
BN_ULONG t[16];
|
||||
bn_sqr_normal(rr->d, a->d, 8, t);
|
||||
#else
|
||||
bn_sqr_comba8(rr->d, a->d);
|
||||
#endif
|
||||
} else {
|
||||
#if defined(BN_RECURSION)
|
||||
if (al < BN_SQR_RECURSIVE_SIZE_NORMAL) {
|
||||
BN_ULONG t[BN_SQR_RECURSIVE_SIZE_NORMAL * 2];
|
||||
bn_sqr_normal(rr->d, a->d, al, t);
|
||||
} else {
|
||||
int j, k;
|
||||
|
||||
j = BN_num_bits_word((BN_ULONG)al);
|
||||
j = 1 << (j - 1);
|
||||
k = j + j;
|
||||
if (al == j) {
|
||||
if (bn_wexpand(tmp, k * 2) == NULL)
|
||||
goto err;
|
||||
bn_sqr_recursive(rr->d, a->d, al, tmp->d);
|
||||
} else {
|
||||
if (bn_wexpand(tmp, max) == NULL)
|
||||
goto err;
|
||||
bn_sqr_normal(rr->d, a->d, al, tmp->d);
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (bn_wexpand(tmp, max) == NULL)
|
||||
goto err;
|
||||
bn_sqr_normal(rr->d, a->d, al, tmp->d);
|
||||
#endif
|
||||
}
|
||||
|
||||
rr->neg = 0;
|
||||
/*
|
||||
* If the most-significant half of the top word of 'a' is zero, then the
|
||||
* square of 'a' will max-1 words.
|
||||
*/
|
||||
if (a->d[al - 1] == (a->d[al - 1] & BN_MASK2l))
|
||||
rr->top = max - 1;
|
||||
else
|
||||
rr->top = max;
|
||||
if (rr != r)
|
||||
BN_copy(r, rr);
|
||||
ret = 1;
|
||||
err:
|
||||
bn_check_top(rr);
|
||||
bn_check_top(tmp);
|
||||
BN_CTX_end(ctx);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
/* tmp must have 2*n words */
|
||||
void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp)
|
||||
{
|
||||
int i, j, max;
|
||||
const BN_ULONG *ap;
|
||||
BN_ULONG *rp;
|
||||
|
||||
max = n * 2;
|
||||
ap = a;
|
||||
rp = r;
|
||||
rp[0] = rp[max - 1] = 0;
|
||||
rp++;
|
||||
j = n;
|
||||
|
||||
if (--j > 0) {
|
||||
ap++;
|
||||
rp[j] = bn_mul_words(rp, ap, j, ap[-1]);
|
||||
rp += 2;
|
||||
}
|
||||
|
||||
for (i = n - 2; i > 0; i--) {
|
||||
j--;
|
||||
ap++;
|
||||
rp[j] = bn_mul_add_words(rp, ap, j, ap[-1]);
|
||||
rp += 2;
|
||||
}
|
||||
|
||||
bn_add_words(r, r, r, max);
|
||||
|
||||
/* There will not be a carry */
|
||||
|
||||
bn_sqr_words(tmp, a, n);
|
||||
|
||||
bn_add_words(r, r, tmp, max);
|
||||
}
|
||||
|
||||
#ifdef BN_RECURSION
|
||||
/*-
|
||||
* r is 2*n words in size,
|
||||
* a and b are both n words in size. (There's not actually a 'b' here ...)
|
||||
* n must be a power of 2.
|
||||
* We multiply and return the result.
|
||||
* t must be 2*n words in size
|
||||
* We calculate
|
||||
* a[0]*b[0]
|
||||
* a[0]*b[0]+a[1]*b[1]+(a[0]-a[1])*(b[1]-b[0])
|
||||
* a[1]*b[1]
|
||||
*/
|
||||
void bn_sqr_recursive(BN_ULONG *r, const BN_ULONG *a, int n2, BN_ULONG *t)
|
||||
{
|
||||
int n = n2 / 2;
|
||||
int zero, c1;
|
||||
BN_ULONG ln, lo, *p;
|
||||
|
||||
# ifdef BN_COUNT
|
||||
fprintf(stderr, " bn_sqr_recursive %d * %d\n", n2, n2);
|
||||
# endif
|
||||
if (n2 == 4) {
|
||||
# ifndef BN_SQR_COMBA
|
||||
bn_sqr_normal(r, a, 4, t);
|
||||
# else
|
||||
bn_sqr_comba4(r, a);
|
||||
# endif
|
||||
return;
|
||||
} else if (n2 == 8) {
|
||||
# ifndef BN_SQR_COMBA
|
||||
bn_sqr_normal(r, a, 8, t);
|
||||
# else
|
||||
bn_sqr_comba8(r, a);
|
||||
# endif
|
||||
return;
|
||||
}
|
||||
if (n2 < BN_SQR_RECURSIVE_SIZE_NORMAL) {
|
||||
bn_sqr_normal(r, a, n2, t);
|
||||
return;
|
||||
}
|
||||
/* r=(a[0]-a[1])*(a[1]-a[0]) */
|
||||
c1 = bn_cmp_words(a, &(a[n]), n);
|
||||
zero = 0;
|
||||
if (c1 > 0)
|
||||
bn_sub_words(t, a, &(a[n]), n);
|
||||
else if (c1 < 0)
|
||||
bn_sub_words(t, &(a[n]), a, n);
|
||||
else
|
||||
zero = 1;
|
||||
|
||||
/* The result will always be negative unless it is zero */
|
||||
p = &(t[n2 * 2]);
|
||||
|
||||
if (!zero)
|
||||
bn_sqr_recursive(&(t[n2]), t, n, p);
|
||||
else
|
||||
memset(&(t[n2]), 0, n2 * sizeof(BN_ULONG));
|
||||
bn_sqr_recursive(r, a, n, p);
|
||||
bn_sqr_recursive(&(r[n2]), &(a[n]), n, p);
|
||||
|
||||
/*-
|
||||
* t[32] holds (a[0]-a[1])*(a[1]-a[0]), it is negative or zero
|
||||
* r[10] holds (a[0]*b[0])
|
||||
* r[32] holds (b[1]*b[1])
|
||||
*/
|
||||
|
||||
c1 = (int)(bn_add_words(t, r, &(r[n2]), n2));
|
||||
|
||||
/* t[32] is negative */
|
||||
c1 -= (int)(bn_sub_words(&(t[n2]), t, &(t[n2]), n2));
|
||||
|
||||
/*-
|
||||
* t[32] holds (a[0]-a[1])*(a[1]-a[0])+(a[0]*a[0])+(a[1]*a[1])
|
||||
* r[10] holds (a[0]*a[0])
|
||||
* r[32] holds (a[1]*a[1])
|
||||
* c1 holds the carry bits
|
||||
*/
|
||||
c1 += (int)(bn_add_words(&(r[n]), &(r[n]), &(t[n2]), n2));
|
||||
if (c1) {
|
||||
p = &(r[n + n2]);
|
||||
lo = *p;
|
||||
ln = (lo + c1) & BN_MASK2;
|
||||
*p = ln;
|
||||
|
||||
/*
|
||||
* The overflow will stop before we over write words we should not
|
||||
* overwrite
|
||||
*/
|
||||
if (ln < (BN_ULONG)c1) {
|
||||
do {
|
||||
p++;
|
||||
lo = *p;
|
||||
ln = (lo + 1) & BN_MASK2;
|
||||
*p = ln;
|
||||
} while (ln == 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,395 @@
|
||||
/* crypto/bn/bn_sqrt.c */
|
||||
/*
|
||||
* Written by Lenka Fibikova <fibikova@exp-math.uni-essen.de> and Bodo
|
||||
* Moeller for the OpenSSL project.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 1998-2000 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* openssl-core@openssl.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.openssl.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
|
||||
BIGNUM *BN_mod_sqrt(BIGNUM *in, const BIGNUM *a, const BIGNUM *p, BN_CTX *ctx)
|
||||
/* Returns 'ret' such that
|
||||
* ret^2 == a (mod p),
|
||||
* using the Tonelli/Shanks algorithm (cf. Henri Cohen, "A Course
|
||||
* in Algebraic Computational Number Theory", algorithm 1.5.1).
|
||||
* 'p' must be prime!
|
||||
*/
|
||||
{
|
||||
BIGNUM *ret = in;
|
||||
int err = 1;
|
||||
int r;
|
||||
BIGNUM *A, *b, *q, *t, *x, *y;
|
||||
int e, i, j;
|
||||
|
||||
if (!BN_is_odd(p) || BN_abs_is_word(p, 1))
|
||||
{
|
||||
if (BN_abs_is_word(p, 2))
|
||||
{
|
||||
if (ret == NULL)
|
||||
ret = BN_new();
|
||||
if (ret == NULL)
|
||||
goto end;
|
||||
if (!BN_set_word(ret, BN_is_bit_set(a, 0)))
|
||||
{
|
||||
if (ret != in)
|
||||
BN_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
bn_check_top(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
if (BN_is_zero(a) || BN_is_one(a))
|
||||
{
|
||||
if (ret == NULL)
|
||||
ret = BN_new();
|
||||
if (ret == NULL)
|
||||
goto end;
|
||||
if (!BN_set_word(ret, BN_is_one(a)))
|
||||
{
|
||||
if (ret != in)
|
||||
BN_free(ret);
|
||||
return NULL;
|
||||
}
|
||||
bn_check_top(ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
A = BN_CTX_get(ctx);
|
||||
b = BN_CTX_get(ctx);
|
||||
q = BN_CTX_get(ctx);
|
||||
t = BN_CTX_get(ctx);
|
||||
x = BN_CTX_get(ctx);
|
||||
y = BN_CTX_get(ctx);
|
||||
if (y == NULL) goto end;
|
||||
|
||||
if (ret == NULL)
|
||||
ret = BN_new();
|
||||
if (ret == NULL) goto end;
|
||||
|
||||
/* A = a mod p */
|
||||
if (!BN_nnmod(A, a, p, ctx)) goto end;
|
||||
|
||||
/* now write |p| - 1 as 2^e*q where q is odd */
|
||||
e = 1;
|
||||
while (!BN_is_bit_set(p, e))
|
||||
e++;
|
||||
/* we'll set q later (if needed) */
|
||||
|
||||
if (e == 1)
|
||||
{
|
||||
/* The easy case: (|p|-1)/2 is odd, so 2 has an inverse
|
||||
* modulo (|p|-1)/2, and square roots can be computed
|
||||
* directly by modular exponentiation.
|
||||
* We have
|
||||
* 2 * (|p|+1)/4 == 1 (mod (|p|-1)/2),
|
||||
* so we can use exponent (|p|+1)/4, i.e. (|p|-3)/4 + 1.
|
||||
*/
|
||||
if (!BN_rshift(q, p, 2)) goto end;
|
||||
q->neg = 0;
|
||||
if (!BN_add_word(q, 1)) goto end;
|
||||
if (!BN_mod_exp(ret, A, q, p, ctx)) goto end;
|
||||
err = 0;
|
||||
goto vrfy;
|
||||
}
|
||||
|
||||
if (e == 2)
|
||||
{
|
||||
/* |p| == 5 (mod 8)
|
||||
*
|
||||
* In this case 2 is always a non-square since
|
||||
* Legendre(2,p) = (-1)^((p^2-1)/8) for any odd prime.
|
||||
* So if a really is a square, then 2*a is a non-square.
|
||||
* Thus for
|
||||
* b := (2*a)^((|p|-5)/8),
|
||||
* i := (2*a)*b^2
|
||||
* we have
|
||||
* i^2 = (2*a)^((1 + (|p|-5)/4)*2)
|
||||
* = (2*a)^((p-1)/2)
|
||||
* = -1;
|
||||
* so if we set
|
||||
* x := a*b*(i-1),
|
||||
* then
|
||||
* x^2 = a^2 * b^2 * (i^2 - 2*i + 1)
|
||||
* = a^2 * b^2 * (-2*i)
|
||||
* = a*(-i)*(2*a*b^2)
|
||||
* = a*(-i)*i
|
||||
* = a.
|
||||
*
|
||||
* (This is due to A.O.L. Atkin,
|
||||
* <URL: http://listserv.nodak.edu/scripts/wa.exe?A2=ind9211&L=nmbrthry&O=T&P=562>,
|
||||
* November 1992.)
|
||||
*/
|
||||
|
||||
/* t := 2*a */
|
||||
if (!BN_mod_lshift1_quick(t, A, p)) goto end;
|
||||
|
||||
/* b := (2*a)^((|p|-5)/8) */
|
||||
if (!BN_rshift(q, p, 3)) goto end;
|
||||
q->neg = 0;
|
||||
if (!BN_mod_exp(b, t, q, p, ctx)) goto end;
|
||||
|
||||
/* y := b^2 */
|
||||
if (!BN_mod_sqr(y, b, p, ctx)) goto end;
|
||||
|
||||
/* t := (2*a)*b^2 - 1*/
|
||||
if (!BN_mod_mul(t, t, y, p, ctx)) goto end;
|
||||
if (!BN_sub_word(t, 1)) goto end;
|
||||
|
||||
/* x = a*b*t */
|
||||
if (!BN_mod_mul(x, A, b, p, ctx)) goto end;
|
||||
if (!BN_mod_mul(x, x, t, p, ctx)) goto end;
|
||||
|
||||
if (!BN_copy(ret, x)) goto end;
|
||||
err = 0;
|
||||
goto vrfy;
|
||||
}
|
||||
|
||||
/* e > 2, so we really have to use the Tonelli/Shanks algorithm.
|
||||
* First, find some y that is not a square. */
|
||||
if (!BN_copy(q, p)) goto end; /* use 'q' as temp */
|
||||
q->neg = 0;
|
||||
i = 2;
|
||||
do
|
||||
{
|
||||
/* For efficiency, try small numbers first;
|
||||
* if this fails, try random numbers.
|
||||
*/
|
||||
if (i < 22)
|
||||
{
|
||||
if (!BN_set_word(y, i)) goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!BN_pseudo_rand(y, BN_num_bits(p), 0, 0)) goto end;
|
||||
if (BN_ucmp(y, p) >= 0)
|
||||
{
|
||||
if (!(p->neg ? BN_add : BN_sub)(y, y, p)) goto end;
|
||||
}
|
||||
/* now 0 <= y < |p| */
|
||||
if (BN_is_zero(y))
|
||||
if (!BN_set_word(y, i)) goto end;
|
||||
}
|
||||
|
||||
r = BN_kronecker(y, q, ctx); /* here 'q' is |p| */
|
||||
if (r < -1) goto end;
|
||||
if (r == 0)
|
||||
{
|
||||
/* m divides p */
|
||||
BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
while (r == 1 && ++i < 82);
|
||||
|
||||
if (r != -1)
|
||||
{
|
||||
/* Many rounds and still no non-square -- this is more likely
|
||||
* a bug than just bad luck.
|
||||
* Even if p is not prime, we should have found some y
|
||||
* such that r == -1.
|
||||
*/
|
||||
BNerr(BN_F_BN_MOD_SQRT, BN_R_TOO_MANY_ITERATIONS);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Here's our actual 'q': */
|
||||
if (!BN_rshift(q, q, e)) goto end;
|
||||
|
||||
/* Now that we have some non-square, we can find an element
|
||||
* of order 2^e by computing its q'th power. */
|
||||
if (!BN_mod_exp(y, y, q, p, ctx)) goto end;
|
||||
if (BN_is_one(y))
|
||||
{
|
||||
BNerr(BN_F_BN_MOD_SQRT, BN_R_P_IS_NOT_PRIME);
|
||||
goto end;
|
||||
}
|
||||
|
||||
/* Now we know that (if p is indeed prime) there is an integer
|
||||
* k, 0 <= k < 2^e, such that
|
||||
*
|
||||
* a^q * y^k == 1 (mod p).
|
||||
*
|
||||
* As a^q is a square and y is not, k must be even.
|
||||
* q+1 is even, too, so there is an element
|
||||
*
|
||||
* X := a^((q+1)/2) * y^(k/2),
|
||||
*
|
||||
* and it satisfies
|
||||
*
|
||||
* X^2 = a^q * a * y^k
|
||||
* = a,
|
||||
*
|
||||
* so it is the square root that we are looking for.
|
||||
*/
|
||||
|
||||
/* t := (q-1)/2 (note that q is odd) */
|
||||
if (!BN_rshift1(t, q)) goto end;
|
||||
|
||||
/* x := a^((q-1)/2) */
|
||||
if (BN_is_zero(t)) /* special case: p = 2^e + 1 */
|
||||
{
|
||||
if (!BN_nnmod(t, A, p, ctx)) goto end;
|
||||
if (BN_is_zero(t))
|
||||
{
|
||||
/* special case: a == 0 (mod p) */
|
||||
BN_zero(ret);
|
||||
err = 0;
|
||||
goto end;
|
||||
}
|
||||
else
|
||||
if (!BN_one(x)) goto end;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!BN_mod_exp(x, A, t, p, ctx)) goto end;
|
||||
if (BN_is_zero(x))
|
||||
{
|
||||
/* special case: a == 0 (mod p) */
|
||||
BN_zero(ret);
|
||||
err = 0;
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* b := a*x^2 (= a^q) */
|
||||
if (!BN_mod_sqr(b, x, p, ctx)) goto end;
|
||||
if (!BN_mod_mul(b, b, A, p, ctx)) goto end;
|
||||
|
||||
/* x := a*x (= a^((q+1)/2)) */
|
||||
if (!BN_mod_mul(x, x, A, p, ctx)) goto end;
|
||||
|
||||
while (1)
|
||||
{
|
||||
/* Now b is a^q * y^k for some even k (0 <= k < 2^E
|
||||
* where E refers to the original value of e, which we
|
||||
* don't keep in a variable), and x is a^((q+1)/2) * y^(k/2).
|
||||
*
|
||||
* We have a*b = x^2,
|
||||
* y^2^(e-1) = -1,
|
||||
* b^2^(e-1) = 1.
|
||||
*/
|
||||
|
||||
if (BN_is_one(b))
|
||||
{
|
||||
if (!BN_copy(ret, x)) goto end;
|
||||
err = 0;
|
||||
goto vrfy;
|
||||
}
|
||||
|
||||
|
||||
/* find smallest i such that b^(2^i) = 1 */
|
||||
i = 1;
|
||||
if (!BN_mod_sqr(t, b, p, ctx)) goto end;
|
||||
while (!BN_is_one(t))
|
||||
{
|
||||
i++;
|
||||
if (i == e)
|
||||
{
|
||||
BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
|
||||
goto end;
|
||||
}
|
||||
if (!BN_mod_mul(t, t, t, p, ctx)) goto end;
|
||||
}
|
||||
|
||||
|
||||
/* t := y^2^(e - i - 1) */
|
||||
if (!BN_copy(t, y)) goto end;
|
||||
for (j = e - i - 1; j > 0; j--)
|
||||
{
|
||||
if (!BN_mod_sqr(t, t, p, ctx)) goto end;
|
||||
}
|
||||
if (!BN_mod_mul(y, t, t, p, ctx)) goto end;
|
||||
if (!BN_mod_mul(x, x, t, p, ctx)) goto end;
|
||||
if (!BN_mod_mul(b, b, y, p, ctx)) goto end;
|
||||
e = i;
|
||||
}
|
||||
|
||||
vrfy:
|
||||
if (!err)
|
||||
{
|
||||
/* verify the result -- the input might have been not a square
|
||||
* (test added in 0.9.8) */
|
||||
|
||||
if (!BN_mod_sqr(x, ret, p, ctx))
|
||||
err = 1;
|
||||
|
||||
if (!err && 0 != BN_cmp(x, A))
|
||||
{
|
||||
BNerr(BN_F_BN_MOD_SQRT, BN_R_NOT_A_SQUARE);
|
||||
err = 1;
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
if (err) {
|
||||
if (ret != NULL && ret != in) {
|
||||
BN_clear_free(ret);
|
||||
}
|
||||
ret = NULL;
|
||||
}
|
||||
BN_CTX_end(ctx);
|
||||
bn_check_top(ret);
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,227 @@
|
||||
/* crypto/bn/bn_word.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "cryptlib.h"
|
||||
#include "bn_lcl.h"
|
||||
|
||||
BN_ULONG BN_mod_word(const BIGNUM *a, BN_ULONG w)
|
||||
{
|
||||
#ifndef BN_LLONG
|
||||
BN_ULONG ret = 0;
|
||||
#else
|
||||
BN_ULLONG ret = 0;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
if (w == 0)
|
||||
return (BN_ULONG)-1;
|
||||
|
||||
bn_check_top(a);
|
||||
w &= BN_MASK2;
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
#ifndef BN_LLONG
|
||||
ret = ((ret << BN_BITS4) | ((a->d[i] >> BN_BITS4) & BN_MASK2l)) % w;
|
||||
ret = ((ret << BN_BITS4) | (a->d[i] & BN_MASK2l)) % w;
|
||||
#else
|
||||
ret = (BN_ULLONG) (((ret << (BN_ULLONG) BN_BITS2) | a->d[i]) %
|
||||
(BN_ULLONG) w);
|
||||
#endif
|
||||
}
|
||||
return ((BN_ULONG)ret);
|
||||
}
|
||||
|
||||
BN_ULONG BN_div_word(BIGNUM *a, BN_ULONG w)
|
||||
{
|
||||
BN_ULONG ret = 0;
|
||||
int i, j;
|
||||
|
||||
bn_check_top(a);
|
||||
w &= BN_MASK2;
|
||||
|
||||
if (!w)
|
||||
/* actually this an error (division by zero) */
|
||||
return (BN_ULONG)-1;
|
||||
if (a->top == 0)
|
||||
return 0;
|
||||
|
||||
/* normalize input (so bn_div_words doesn't complain) */
|
||||
j = BN_BITS2 - BN_num_bits_word(w);
|
||||
w <<= j;
|
||||
if (!BN_lshift(a, a, j))
|
||||
return (BN_ULONG)-1;
|
||||
|
||||
for (i = a->top - 1; i >= 0; i--) {
|
||||
BN_ULONG l, d;
|
||||
|
||||
l = a->d[i];
|
||||
d = bn_div_words(ret, l, w);
|
||||
ret = (l - ((d * w) & BN_MASK2)) & BN_MASK2;
|
||||
a->d[i] = d;
|
||||
}
|
||||
if ((a->top > 0) && (a->d[a->top - 1] == 0))
|
||||
a->top--;
|
||||
ret >>= j;
|
||||
bn_check_top(a);
|
||||
return (ret);
|
||||
}
|
||||
|
||||
int BN_add_word(BIGNUM *a, BN_ULONG w)
|
||||
{
|
||||
BN_ULONG l;
|
||||
int i;
|
||||
|
||||
bn_check_top(a);
|
||||
w &= BN_MASK2;
|
||||
|
||||
/* degenerate case: w is zero */
|
||||
if (!w)
|
||||
return 1;
|
||||
/* degenerate case: a is zero */
|
||||
if (BN_is_zero(a))
|
||||
return BN_set_word(a, w);
|
||||
/* handle 'a' when negative */
|
||||
if (a->neg) {
|
||||
a->neg = 0;
|
||||
i = BN_sub_word(a, w);
|
||||
if (!BN_is_zero(a))
|
||||
a->neg = !(a->neg);
|
||||
return (i);
|
||||
}
|
||||
for (i = 0; w != 0 && i < a->top; i++) {
|
||||
a->d[i] = l = (a->d[i] + w) & BN_MASK2;
|
||||
w = (w > l) ? 1 : 0;
|
||||
}
|
||||
if (w && i == a->top) {
|
||||
if (bn_wexpand(a, a->top + 1) == NULL)
|
||||
return 0;
|
||||
a->top++;
|
||||
a->d[i] = w;
|
||||
}
|
||||
bn_check_top(a);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int BN_sub_word(BIGNUM *a, BN_ULONG w)
|
||||
{
|
||||
int i;
|
||||
|
||||
bn_check_top(a);
|
||||
w &= BN_MASK2;
|
||||
|
||||
/* degenerate case: w is zero */
|
||||
if (!w)
|
||||
return 1;
|
||||
/* degenerate case: a is zero */
|
||||
if (BN_is_zero(a)) {
|
||||
i = BN_set_word(a, w);
|
||||
if (i != 0)
|
||||
BN_set_negative(a, 1);
|
||||
return i;
|
||||
}
|
||||
/* handle 'a' when negative */
|
||||
if (a->neg) {
|
||||
a->neg = 0;
|
||||
i = BN_add_word(a, w);
|
||||
a->neg = 1;
|
||||
return (i);
|
||||
}
|
||||
|
||||
if ((a->top == 1) && (a->d[0] < w)) {
|
||||
a->d[0] = w - a->d[0];
|
||||
a->neg = 1;
|
||||
return (1);
|
||||
}
|
||||
i = 0;
|
||||
for (;;) {
|
||||
if (a->d[i] >= w) {
|
||||
a->d[i] -= w;
|
||||
break;
|
||||
} else {
|
||||
a->d[i] = (a->d[i] - w) & BN_MASK2;
|
||||
i++;
|
||||
w = 1;
|
||||
}
|
||||
}
|
||||
if ((a->d[i] == 0) && (i == (a->top - 1)))
|
||||
a->top--;
|
||||
bn_check_top(a);
|
||||
return (1);
|
||||
}
|
||||
|
||||
int BN_mul_word(BIGNUM *a, BN_ULONG w)
|
||||
{
|
||||
BN_ULONG ll;
|
||||
|
||||
bn_check_top(a);
|
||||
w &= BN_MASK2;
|
||||
if (a->top) {
|
||||
if (w == 0)
|
||||
BN_zero(a);
|
||||
else {
|
||||
ll = bn_mul_words(a->d, a->d, a->top, w);
|
||||
if (ll) {
|
||||
if (bn_wexpand(a, a->top + 1) == NULL)
|
||||
return (0);
|
||||
a->d[a->top++] = ll;
|
||||
}
|
||||
}
|
||||
}
|
||||
bn_check_top(a);
|
||||
return (1);
|
||||
}
|
||||
@@ -0,0 +1,274 @@
|
||||
/* bn_x931p.c */
|
||||
/*
|
||||
* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL project
|
||||
* 2005.
|
||||
*/
|
||||
/* ====================================================================
|
||||
* Copyright (c) 2005 The OpenSSL Project. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* 3. All advertising materials mentioning features or use of this
|
||||
* software must display the following acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
|
||||
* endorse or promote products derived from this software without
|
||||
* prior written permission. For written permission, please contact
|
||||
* licensing@OpenSSL.org.
|
||||
*
|
||||
* 5. Products derived from this software may not be called "OpenSSL"
|
||||
* nor may "OpenSSL" appear in their names without prior written
|
||||
* permission of the OpenSSL Project.
|
||||
*
|
||||
* 6. Redistributions of any form whatsoever must retain the following
|
||||
* acknowledgment:
|
||||
* "This product includes software developed by the OpenSSL Project
|
||||
* for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
|
||||
* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
|
||||
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
||||
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
|
||||
* OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
* ====================================================================
|
||||
*
|
||||
* This product includes cryptographic software written by Eric Young
|
||||
* (eay@cryptsoft.com). This product includes software written by Tim
|
||||
* Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <openssl/bn.h>
|
||||
|
||||
/* X9.31 routines for prime derivation */
|
||||
|
||||
/*
|
||||
* X9.31 prime derivation. This is used to generate the primes pi (p1, p2,
|
||||
* q1, q2) from a parameter Xpi by checking successive odd integers.
|
||||
*/
|
||||
|
||||
static int bn_x931_derive_pi(BIGNUM *pi, const BIGNUM *Xpi, BN_CTX *ctx,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
int i = 0;
|
||||
if (!BN_copy(pi, Xpi))
|
||||
return 0;
|
||||
if (!BN_is_odd(pi) && !BN_add_word(pi, 1))
|
||||
return 0;
|
||||
for (;;) {
|
||||
i++;
|
||||
BN_GENCB_call(cb, 0, i);
|
||||
/* NB 27 MR is specificed in X9.31 */
|
||||
if (BN_is_prime_fasttest_ex(pi, 27, ctx, 1, cb))
|
||||
break;
|
||||
if (!BN_add_word(pi, 2))
|
||||
return 0;
|
||||
}
|
||||
BN_GENCB_call(cb, 2, i);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This is the main X9.31 prime derivation function. From parameters Xp1, Xp2
|
||||
* and Xp derive the prime p. If the parameters p1 or p2 are not NULL they
|
||||
* will be returned too: this is needed for testing.
|
||||
*/
|
||||
|
||||
int BN_X931_derive_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
|
||||
const BIGNUM *Xp, const BIGNUM *Xp1,
|
||||
const BIGNUM *Xp2, const BIGNUM *e, BN_CTX *ctx,
|
||||
BN_GENCB *cb)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
BIGNUM *t, *p1p2, *pm1;
|
||||
|
||||
/* Only even e supported */
|
||||
if (!BN_is_odd(e))
|
||||
return 0;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if (!p1)
|
||||
p1 = BN_CTX_get(ctx);
|
||||
|
||||
if (!p2)
|
||||
p2 = BN_CTX_get(ctx);
|
||||
|
||||
t = BN_CTX_get(ctx);
|
||||
|
||||
p1p2 = BN_CTX_get(ctx);
|
||||
|
||||
pm1 = BN_CTX_get(ctx);
|
||||
|
||||
if (!bn_x931_derive_pi(p1, Xp1, ctx, cb))
|
||||
goto err;
|
||||
|
||||
if (!bn_x931_derive_pi(p2, Xp2, ctx, cb))
|
||||
goto err;
|
||||
|
||||
if (!BN_mul(p1p2, p1, p2, ctx))
|
||||
goto err;
|
||||
|
||||
/* First set p to value of Rp */
|
||||
|
||||
if (!BN_mod_inverse(p, p2, p1, ctx))
|
||||
goto err;
|
||||
|
||||
if (!BN_mul(p, p, p2, ctx))
|
||||
goto err;
|
||||
|
||||
if (!BN_mod_inverse(t, p1, p2, ctx))
|
||||
goto err;
|
||||
|
||||
if (!BN_mul(t, t, p1, ctx))
|
||||
goto err;
|
||||
|
||||
if (!BN_sub(p, p, t))
|
||||
goto err;
|
||||
|
||||
if (p->neg && !BN_add(p, p, p1p2))
|
||||
goto err;
|
||||
|
||||
/* p now equals Rp */
|
||||
|
||||
if (!BN_mod_sub(p, p, Xp, p1p2, ctx))
|
||||
goto err;
|
||||
|
||||
if (!BN_add(p, p, Xp))
|
||||
goto err;
|
||||
|
||||
/* p now equals Yp0 */
|
||||
|
||||
for (;;) {
|
||||
int i = 1;
|
||||
BN_GENCB_call(cb, 0, i++);
|
||||
if (!BN_copy(pm1, p))
|
||||
goto err;
|
||||
if (!BN_sub_word(pm1, 1))
|
||||
goto err;
|
||||
if (!BN_gcd(t, pm1, e, ctx))
|
||||
goto err;
|
||||
if (BN_is_one(t)
|
||||
/*
|
||||
* X9.31 specifies 8 MR and 1 Lucas test or any prime test
|
||||
* offering similar or better guarantees 50 MR is considerably
|
||||
* better.
|
||||
*/
|
||||
&& BN_is_prime_fasttest_ex(p, 50, ctx, 1, cb))
|
||||
break;
|
||||
if (!BN_add(p, p, p1p2))
|
||||
goto err;
|
||||
}
|
||||
|
||||
BN_GENCB_call(cb, 3, 0);
|
||||
|
||||
ret = 1;
|
||||
|
||||
err:
|
||||
|
||||
BN_CTX_end(ctx);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate pair of paramters Xp, Xq for X9.31 prime generation. Note: nbits
|
||||
* paramter is sum of number of bits in both.
|
||||
*/
|
||||
|
||||
int BN_X931_generate_Xpq(BIGNUM *Xp, BIGNUM *Xq, int nbits, BN_CTX *ctx)
|
||||
{
|
||||
BIGNUM *t;
|
||||
int i;
|
||||
/*
|
||||
* Number of bits for each prime is of the form 512+128s for s = 0, 1,
|
||||
* ...
|
||||
*/
|
||||
if ((nbits < 1024) || (nbits & 0xff))
|
||||
return 0;
|
||||
nbits >>= 1;
|
||||
/*
|
||||
* The random value Xp must be between sqrt(2) * 2^(nbits-1) and 2^nbits
|
||||
* - 1. By setting the top two bits we ensure that the lower bound is
|
||||
* exceeded.
|
||||
*/
|
||||
if (!BN_rand(Xp, nbits, 1, 0))
|
||||
return 0;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
t = BN_CTX_get(ctx);
|
||||
|
||||
for (i = 0; i < 1000; i++) {
|
||||
if (!BN_rand(Xq, nbits, 1, 0))
|
||||
return 0;
|
||||
/* Check that |Xp - Xq| > 2^(nbits - 100) */
|
||||
BN_sub(t, Xp, Xq);
|
||||
if (BN_num_bits(t) > (nbits - 100))
|
||||
break;
|
||||
}
|
||||
|
||||
BN_CTX_end(ctx);
|
||||
|
||||
if (i < 1000)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Generate primes using X9.31 algorithm. Of the values p, p1, p2, Xp1 and
|
||||
* Xp2 only 'p' needs to be non-NULL. If any of the others are not NULL the
|
||||
* relevant parameter will be stored in it. Due to the fact that |Xp - Xq| >
|
||||
* 2^(nbits - 100) must be satisfied Xp and Xq are generated using the
|
||||
* previous function and supplied as input.
|
||||
*/
|
||||
|
||||
int BN_X931_generate_prime_ex(BIGNUM *p, BIGNUM *p1, BIGNUM *p2,
|
||||
BIGNUM *Xp1, BIGNUM *Xp2,
|
||||
const BIGNUM *Xp,
|
||||
const BIGNUM *e, BN_CTX *ctx, BN_GENCB *cb)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
if (!Xp1)
|
||||
Xp1 = BN_CTX_get(ctx);
|
||||
if (!Xp2)
|
||||
Xp2 = BN_CTX_get(ctx);
|
||||
|
||||
if (!BN_rand(Xp1, 101, 0, 0))
|
||||
goto error;
|
||||
if (!BN_rand(Xp2, 101, 0, 0))
|
||||
goto error;
|
||||
if (!BN_X931_derive_prime_ex(p, p1, p2, Xp, Xp1, Xp2, e, ctx, cb))
|
||||
goto error;
|
||||
|
||||
ret = 1;
|
||||
|
||||
error:
|
||||
BN_CTX_end(ctx);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,257 @@
|
||||
/* crypto/bn/exptest.c */
|
||||
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
|
||||
* All rights reserved.
|
||||
*
|
||||
* This package is an SSL implementation written
|
||||
* by Eric Young (eay@cryptsoft.com).
|
||||
* The implementation was written so as to conform with Netscapes SSL.
|
||||
*
|
||||
* This library is free for commercial and non-commercial use as long as
|
||||
* the following conditions are aheared to. The following conditions
|
||||
* apply to all code found in this distribution, be it the RC4, RSA,
|
||||
* lhash, DES, etc., code; not just the SSL code. The SSL documentation
|
||||
* included with this distribution is covered by the same copyright terms
|
||||
* except that the holder is Tim Hudson (tjh@cryptsoft.com).
|
||||
*
|
||||
* Copyright remains Eric Young's, and as such any Copyright notices in
|
||||
* the code are not to be removed.
|
||||
* If this package is used in a product, Eric Young should be given attribution
|
||||
* as the author of the parts of the library used.
|
||||
* This can be in the form of a textual message at program startup or
|
||||
* in documentation (online or textual) provided with the package.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. All advertising materials mentioning features or use of this software
|
||||
* must display the following acknowledgement:
|
||||
* "This product includes cryptographic software written by
|
||||
* Eric Young (eay@cryptsoft.com)"
|
||||
* The word 'cryptographic' can be left out if the rouines from the library
|
||||
* being used are not cryptographic related :-).
|
||||
* 4. If you include any Windows specific code (or a derivative thereof) from
|
||||
* the apps directory (application code) you must include an acknowledgement:
|
||||
* "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* The licence and distribution terms for any publically available version or
|
||||
* derivative of this code cannot be changed. i.e. this code cannot simply be
|
||||
* copied and put under another distribution licence
|
||||
* [including the GNU Public Licence.]
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../e_os.h"
|
||||
|
||||
#include <openssl/bio.h>
|
||||
#include <openssl/bn.h>
|
||||
#include <openssl/rand.h>
|
||||
#include <openssl/err.h>
|
||||
|
||||
#define NUM_BITS (BN_BITS*2)
|
||||
|
||||
static const char rnd_seed[] =
|
||||
"string to make the random number generator think it has entropy";
|
||||
|
||||
/*
|
||||
* Disabled for FIPS capable builds because they use the FIPS BIGNUM library
|
||||
* which will fail this test.
|
||||
*/
|
||||
#ifndef OPENSSL_FIPS
|
||||
/*
|
||||
* test_exp_mod_zero tests that x**0 mod 1 == 0. It returns zero on success.
|
||||
*/
|
||||
static int test_exp_mod_zero()
|
||||
{
|
||||
BIGNUM a, p, m;
|
||||
BIGNUM r;
|
||||
BN_CTX *ctx = BN_CTX_new();
|
||||
int ret = 1;
|
||||
|
||||
BN_init(&m);
|
||||
BN_one(&m);
|
||||
|
||||
BN_init(&a);
|
||||
BN_one(&a);
|
||||
|
||||
BN_init(&p);
|
||||
BN_zero(&p);
|
||||
|
||||
BN_init(&r);
|
||||
BN_mod_exp(&r, &a, &p, &m, ctx);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
if (BN_is_zero(&r))
|
||||
ret = 0;
|
||||
else {
|
||||
printf("1**0 mod 1 = ");
|
||||
BN_print_fp(stdout, &r);
|
||||
printf(", should be 0\n");
|
||||
}
|
||||
|
||||
BN_free(&r);
|
||||
BN_free(&a);
|
||||
BN_free(&p);
|
||||
BN_free(&m);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif
|
||||
|
||||
int exptest(int argc, char *argv[]);
|
||||
|
||||
int exptest(int argc, char *argv[])
|
||||
{
|
||||
BN_CTX *ctx;
|
||||
BIO *out=NULL;
|
||||
int i,ret;
|
||||
unsigned char c;
|
||||
BIGNUM *r_mont,*r_mont_const,*r_recp,*r_simple,*a,*b,*m;
|
||||
|
||||
RAND_seed(rnd_seed, sizeof rnd_seed); /* or BN_rand may fail, and we don't
|
||||
* even check its return value
|
||||
* (which we should) */
|
||||
|
||||
ERR_load_BN_strings();
|
||||
|
||||
ctx=BN_CTX_new();
|
||||
if (ctx == NULL) EXIT(1);
|
||||
r_mont=BN_new();
|
||||
r_mont_const=BN_new();
|
||||
r_recp=BN_new();
|
||||
r_simple=BN_new();
|
||||
a=BN_new();
|
||||
b=BN_new();
|
||||
m=BN_new();
|
||||
if ( (r_mont == NULL) || (r_recp == NULL) ||
|
||||
(a == NULL) || (b == NULL))
|
||||
goto err;
|
||||
|
||||
out=BIO_new(BIO_s_file());
|
||||
|
||||
if (out == NULL) EXIT(1);
|
||||
BIO_set_fp(out,stdout,BIO_NOCLOSE);
|
||||
|
||||
for (i=0; i<200; i++)
|
||||
{
|
||||
RAND_bytes(&c,1);
|
||||
c=(c%BN_BITS)-BN_BITS2;
|
||||
BN_rand(a,NUM_BITS+c,0,0);
|
||||
|
||||
RAND_bytes(&c,1);
|
||||
c=(c%BN_BITS)-BN_BITS2;
|
||||
BN_rand(b,NUM_BITS+c,0,0);
|
||||
|
||||
RAND_bytes(&c,1);
|
||||
c=(c%BN_BITS)-BN_BITS2;
|
||||
BN_rand(m,NUM_BITS+c,0,1);
|
||||
|
||||
BN_mod(a,a,m,ctx);
|
||||
BN_mod(b,b,m,ctx);
|
||||
|
||||
ret=BN_mod_exp_mont(r_mont,a,b,m,ctx,NULL);
|
||||
if (ret <= 0)
|
||||
{
|
||||
printf("BN_mod_exp_mont() problems\n");
|
||||
ERR_print_errors(out);
|
||||
EXIT(1);
|
||||
}
|
||||
|
||||
ret=BN_mod_exp_recp(r_recp,a,b,m,ctx);
|
||||
if (ret <= 0)
|
||||
{
|
||||
printf("BN_mod_exp_recp() problems\n");
|
||||
ERR_print_errors(out);
|
||||
EXIT(1);
|
||||
}
|
||||
|
||||
ret=BN_mod_exp_simple(r_simple,a,b,m,ctx);
|
||||
if (ret <= 0)
|
||||
{
|
||||
printf("BN_mod_exp_simple() problems\n");
|
||||
ERR_print_errors(out);
|
||||
EXIT(1);
|
||||
}
|
||||
|
||||
ret=BN_mod_exp_mont_consttime(r_mont_const,a,b,m,ctx,NULL);
|
||||
if (ret <= 0)
|
||||
{
|
||||
printf("BN_mod_exp_mont_consttime() problems\n");
|
||||
ERR_print_errors(out);
|
||||
EXIT(1);
|
||||
}
|
||||
|
||||
if (BN_cmp(r_simple, r_mont) == 0
|
||||
&& BN_cmp(r_simple,r_recp) == 0
|
||||
&& BN_cmp(r_simple,r_mont_const) == 0)
|
||||
{
|
||||
printf(".");
|
||||
fflush(stdout);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (BN_cmp(r_simple,r_mont) != 0)
|
||||
printf("\nsimple and mont results differ\n");
|
||||
if (BN_cmp(r_simple,r_mont) != 0)
|
||||
printf("\nsimple and mont const time results differ\n");
|
||||
if (BN_cmp(r_simple,r_recp) != 0)
|
||||
printf("\nsimple and recp results differ\n");
|
||||
|
||||
printf("a (%3d) = ",BN_num_bits(a)); BN_print(out,a);
|
||||
printf("\nb (%3d) = ",BN_num_bits(b)); BN_print(out,b);
|
||||
printf("\nm (%3d) = ",BN_num_bits(m)); BN_print(out,m);
|
||||
printf("\nsimple ="); BN_print(out,r_simple);
|
||||
printf("\nrecp ="); BN_print(out,r_recp);
|
||||
printf("\nmont ="); BN_print(out,r_mont);
|
||||
printf("\nmont_ct ="); BN_print(out,r_mont_const);
|
||||
printf("\n");
|
||||
EXIT(1);
|
||||
}
|
||||
}
|
||||
BN_free(r_mont);
|
||||
BN_free(r_mont_const);
|
||||
BN_free(r_recp);
|
||||
BN_free(r_simple);
|
||||
BN_free(a);
|
||||
BN_free(b);
|
||||
BN_free(m);
|
||||
BN_CTX_free(ctx);
|
||||
ERR_remove_state(0);
|
||||
/* CRYPTO_mem_leaks(out); */
|
||||
BIO_free(out);
|
||||
printf("\n");
|
||||
#ifndef OPENSSL_FIPS
|
||||
if (test_exp_mod_zero() != 0)
|
||||
goto err;
|
||||
#endif
|
||||
printf("done\n");
|
||||
|
||||
EXIT(0);
|
||||
err:
|
||||
ERR_load_crypto_strings();
|
||||
ERR_print_errors(out);
|
||||
#ifdef OPENSSL_SYS_NETWARE
|
||||
printf("ERROR\n");
|
||||
#endif
|
||||
EXIT(1);
|
||||
return (1);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,628 @@
|
||||
#ifdef __SUNPRO_C
|
||||
# include "../bn_asm.c" /* kind of dirty hack for Sun Studio */
|
||||
#else
|
||||
/*-
|
||||
* x86_64 BIGNUM accelerator version 0.1, December 2002.
|
||||
*
|
||||
* Implemented by Andy Polyakov <appro@fy.chalmers.se> for the OpenSSL
|
||||
* project.
|
||||
*
|
||||
* Rights for redistribution and usage in source and binary forms are
|
||||
* granted according to the OpenSSL license. Warranty of any kind is
|
||||
* disclaimed.
|
||||
*
|
||||
* Q. Version 0.1? It doesn't sound like Andy, he used to assign real
|
||||
* versions, like 1.0...
|
||||
* A. Well, that's because this code is basically a quick-n-dirty
|
||||
* proof-of-concept hack. As you can see it's implemented with
|
||||
* inline assembler, which means that you're bound to GCC and that
|
||||
* there might be enough room for further improvement.
|
||||
*
|
||||
* Q. Why inline assembler?
|
||||
* A. x86_64 features own ABI which I'm not familiar with. This is
|
||||
* why I decided to let the compiler take care of subroutine
|
||||
* prologue/epilogue as well as register allocation. For reference.
|
||||
* Win64 implements different ABI for AMD64, different from Linux.
|
||||
*
|
||||
* Q. How much faster does it get?
|
||||
* A. 'apps/openssl speed rsa dsa' output with no-asm:
|
||||
*
|
||||
* sign verify sign/s verify/s
|
||||
* rsa 512 bits 0.0006s 0.0001s 1683.8 18456.2
|
||||
* rsa 1024 bits 0.0028s 0.0002s 356.0 6407.0
|
||||
* rsa 2048 bits 0.0172s 0.0005s 58.0 1957.8
|
||||
* rsa 4096 bits 0.1155s 0.0018s 8.7 555.6
|
||||
* sign verify sign/s verify/s
|
||||
* dsa 512 bits 0.0005s 0.0006s 2100.8 1768.3
|
||||
* dsa 1024 bits 0.0014s 0.0018s 692.3 559.2
|
||||
* dsa 2048 bits 0.0049s 0.0061s 204.7 165.0
|
||||
*
|
||||
* 'apps/openssl speed rsa dsa' output with this module:
|
||||
*
|
||||
* sign verify sign/s verify/s
|
||||
* rsa 512 bits 0.0004s 0.0000s 2767.1 33297.9
|
||||
* rsa 1024 bits 0.0012s 0.0001s 867.4 14674.7
|
||||
* rsa 2048 bits 0.0061s 0.0002s 164.0 5270.0
|
||||
* rsa 4096 bits 0.0384s 0.0006s 26.1 1650.8
|
||||
* sign verify sign/s verify/s
|
||||
* dsa 512 bits 0.0002s 0.0003s 4442.2 3786.3
|
||||
* dsa 1024 bits 0.0005s 0.0007s 1835.1 1497.4
|
||||
* dsa 2048 bits 0.0016s 0.0020s 620.4 504.6
|
||||
*
|
||||
* For the reference. IA-32 assembler implementation performs
|
||||
* very much like 64-bit code compiled with no-asm on the same
|
||||
* machine.
|
||||
*/
|
||||
|
||||
# define BN_ULONG unsigned long
|
||||
|
||||
/*
|
||||
* "m"(a), "+m"(r) is the way to favor DirectPath µ-code;
|
||||
* "g"(0) let the compiler to decide where does it
|
||||
* want to keep the value of zero;
|
||||
*/
|
||||
#define mul_add(r,a,word,carry) do { \
|
||||
register BN_ULONG high,low; \
|
||||
__asm__ ("mulq %3" \
|
||||
: "=a"(low),"=d"(high) \
|
||||
: "a"(word),"m"(a) \
|
||||
: "cc"); \
|
||||
__asm__ ("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(carry),"+d"(high)\
|
||||
: "a"(low),"g"(0) \
|
||||
: "cc"); \
|
||||
__asm__ ("addq %2,%0; adcq %3,%1" \
|
||||
: "+m"(r),"+d"(high) \
|
||||
: "r"(carry),"g"(0) \
|
||||
: "cc"); \
|
||||
carry=high; \
|
||||
} while (0)
|
||||
|
||||
#define mul(r,a,word,carry) do { \
|
||||
register BN_ULONG high,low; \
|
||||
__asm__ ("mulq %3" \
|
||||
: "=a"(low),"=d"(high) \
|
||||
: "a"(word),"g"(a) \
|
||||
: "cc"); \
|
||||
__asm__ ("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(carry),"+d"(high)\
|
||||
: "a"(low),"g"(0) \
|
||||
: "cc"); \
|
||||
(r)=carry, carry=high; \
|
||||
} while (0)
|
||||
|
||||
#define sqr(r0,r1,a) \
|
||||
__asm__ ("mulq %2" \
|
||||
: "=a"(r0),"=d"(r1) \
|
||||
: "a"(a) \
|
||||
: "cc");
|
||||
|
||||
BN_ULONG bn_mul_add_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
|
||||
{
|
||||
BN_ULONG c1=0;
|
||||
|
||||
if (num <= 0) return(c1);
|
||||
|
||||
while (num&~3)
|
||||
{
|
||||
mul_add(rp[0],ap[0],w,c1);
|
||||
mul_add(rp[1],ap[1],w,c1);
|
||||
mul_add(rp[2],ap[2],w,c1);
|
||||
mul_add(rp[3],ap[3],w,c1);
|
||||
ap+=4; rp+=4; num-=4;
|
||||
}
|
||||
if (num)
|
||||
{
|
||||
mul_add(rp[0],ap[0],w,c1); if (--num==0) return c1;
|
||||
mul_add(rp[1],ap[1],w,c1); if (--num==0) return c1;
|
||||
mul_add(rp[2],ap[2],w,c1); return c1;
|
||||
}
|
||||
|
||||
return(c1);
|
||||
}
|
||||
|
||||
BN_ULONG bn_mul_words(BN_ULONG *rp, BN_ULONG *ap, int num, BN_ULONG w)
|
||||
{
|
||||
BN_ULONG c1=0;
|
||||
|
||||
if (num <= 0)
|
||||
return (c1);
|
||||
|
||||
while (num & ~3) {
|
||||
mul(rp[0], ap[0], w, c1);
|
||||
mul(rp[1], ap[1], w, c1);
|
||||
mul(rp[2], ap[2], w, c1);
|
||||
mul(rp[3], ap[3], w, c1);
|
||||
ap += 4;
|
||||
rp += 4;
|
||||
num -= 4;
|
||||
}
|
||||
if (num) {
|
||||
mul(rp[0], ap[0], w, c1);
|
||||
if (--num == 0)
|
||||
return c1;
|
||||
mul(rp[1], ap[1], w, c1);
|
||||
if (--num == 0)
|
||||
return c1;
|
||||
mul(rp[2], ap[2], w, c1);
|
||||
}
|
||||
return (c1);
|
||||
}
|
||||
|
||||
void bn_sqr_words(BN_ULONG *r, BN_ULONG *a, int n)
|
||||
{
|
||||
if (n <= 0)
|
||||
return;
|
||||
|
||||
while (n & ~3) {
|
||||
sqr(r[0], r[1], a[0]);
|
||||
sqr(r[2], r[3], a[1]);
|
||||
sqr(r[4], r[5], a[2]);
|
||||
sqr(r[6], r[7], a[3]);
|
||||
a += 4;
|
||||
r += 8;
|
||||
n -= 4;
|
||||
}
|
||||
if (n) {
|
||||
sqr(r[0], r[1], a[0]);
|
||||
if (--n == 0)
|
||||
return;
|
||||
sqr(r[2], r[3], a[1]);
|
||||
if (--n == 0)
|
||||
return;
|
||||
sqr(r[4], r[5], a[2]);
|
||||
}
|
||||
}
|
||||
|
||||
BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d)
|
||||
{
|
||||
BN_ULONG ret, waste;
|
||||
|
||||
__asm__ ("divq %4"
|
||||
: "=a"(ret),"=d"(waste)
|
||||
: "a"(l),"d"(h),"g"(d)
|
||||
: "cc");
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
BN_ULONG bn_add_words (BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int n)
|
||||
{ BN_ULONG ret=0,i=0;
|
||||
|
||||
if (n <= 0) return 0;
|
||||
|
||||
__asm__ (
|
||||
" subq %2,%2 \n"
|
||||
".align 16 \n"
|
||||
"1: movq (%4,%2,8),%0 \n"
|
||||
" adcq (%5,%2,8),%0 \n"
|
||||
" movq %0,(%3,%2,8) \n"
|
||||
" leaq 1(%2),%2 \n"
|
||||
" loop 1b \n"
|
||||
" sbbq %0,%0 \n"
|
||||
: "=&a"(ret),"+c"(n),"=&r"(i)
|
||||
: "r"(rp),"r"(ap),"r"(bp)
|
||||
: "cc", "memory"
|
||||
);
|
||||
|
||||
return ret&1;
|
||||
}
|
||||
|
||||
#ifndef SIMICS
|
||||
BN_ULONG bn_sub_words (BN_ULONG *rp, BN_ULONG *ap, BN_ULONG *bp,int n)
|
||||
{ BN_ULONG ret=0,i=0;
|
||||
|
||||
if (n <= 0) return 0;
|
||||
|
||||
__asm__ (
|
||||
" subq %2,%2 \n"
|
||||
".align 16 \n"
|
||||
"1: movq (%4,%2,8),%0 \n"
|
||||
" sbbq (%5,%2,8),%0 \n"
|
||||
" movq %0,(%3,%2,8) \n"
|
||||
" leaq 1(%2),%2 \n"
|
||||
" loop 1b \n"
|
||||
" sbbq %0,%0 \n"
|
||||
: "=&a"(ret),"+c"(n),"=&r"(i)
|
||||
: "r"(rp),"r"(ap),"r"(bp)
|
||||
: "cc", "memory"
|
||||
);
|
||||
|
||||
return ret & 1;
|
||||
}
|
||||
# else
|
||||
/* Simics 1.4<7 has buggy sbbq:-( */
|
||||
# define BN_MASK2 0xffffffffffffffffL
|
||||
BN_ULONG bn_sub_words(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b, int n)
|
||||
{
|
||||
BN_ULONG t1, t2;
|
||||
int c = 0;
|
||||
|
||||
if (n <= 0)
|
||||
return ((BN_ULONG)0);
|
||||
|
||||
for (;;) {
|
||||
t1 = a[0];
|
||||
t2 = b[0];
|
||||
r[0] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2)
|
||||
c = (t1 < t2);
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
t1 = a[1];
|
||||
t2 = b[1];
|
||||
r[1] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2)
|
||||
c = (t1 < t2);
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
t1 = a[2];
|
||||
t2 = b[2];
|
||||
r[2] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2)
|
||||
c = (t1 < t2);
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
t1 = a[3];
|
||||
t2 = b[3];
|
||||
r[3] = (t1 - t2 - c) & BN_MASK2;
|
||||
if (t1 != t2)
|
||||
c = (t1 < t2);
|
||||
if (--n <= 0)
|
||||
break;
|
||||
|
||||
a += 4;
|
||||
b += 4;
|
||||
r += 4;
|
||||
}
|
||||
return (c);
|
||||
}
|
||||
# endif
|
||||
|
||||
/* mul_add_c(a,b,c0,c1,c2) -- c+=a*b for three word number c=(c2,c1,c0) */
|
||||
/* mul_add_c2(a,b,c0,c1,c2) -- c+=2*a*b for three word number c=(c2,c1,c0) */
|
||||
/* sqr_add_c(a,i,c0,c1,c2) -- c+=a[i]^2 for three word number c=(c2,c1,c0) */
|
||||
/*
|
||||
* sqr_add_c2(a,i,c0,c1,c2) -- c+=2*a[i]*a[j] for three word number
|
||||
* c=(c2,c1,c0)
|
||||
*/
|
||||
|
||||
/*
|
||||
* Keep in mind that carrying into high part of multiplication result
|
||||
* can not overflow, because it cannot be all-ones.
|
||||
*/
|
||||
# if 0
|
||||
/* original macros are kept for reference purposes */
|
||||
#define mul_add_c(a,b,c0,c1,c2) { \
|
||||
BN_ULONG ta=(a),tb=(b); \
|
||||
t1 = ta * tb; \
|
||||
t2 = BN_UMULT_HIGH(ta,tb); \
|
||||
c0 += t1; t2 += (c0<t1)?1:0; \
|
||||
c1 += t2; c2 += (c1<t2)?1:0; \
|
||||
}
|
||||
|
||||
#define mul_add_c2(a,b,c0,c1,c2) { \
|
||||
BN_ULONG ta=(a),tb=(b),t0; \
|
||||
t1 = BN_UMULT_HIGH(ta,tb); \
|
||||
t0 = ta * tb; \
|
||||
c0 += t0; t2 = t1+((c0<t0)?1:0);\
|
||||
c1 += t2; c2 += (c1<t2)?1:0; \
|
||||
c0 += t0; t1 += (c0<t0)?1:0; \
|
||||
c1 += t1; c2 += (c1<t1)?1:0; \
|
||||
}
|
||||
#else
|
||||
#define mul_add_c(a,b,c0,c1,c2) do { \
|
||||
__asm__ ("mulq %3" \
|
||||
: "=a"(t1),"=d"(t2) \
|
||||
: "a"(a),"m"(b) \
|
||||
: "cc"); \
|
||||
__asm__ ("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c0),"+d"(t2) \
|
||||
: "a"(t1),"g"(0) \
|
||||
: "cc"); \
|
||||
__asm__ ("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c1),"+r"(c2) \
|
||||
: "d"(t2),"g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
|
||||
#define sqr_add_c(a,i,c0,c1,c2) do { \
|
||||
__asm__ ("mulq %2" \
|
||||
: "=a"(t1),"=d"(t2) \
|
||||
: "a"(a[i]) \
|
||||
: "cc"); \
|
||||
__asm__ ("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c0),"+d"(t2) \
|
||||
: "a"(t1),"g"(0) \
|
||||
: "cc"); \
|
||||
__asm__ ("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c1),"+r"(c2) \
|
||||
: "d"(t2),"g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
|
||||
#define mul_add_c2(a,b,c0,c1,c2) do { \
|
||||
__asm__ ("mulq %3" \
|
||||
: "=a"(t1),"=d"(t2) \
|
||||
: "a"(a),"m"(b) \
|
||||
: "cc"); \
|
||||
__asm__ ("addq %0,%0; adcq %2,%1" \
|
||||
: "+d"(t2),"+r"(c2) \
|
||||
: "g"(0) \
|
||||
: "cc"); \
|
||||
__asm__ ("addq %0,%0; adcq %2,%1" \
|
||||
: "+a"(t1),"+d"(t2) \
|
||||
: "g"(0) \
|
||||
: "cc"); \
|
||||
__asm__ ("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c0),"+d"(t2) \
|
||||
: "a"(t1),"g"(0) \
|
||||
: "cc"); \
|
||||
__asm__ ("addq %2,%0; adcq %3,%1" \
|
||||
: "+r"(c1),"+r"(c2) \
|
||||
: "d"(t2),"g"(0) \
|
||||
: "cc"); \
|
||||
} while (0)
|
||||
#endif
|
||||
|
||||
# define sqr_add_c2(a,i,j,c0,c1,c2) \
|
||||
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
|
||||
|
||||
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[0], c1, c2, c3);
|
||||
r[0] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[0], b[1], c2, c3, c1);
|
||||
mul_add_c(a[1], b[0], c2, c3, c1);
|
||||
r[1] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[2], b[0], c3, c1, c2);
|
||||
mul_add_c(a[1], b[1], c3, c1, c2);
|
||||
mul_add_c(a[0], b[2], c3, c1, c2);
|
||||
r[2] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[3], c1, c2, c3);
|
||||
mul_add_c(a[1], b[2], c1, c2, c3);
|
||||
mul_add_c(a[2], b[1], c1, c2, c3);
|
||||
mul_add_c(a[3], b[0], c1, c2, c3);
|
||||
r[3] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[4], b[0], c2, c3, c1);
|
||||
mul_add_c(a[3], b[1], c2, c3, c1);
|
||||
mul_add_c(a[2], b[2], c2, c3, c1);
|
||||
mul_add_c(a[1], b[3], c2, c3, c1);
|
||||
mul_add_c(a[0], b[4], c2, c3, c1);
|
||||
r[4] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[0], b[5], c3, c1, c2);
|
||||
mul_add_c(a[1], b[4], c3, c1, c2);
|
||||
mul_add_c(a[2], b[3], c3, c1, c2);
|
||||
mul_add_c(a[3], b[2], c3, c1, c2);
|
||||
mul_add_c(a[4], b[1], c3, c1, c2);
|
||||
mul_add_c(a[5], b[0], c3, c1, c2);
|
||||
r[5] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[6], b[0], c1, c2, c3);
|
||||
mul_add_c(a[5], b[1], c1, c2, c3);
|
||||
mul_add_c(a[4], b[2], c1, c2, c3);
|
||||
mul_add_c(a[3], b[3], c1, c2, c3);
|
||||
mul_add_c(a[2], b[4], c1, c2, c3);
|
||||
mul_add_c(a[1], b[5], c1, c2, c3);
|
||||
mul_add_c(a[0], b[6], c1, c2, c3);
|
||||
r[6] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[0], b[7], c2, c3, c1);
|
||||
mul_add_c(a[1], b[6], c2, c3, c1);
|
||||
mul_add_c(a[2], b[5], c2, c3, c1);
|
||||
mul_add_c(a[3], b[4], c2, c3, c1);
|
||||
mul_add_c(a[4], b[3], c2, c3, c1);
|
||||
mul_add_c(a[5], b[2], c2, c3, c1);
|
||||
mul_add_c(a[6], b[1], c2, c3, c1);
|
||||
mul_add_c(a[7], b[0], c2, c3, c1);
|
||||
r[7] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[7], b[1], c3, c1, c2);
|
||||
mul_add_c(a[6], b[2], c3, c1, c2);
|
||||
mul_add_c(a[5], b[3], c3, c1, c2);
|
||||
mul_add_c(a[4], b[4], c3, c1, c2);
|
||||
mul_add_c(a[3], b[5], c3, c1, c2);
|
||||
mul_add_c(a[2], b[6], c3, c1, c2);
|
||||
mul_add_c(a[1], b[7], c3, c1, c2);
|
||||
r[8] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[2], b[7], c1, c2, c3);
|
||||
mul_add_c(a[3], b[6], c1, c2, c3);
|
||||
mul_add_c(a[4], b[5], c1, c2, c3);
|
||||
mul_add_c(a[5], b[4], c1, c2, c3);
|
||||
mul_add_c(a[6], b[3], c1, c2, c3);
|
||||
mul_add_c(a[7], b[2], c1, c2, c3);
|
||||
r[9] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[7], b[3], c2, c3, c1);
|
||||
mul_add_c(a[6], b[4], c2, c3, c1);
|
||||
mul_add_c(a[5], b[5], c2, c3, c1);
|
||||
mul_add_c(a[4], b[6], c2, c3, c1);
|
||||
mul_add_c(a[3], b[7], c2, c3, c1);
|
||||
r[10] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[4], b[7], c3, c1, c2);
|
||||
mul_add_c(a[5], b[6], c3, c1, c2);
|
||||
mul_add_c(a[6], b[5], c3, c1, c2);
|
||||
mul_add_c(a[7], b[4], c3, c1, c2);
|
||||
r[11] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[7], b[5], c1, c2, c3);
|
||||
mul_add_c(a[6], b[6], c1, c2, c3);
|
||||
mul_add_c(a[5], b[7], c1, c2, c3);
|
||||
r[12] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[6], b[7], c2, c3, c1);
|
||||
mul_add_c(a[7], b[6], c2, c3, c1);
|
||||
r[13] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[7], b[7], c3, c1, c2);
|
||||
r[14] = c3;
|
||||
r[15] = c1;
|
||||
}
|
||||
|
||||
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
|
||||
{
|
||||
BN_ULONG t1, t2;
|
||||
BN_ULONG c1, c2, c3;
|
||||
|
||||
c1 = 0;
|
||||
c2 = 0;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[0], c1, c2, c3);
|
||||
r[0] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[0], b[1], c2, c3, c1);
|
||||
mul_add_c(a[1], b[0], c2, c3, c1);
|
||||
r[1] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[2], b[0], c3, c1, c2);
|
||||
mul_add_c(a[1], b[1], c3, c1, c2);
|
||||
mul_add_c(a[0], b[2], c3, c1, c2);
|
||||
r[2] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[0], b[3], c1, c2, c3);
|
||||
mul_add_c(a[1], b[2], c1, c2, c3);
|
||||
mul_add_c(a[2], b[1], c1, c2, c3);
|
||||
mul_add_c(a[3], b[0], c1, c2, c3);
|
||||
r[3] = c1;
|
||||
c1 = 0;
|
||||
mul_add_c(a[3], b[1], c2, c3, c1);
|
||||
mul_add_c(a[2], b[2], c2, c3, c1);
|
||||
mul_add_c(a[1], b[3], c2, c3, c1);
|
||||
r[4] = c2;
|
||||
c2 = 0;
|
||||
mul_add_c(a[2], b[3], c3, c1, c2);
|
||||
mul_add_c(a[3], b[2], c3, c1, c2);
|
||||
r[5] = c3;
|
||||
c3 = 0;
|
||||
mul_add_c(a[3], b[3], c1, c2, c3);
|
||||
r[6] = c1;
|
||||
r[7] = c2;
|
||||
}
|
||||
|
||||
void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a)
|
||||
{
|
||||
BN_ULONG t1,t2;
|
||||
BN_ULONG c1,c2,c3;
|
||||
|
||||
c1=0;
|
||||
c2=0;
|
||||
c3=0;
|
||||
sqr_add_c(a,0,c1,c2,c3);
|
||||
r[0]=c1;
|
||||
c1=0;
|
||||
sqr_add_c2(a,1,0,c2,c3,c1);
|
||||
r[1]=c2;
|
||||
c2=0;
|
||||
sqr_add_c(a,1,c3,c1,c2);
|
||||
sqr_add_c2(a,2,0,c3,c1,c2);
|
||||
r[2]=c3;
|
||||
c3=0;
|
||||
sqr_add_c2(a,3,0,c1,c2,c3);
|
||||
sqr_add_c2(a,2,1,c1,c2,c3);
|
||||
r[3]=c1;
|
||||
c1=0;
|
||||
sqr_add_c(a,2,c2,c3,c1);
|
||||
sqr_add_c2(a,3,1,c2,c3,c1);
|
||||
sqr_add_c2(a,4,0,c2,c3,c1);
|
||||
r[4]=c2;
|
||||
c2=0;
|
||||
sqr_add_c2(a,5,0,c3,c1,c2);
|
||||
sqr_add_c2(a,4,1,c3,c1,c2);
|
||||
sqr_add_c2(a,3,2,c3,c1,c2);
|
||||
r[5]=c3;
|
||||
c3=0;
|
||||
sqr_add_c(a,3,c1,c2,c3);
|
||||
sqr_add_c2(a,4,2,c1,c2,c3);
|
||||
sqr_add_c2(a,5,1,c1,c2,c3);
|
||||
sqr_add_c2(a,6,0,c1,c2,c3);
|
||||
r[6]=c1;
|
||||
c1=0;
|
||||
sqr_add_c2(a,7,0,c2,c3,c1);
|
||||
sqr_add_c2(a,6,1,c2,c3,c1);
|
||||
sqr_add_c2(a,5,2,c2,c3,c1);
|
||||
sqr_add_c2(a,4,3,c2,c3,c1);
|
||||
r[7]=c2;
|
||||
c2=0;
|
||||
sqr_add_c(a,4,c3,c1,c2);
|
||||
sqr_add_c2(a,5,3,c3,c1,c2);
|
||||
sqr_add_c2(a,6,2,c3,c1,c2);
|
||||
sqr_add_c2(a,7,1,c3,c1,c2);
|
||||
r[8]=c3;
|
||||
c3=0;
|
||||
sqr_add_c2(a,7,2,c1,c2,c3);
|
||||
sqr_add_c2(a,6,3,c1,c2,c3);
|
||||
sqr_add_c2(a,5,4,c1,c2,c3);
|
||||
r[9]=c1;
|
||||
c1=0;
|
||||
sqr_add_c(a,5,c2,c3,c1);
|
||||
sqr_add_c2(a,6,4,c2,c3,c1);
|
||||
sqr_add_c2(a,7,3,c2,c3,c1);
|
||||
r[10]=c2;
|
||||
c2=0;
|
||||
sqr_add_c2(a,7,4,c3,c1,c2);
|
||||
sqr_add_c2(a,6,5,c3,c1,c2);
|
||||
r[11]=c3;
|
||||
c3=0;
|
||||
sqr_add_c(a,6,c1,c2,c3);
|
||||
sqr_add_c2(a,7,5,c1,c2,c3);
|
||||
r[12]=c1;
|
||||
c1=0;
|
||||
sqr_add_c2(a,7,6,c2,c3,c1);
|
||||
r[13]=c2;
|
||||
c2=0;
|
||||
sqr_add_c(a,7,c3,c1,c2);
|
||||
r[14]=c3;
|
||||
r[15]=c1;
|
||||
}
|
||||
|
||||
void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a)
|
||||
{
|
||||
BN_ULONG t1,t2;
|
||||
BN_ULONG c1,c2,c3;
|
||||
|
||||
c1=0;
|
||||
c2=0;
|
||||
c3=0;
|
||||
sqr_add_c(a,0,c1,c2,c3);
|
||||
r[0]=c1;
|
||||
c1=0;
|
||||
sqr_add_c2(a,1,0,c2,c3,c1);
|
||||
r[1]=c2;
|
||||
c2=0;
|
||||
sqr_add_c(a,1,c3,c1,c2);
|
||||
sqr_add_c2(a,2,0,c3,c1,c2);
|
||||
r[2]=c3;
|
||||
c3=0;
|
||||
sqr_add_c2(a,3,0,c1,c2,c3);
|
||||
sqr_add_c2(a,2,1,c1,c2,c3);
|
||||
r[3]=c1;
|
||||
c1=0;
|
||||
sqr_add_c(a,2,c2,c3,c1);
|
||||
sqr_add_c2(a,3,1,c2,c3,c1);
|
||||
r[4]=c2;
|
||||
c2=0;
|
||||
sqr_add_c2(a,3,2,c3,c1,c2);
|
||||
r[5]=c3;
|
||||
c3=0;
|
||||
sqr_add_c(a,3,c1,c2,c3);
|
||||
r[6]=c1;
|
||||
r[7]=c2;
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
.text
|
||||
|
||||
.globl bn_mul_mont
|
||||
.type bn_mul_mont,@function
|
||||
.align 16
|
||||
bn_mul_mont:
|
||||
pushq %rbx
|
||||
pushq %rbp
|
||||
pushq %r12
|
||||
pushq %r13
|
||||
pushq %r14
|
||||
pushq %r15
|
||||
|
||||
movl %r9d,%r9d
|
||||
leaq 2(%r9),%rax
|
||||
movq %rsp,%rbp
|
||||
negq %rax
|
||||
leaq (%rsp,%rax,8),%rsp
|
||||
andq $-1024,%rsp
|
||||
|
||||
movq %rbp,8(%rsp,%r9,8)
|
||||
movq %rdx,%r12
|
||||
|
||||
movq (%r8),%r8
|
||||
|
||||
xorq %r14,%r14
|
||||
xorq %r15,%r15
|
||||
|
||||
movq (%r12),%rbx
|
||||
movq (%rsi),%rax
|
||||
mulq %rbx
|
||||
movq %rax,%r10
|
||||
movq %rdx,%r11
|
||||
|
||||
imulq %r8,%rax
|
||||
movq %rax,%rbp
|
||||
|
||||
mulq (%rcx)
|
||||
addq %r10,%rax
|
||||
adcq $0,%rdx
|
||||
movq %rdx,%r13
|
||||
|
||||
leaq 1(%r15),%r15
|
||||
.L1st:
|
||||
movq (%rsi,%r15,8),%rax
|
||||
mulq %rbx
|
||||
addq %r11,%rax
|
||||
adcq $0,%rdx
|
||||
movq %rax,%r10
|
||||
movq (%rcx,%r15,8),%rax
|
||||
movq %rdx,%r11
|
||||
|
||||
mulq %rbp
|
||||
addq %r13,%rax
|
||||
leaq 1(%r15),%r15
|
||||
adcq $0,%rdx
|
||||
addq %r10,%rax
|
||||
adcq $0,%rdx
|
||||
movq %rax,-16(%rsp,%r15,8)
|
||||
cmpq %r9,%r15
|
||||
movq %rdx,%r13
|
||||
jl .L1st
|
||||
|
||||
xorq %rdx,%rdx
|
||||
addq %r11,%r13
|
||||
adcq $0,%rdx
|
||||
movq %r13,-8(%rsp,%r9,8)
|
||||
movq %rdx,(%rsp,%r9,8)
|
||||
|
||||
leaq 1(%r14),%r14
|
||||
.align 4
|
||||
.Louter:
|
||||
xorq %r15,%r15
|
||||
|
||||
movq (%r12,%r14,8),%rbx
|
||||
movq (%rsi),%rax
|
||||
mulq %rbx
|
||||
addq (%rsp),%rax
|
||||
adcq $0,%rdx
|
||||
movq %rax,%r10
|
||||
movq %rdx,%r11
|
||||
|
||||
imulq %r8,%rax
|
||||
movq %rax,%rbp
|
||||
|
||||
mulq (%rcx,%r15,8)
|
||||
addq %r10,%rax
|
||||
movq 8(%rsp),%r10
|
||||
adcq $0,%rdx
|
||||
movq %rdx,%r13
|
||||
|
||||
leaq 1(%r15),%r15
|
||||
.align 4
|
||||
.Linner:
|
||||
movq (%rsi,%r15,8),%rax
|
||||
mulq %rbx
|
||||
addq %r11,%rax
|
||||
adcq $0,%rdx
|
||||
addq %rax,%r10
|
||||
movq (%rcx,%r15,8),%rax
|
||||
adcq $0,%rdx
|
||||
movq %rdx,%r11
|
||||
|
||||
mulq %rbp
|
||||
addq %r13,%rax
|
||||
leaq 1(%r15),%r15
|
||||
adcq $0,%rdx
|
||||
addq %r10,%rax
|
||||
adcq $0,%rdx
|
||||
movq (%rsp,%r15,8),%r10
|
||||
cmpq %r9,%r15
|
||||
movq %rax,-16(%rsp,%r15,8)
|
||||
movq %rdx,%r13
|
||||
jl .Linner
|
||||
|
||||
xorq %rdx,%rdx
|
||||
addq %r11,%r13
|
||||
adcq $0,%rdx
|
||||
addq %r10,%r13
|
||||
adcq $0,%rdx
|
||||
movq %r13,-8(%rsp,%r9,8)
|
||||
movq %rdx,(%rsp,%r9,8)
|
||||
|
||||
leaq 1(%r14),%r14
|
||||
cmpq %r9,%r14
|
||||
jl .Louter
|
||||
|
||||
leaq (%rsp),%rsi
|
||||
leaq -1(%r9),%r15
|
||||
|
||||
movq (%rsi),%rax
|
||||
xorq %r14,%r14
|
||||
jmp .Lsub
|
||||
.align 16
|
||||
.Lsub: sbbq (%rcx,%r14,8),%rax
|
||||
movq %rax,(%rdi,%r14,8)
|
||||
decq %r15
|
||||
movq 8(%rsi,%r14,8),%rax
|
||||
leaq 1(%r14),%r14
|
||||
jge .Lsub
|
||||
|
||||
sbbq $0,%rax
|
||||
andq %rax,%rsi
|
||||
notq %rax
|
||||
movq %rdi,%rcx
|
||||
andq %rax,%rcx
|
||||
leaq -1(%r9),%r15
|
||||
orq %rcx,%rsi
|
||||
.align 16
|
||||
.Lcopy:
|
||||
movq (%rsi,%r15,8),%rax
|
||||
movq %rax,(%rdi,%r15,8)
|
||||
movq %r14,(%rsp,%r15,8)
|
||||
decq %r15
|
||||
jge .Lcopy
|
||||
|
||||
movq 8(%rsp,%r9,8),%rsp
|
||||
movq $1,%rax
|
||||
popq %r15
|
||||
popq %r14
|
||||
popq %r13
|
||||
popq %r12
|
||||
popq %rbp
|
||||
popq %rbx
|
||||
.byte 0xf3,0xc3
|
||||
.size bn_mul_mont,.-bn_mul_mont
|
||||
.byte 77,111,110,116,103,111,109,101,114,121,32,77,117,108,116,105,112,108,105,99,97,116,105,111,110,32,102,111,114,32,120,56,54,95,54,52,44,32,67,82,89,80,84,79,71,65,77,83,32,98,121,32,60,97,112,112,114,111,64,111,112,101,110,115,115,108,46,111,114,103,62,0
|
||||
Reference in New Issue
Block a user