summaryrefslogtreecommitdiff
path: root/security/nss/lib/freebl/mpi/mpmontg.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/lib/freebl/mpi/mpmontg.c')
-rw-r--r--security/nss/lib/freebl/mpi/mpmontg.c561
1 files changed, 0 insertions, 561 deletions
diff --git a/security/nss/lib/freebl/mpi/mpmontg.c b/security/nss/lib/freebl/mpi/mpmontg.c
deleted file mode 100644
index 146c8c625..000000000
--- a/security/nss/lib/freebl/mpi/mpmontg.c
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- * $Id$
- */
-
-/* This file implements moduluar exponentiation using Montgomery's
- * method for modular reduction. This file implements the method
- * described as "Improvement 1" in the paper "A Cryptogrpahic Library for
- * the Motorola DSP56000" by Stephen R. Dusse' and Burton S. Kaliski Jr.
- * published in "Advances in Cryptology: Proceedings of EUROCRYPT '90"
- * "Lecture Notes in Computer Science" volume 473, 1991, pg 230-244,
- * published by Springer Verlag.
- */
-
-/* #define MP_USING_MONT_MULF 1 */
-#include <string.h>
-#include "mpi-priv.h"
-#include "mplogic.h"
-#include "mpprime.h"
-#ifdef MP_USING_MONT_MULF
-#include "montmulf.h"
-#endif
-
-#define STATIC
-/* #define DEBUG 1 */
-
-#define MAX_WINDOW_BITS 6
-#define MAX_ODD_INTS 32 /* 2 ** (WINDOW_BITS - 1) */
-
-typedef struct {
- mp_int N; /* modulus N */
- mp_digit n0prime; /* n0' = - (n0 ** -1) mod MP_RADIX */
- mp_size b; /* R == 2 ** b, also b = # significant bits in N */
-} mp_mont_modulus;
-
-mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c,
- mp_mont_modulus *mmm);
-
-/* computes T = REDC(T), 2^b == R */
-STATIC
-mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm)
-{
- mp_err res;
- mp_size i;
-
- i = MP_USED(T) + MP_USED(&mmm->N) + 2;
- MP_CHECKOK( s_mp_pad(T, i) );
- for (i = 0; i < MP_USED(&mmm->N); ++i ) {
- mp_digit m_i = MP_DIGIT(T, i) * mmm->n0prime;
- /* T += N * m_i * (MP_RADIX ** i); */
- MP_CHECKOK( s_mp_mul_d_add_offset(&mmm->N, m_i, T, i) );
- }
- s_mp_clamp(T);
-
- /* T /= R */
- s_mp_div_2d(T, mmm->b);
-
- if ((res = s_mp_cmp(T, &mmm->N)) >= 0) {
- /* T = T - N */
- MP_CHECKOK( s_mp_sub(T, &mmm->N) );
-#ifdef DEBUG
- if ((res = mp_cmp(T, &mmm->N)) >= 0) {
- res = MP_UNDEF;
- goto CLEANUP;
- }
-#endif
- }
- res = MP_OKAY;
-CLEANUP:
- return res;
-}
-
-#if !defined(MP_ASSEMBLY_MUL_MONT) && !defined(MP_MONT_USE_MP_MUL)
-mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c,
- mp_mont_modulus *mmm)
-{
- mp_digit *pb;
- mp_digit m_i;
- mp_err res;
- mp_size ib;
- mp_size useda, usedb;
-
- ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
-
- if (MP_USED(a) < MP_USED(b)) {
- const mp_int *xch = b; /* switch a and b, to do fewer outer loops */
- b = a;
- a = xch;
- }
-
- MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
- ib = MP_USED(a) + MP_MAX(MP_USED(b), MP_USED(&mmm->N)) + 2;
- if((res = s_mp_pad(c, ib)) != MP_OKAY)
- goto CLEANUP;
-
- useda = MP_USED(a);
- pb = MP_DIGITS(b);
- s_mpv_mul_d(MP_DIGITS(a), useda, *pb++, MP_DIGITS(c));
- s_mp_setz(MP_DIGITS(c) + useda + 1, ib - (useda + 1));
- m_i = MP_DIGIT(c, 0) * mmm->n0prime;
- s_mp_mul_d_add_offset(&mmm->N, m_i, c, 0);
-
- /* Outer loop: Digits of b */
- usedb = MP_USED(b);
- for (ib = 1; ib < usedb; ib++) {
- mp_digit b_i = *pb++;
-
- /* Inner product: Digits of a */
- if (b_i)
- s_mpv_mul_d_add_prop(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib);
- m_i = MP_DIGIT(c, ib) * mmm->n0prime;
- s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib);
- }
- if (usedb < MP_USED(&mmm->N)) {
- for (usedb = MP_USED(&mmm->N); ib < usedb; ++ib ) {
- m_i = MP_DIGIT(c, ib) * mmm->n0prime;
- s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib);
- }
- }
- s_mp_clamp(c);
- s_mp_div_2d(c, mmm->b);
- if (s_mp_cmp(c, &mmm->N) >= 0) {
- MP_CHECKOK( s_mp_sub(c, &mmm->N) );
- }
- res = MP_OKAY;
-
-CLEANUP:
- return res;
-}
-#endif
-
-STATIC
-mp_err s_mp_to_mont(const mp_int *x, mp_mont_modulus *mmm, mp_int *xMont)
-{
- mp_err res;
-
- /* xMont = x * R mod N where N is modulus */
- MP_CHECKOK( mpl_lsh(x, xMont, mmm->b) ); /* xMont = x << b */
- MP_CHECKOK( mp_div(xMont, &mmm->N, 0, xMont) ); /* mod N */
-CLEANUP:
- return res;
-}
-
-#ifdef MP_USING_MONT_MULF
-
-unsigned int mp_using_mont_mulf = 1;
-
-/* computes montgomery square of the integer in mResult */
-#define SQR \
- conv_i32_to_d32_and_d16(dm1, d16Tmp, mResult, nLen); \
- mont_mulf_noconv(mResult, dm1, d16Tmp, \
- dTmp, dn, MP_DIGITS(modulus), nLen, dn0)
-
-/* computes montgomery product of x and the integer in mResult */
-#define MUL(x) \
- conv_i32_to_d32(dm1, mResult, nLen); \
- mont_mulf_noconv(mResult, dm1, oddPowers[x], \
- dTmp, dn, MP_DIGITS(modulus), nLen, dn0)
-
-/* Do modular exponentiation using floating point multiply code. */
-mp_err mp_exptmod_f(const mp_int * montBase,
- const mp_int * exponent,
- const mp_int * modulus,
- mp_int * result,
- mp_mont_modulus *mmm,
- int nLen,
- mp_size bits_in_exponent,
- mp_size window_bits,
- mp_size odd_ints)
-{
- mp_digit *mResult;
- double *dBuf = 0, *dm1, *dn, *dSqr, *d16Tmp, *dTmp;
- double dn0;
- mp_size i;
- mp_err res;
- int expOff;
- int dSize = 0, oddPowSize, dTmpSize;
- mp_int accum1;
- double *oddPowers[MAX_ODD_INTS];
-
- /* function for computing n0prime only works if n0 is odd */
-
- MP_DIGITS(&accum1) = 0;
-
- for (i = 0; i < MAX_ODD_INTS; ++i)
- oddPowers[i] = 0;
-
- MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) );
-
- mp_set(&accum1, 1);
- MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) );
- MP_CHECKOK( s_mp_pad(&accum1, nLen) );
-
- oddPowSize = 2 * nLen + 1;
- dTmpSize = 2 * oddPowSize;
- dSize = sizeof(double) * (nLen * 4 + 1 +
- ((odd_ints + 1) * oddPowSize) + dTmpSize);
- dBuf = (double *)malloc(dSize);
- dm1 = dBuf; /* array of d32 */
- dn = dBuf + nLen; /* array of d32 */
- dSqr = dn + nLen; /* array of d32 */
- d16Tmp = dSqr + nLen; /* array of d16 */
- dTmp = d16Tmp + oddPowSize;
-
- for (i = 0; i < odd_ints; ++i) {
- oddPowers[i] = dTmp;
- dTmp += oddPowSize;
- }
- mResult = (mp_digit *)(dTmp + dTmpSize); /* size is nLen + 1 */
-
- /* Make dn and dn0 */
- conv_i32_to_d32(dn, MP_DIGITS(modulus), nLen);
- dn0 = (double)(mmm->n0prime & 0xffff);
-
- /* Make dSqr */
- conv_i32_to_d32_and_d16(dm1, oddPowers[0], MP_DIGITS(montBase), nLen);
- mont_mulf_noconv(mResult, dm1, oddPowers[0],
- dTmp, dn, MP_DIGITS(modulus), nLen, dn0);
- conv_i32_to_d32(dSqr, mResult, nLen);
-
- for (i = 1; i < odd_ints; ++i) {
- mont_mulf_noconv(mResult, dSqr, oddPowers[i - 1],
- dTmp, dn, MP_DIGITS(modulus), nLen, dn0);
- conv_i32_to_d16(oddPowers[i], mResult, nLen);
- }
-
- s_mp_copy(MP_DIGITS(&accum1), mResult, nLen); /* from, to, len */
-
- for (expOff = bits_in_exponent - window_bits; expOff >= 0; expOff -= window_bits) {
- mp_size smallExp;
- MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) );
- smallExp = (mp_size)res;
-
- if (window_bits == 4) {
- if (!smallExp) {
- SQR; SQR; SQR; SQR;
- } else if (smallExp & 1) {
- SQR; SQR; SQR; SQR; MUL(smallExp/2);
- } else if (smallExp & 2) {
- SQR; SQR; SQR; MUL(smallExp/4); SQR;
- } else if (smallExp & 4) {
- SQR; SQR; MUL(smallExp/8); SQR; SQR;
- } else if (smallExp & 8) {
- SQR; MUL(smallExp/16); SQR; SQR; SQR;
- } else {
- abort();
- }
- } else if (window_bits == 5) {
- if (!smallExp) {
- SQR; SQR; SQR; SQR; SQR;
- } else if (smallExp & 1) {
- SQR; SQR; SQR; SQR; SQR; MUL(smallExp/2);
- } else if (smallExp & 2) {
- SQR; SQR; SQR; SQR; MUL(smallExp/4); SQR;
- } else if (smallExp & 4) {
- SQR; SQR; SQR; MUL(smallExp/8); SQR; SQR;
- } else if (smallExp & 8) {
- SQR; SQR; MUL(smallExp/16); SQR; SQR; SQR;
- } else if (smallExp & 0x10) {
- SQR; MUL(smallExp/32); SQR; SQR; SQR; SQR;
- } else {
- abort();
- }
- } else if (window_bits == 6) {
- if (!smallExp) {
- SQR; SQR; SQR; SQR; SQR; SQR;
- } else if (smallExp & 1) {
- SQR; SQR; SQR; SQR; SQR; SQR; MUL(smallExp/2);
- } else if (smallExp & 2) {
- SQR; SQR; SQR; SQR; SQR; MUL(smallExp/4); SQR;
- } else if (smallExp & 4) {
- SQR; SQR; SQR; SQR; MUL(smallExp/8); SQR; SQR;
- } else if (smallExp & 8) {
- SQR; SQR; SQR; MUL(smallExp/16); SQR; SQR; SQR;
- } else if (smallExp & 0x10) {
- SQR; SQR; MUL(smallExp/32); SQR; SQR; SQR; SQR;
- } else if (smallExp & 0x20) {
- SQR; MUL(smallExp/64); SQR; SQR; SQR; SQR; SQR;
- } else {
- abort();
- }
- } else {
- abort();
- }
- }
-
- s_mp_copy(mResult, MP_DIGITS(&accum1), nLen); /* from, to, len */
-
- res = s_mp_redc(&accum1, mmm);
- mp_exch(&accum1, result);
-
-CLEANUP:
- mp_clear(&accum1);
- if (dBuf) {
- if (dSize)
- memset(dBuf, 0, dSize);
- free(dBuf);
- }
-
- return res;
-}
-#undef SQR
-#undef MUL
-#endif
-
-#define SQR(a,b) \
- MP_CHECKOK( mp_sqr(a, b) );\
- MP_CHECKOK( s_mp_redc(b, mmm) )
-
-#if defined(MP_MONT_USE_MP_MUL)
-#define MUL(x,a,b) \
- MP_CHECKOK( mp_mul(a, oddPowers + (x), b) ); \
- MP_CHECKOK( s_mp_redc(b, mmm) )
-#else
-#define MUL(x,a,b) \
- MP_CHECKOK( s_mp_mul_mont(a, oddPowers + (x), b, mmm) )
-#endif
-
-#define SWAPPA ptmp = pa1; pa1 = pa2; pa2 = ptmp
-
-/* Do modular exponentiation using integer multiply code. */
-mp_err mp_exptmod_i(const mp_int * montBase,
- const mp_int * exponent,
- const mp_int * modulus,
- mp_int * result,
- mp_mont_modulus *mmm,
- int nLen,
- mp_size bits_in_exponent,
- mp_size window_bits,
- mp_size odd_ints)
-{
- mp_int *pa1, *pa2, *ptmp;
- mp_size i;
- mp_err res;
- int expOff;
- mp_int accum1, accum2, power2, oddPowers[MAX_ODD_INTS];
-
- /* power2 = base ** 2; oddPowers[i] = base ** (2*i + 1); */
- /* oddPowers[i] = base ** (2*i + 1); */
-
- MP_DIGITS(&accum1) = 0;
- MP_DIGITS(&accum2) = 0;
- MP_DIGITS(&power2) = 0;
- for (i = 0; i < MAX_ODD_INTS; ++i) {
- MP_DIGITS(oddPowers + i) = 0;
- }
-
- MP_CHECKOK( mp_init_size(&accum1, 3 * nLen + 2) );
- MP_CHECKOK( mp_init_size(&accum2, 3 * nLen + 2) );
-
- MP_CHECKOK( mp_init_copy(&oddPowers[0], montBase) );
-
- mp_init_size(&power2, nLen + 2 * MP_USED(montBase) + 2);
- MP_CHECKOK( mp_sqr(montBase, &power2) ); /* power2 = montBase ** 2 */
- MP_CHECKOK( s_mp_redc(&power2, mmm) );
-
- for (i = 1; i < odd_ints; ++i) {
- mp_init_size(oddPowers + i, nLen + 2 * MP_USED(&power2) + 2);
- MP_CHECKOK( mp_mul(oddPowers + (i - 1), &power2, oddPowers + i) );
- MP_CHECKOK( s_mp_redc(oddPowers + i, mmm) );
- }
-
- /* set accumulator to montgomery residue of 1 */
- mp_set(&accum1, 1);
- MP_CHECKOK( s_mp_to_mont(&accum1, mmm, &accum1) );
- pa1 = &accum1;
- pa2 = &accum2;
-
- for (expOff = bits_in_exponent - window_bits; expOff >= 0; expOff -= window_bits) {
- mp_size smallExp;
- MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) );
- smallExp = (mp_size)res;
-
- if (window_bits == 4) {
- if (!smallExp) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- } else if (smallExp & 1) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- MUL(smallExp/2, pa1,pa2); SWAPPA;
- } else if (smallExp & 2) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2);
- MUL(smallExp/4,pa2,pa1); SQR(pa1,pa2); SWAPPA;
- } else if (smallExp & 4) {
- SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/8,pa1,pa2);
- SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA;
- } else if (smallExp & 8) {
- SQR(pa1,pa2); MUL(smallExp/16,pa2,pa1); SQR(pa1,pa2);
- SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA;
- } else {
- abort();
- }
- } else if (window_bits == 5) {
- if (!smallExp) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- SQR(pa1,pa2); SWAPPA;
- } else if (smallExp & 1) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- SQR(pa1,pa2); MUL(smallExp/2,pa2,pa1);
- } else if (smallExp & 2) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- MUL(smallExp/4,pa1,pa2); SQR(pa2,pa1);
- } else if (smallExp & 4) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2);
- MUL(smallExp/8,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- } else if (smallExp & 8) {
- SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/16,pa1,pa2);
- SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- } else if (smallExp & 0x10) {
- SQR(pa1,pa2); MUL(smallExp/32,pa2,pa1); SQR(pa1,pa2);
- SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- } else {
- abort();
- }
- } else if (window_bits == 6) {
- if (!smallExp) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- SQR(pa1,pa2); SQR(pa2,pa1);
- } else if (smallExp & 1) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/2,pa1,pa2); SWAPPA;
- } else if (smallExp & 2) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- SQR(pa1,pa2); MUL(smallExp/4,pa2,pa1); SQR(pa1,pa2); SWAPPA;
- } else if (smallExp & 4) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- MUL(smallExp/8,pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA;
- } else if (smallExp & 8) {
- SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2);
- MUL(smallExp/16,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
- SQR(pa1,pa2); SWAPPA;
- } else if (smallExp & 0x10) {
- SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/32,pa1,pa2);
- SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA;
- } else if (smallExp & 0x20) {
- SQR(pa1,pa2); MUL(smallExp/64,pa2,pa1); SQR(pa1,pa2);
- SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA;
- } else {
- abort();
- }
- } else {
- abort();
- }
- }
-
- res = s_mp_redc(pa1, mmm);
- mp_exch(pa1, result);
-
-CLEANUP:
- mp_clear(&accum1);
- mp_clear(&accum2);
- mp_clear(&power2);
- for (i = 0; i < odd_ints; ++i) {
- mp_clear(oddPowers + i);
- }
- return res;
-}
-#undef SQR
-#undef MUL
-
-
-mp_err mp_exptmod(const mp_int *inBase, const mp_int *exponent,
- const mp_int *modulus, mp_int *result)
-{
- const mp_int *base;
- mp_size bits_in_exponent, i, window_bits, odd_ints;
- mp_err res;
- int nLen;
- mp_int montBase, goodBase;
- mp_mont_modulus mmm;
-
- /* function for computing n0prime only works if n0 is odd */
- if (!mp_isodd(modulus))
- return s_mp_exptmod(inBase, exponent, modulus, result);
-
- MP_DIGITS(&montBase) = 0;
- MP_DIGITS(&goodBase) = 0;
-
- if (mp_cmp(inBase, modulus) < 0) {
- base = inBase;
- } else {
- MP_CHECKOK( mp_init(&goodBase) );
- base = &goodBase;
- MP_CHECKOK( mp_mod(inBase, modulus, &goodBase) );
- }
-
- nLen = MP_USED(modulus);
- MP_CHECKOK( mp_init_size(&montBase, 2 * nLen + 2) );
-
- mmm.N = *modulus; /* a copy of the mp_int struct */
- i = mpl_significant_bits(modulus);
- i += MP_DIGIT_BIT - 1;
- mmm.b = i - i % MP_DIGIT_BIT;
-
- /* compute n0', given n0, n0' = -(n0 ** -1) mod MP_RADIX
- ** where n0 = least significant mp_digit of N, the modulus.
- */
- mmm.n0prime = 0 - s_mp_invmod_radix( MP_DIGIT(modulus, 0) );
-
- MP_CHECKOK( s_mp_to_mont(base, &mmm, &montBase) );
-
- bits_in_exponent = mpl_significant_bits(exponent);
- if (bits_in_exponent > 480)
- window_bits = 6;
- else if (bits_in_exponent > 160)
- window_bits = 5;
- else
- window_bits = 4;
- odd_ints = 1 << (window_bits - 1);
- i = bits_in_exponent % window_bits;
- if (i != 0) {
- bits_in_exponent += window_bits - i;
- }
-
-#ifdef MP_USING_MONT_MULF
- if (mp_using_mont_mulf) {
- MP_CHECKOK( s_mp_pad(&montBase, nLen) );
- res = mp_exptmod_f(&montBase, exponent, modulus, result, &mmm, nLen,
- bits_in_exponent, window_bits, odd_ints);
- } else
-#endif
- res = mp_exptmod_i(&montBase, exponent, modulus, result, &mmm, nLen,
- bits_in_exponent, window_bits, odd_ints);
-
-CLEANUP:
- mp_clear(&montBase);
- mp_clear(&goodBase);
- /* Don't mp_clear mmm.N because it is merely a copy of modulus.
- ** Just zap it.
- */
- memset(&mmm, 0, sizeof mmm);
- return res;
-}