mpmontg.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:11k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation. Portions created by Netscape are 
  16.  * Copyright (C) 2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above. If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  *  $Id: mpmontg.c,v 1.8 2000/09/14 00:30:51 nelsonb%netscape.com Exp $
  33.  */
  34. /* This file implements moduluar exponentiation using Montgomery's
  35.  * method for modular reduction.  This file implements the method
  36.  * described as "Improvement 1" in the paper "A Cryptogrpahic Library for
  37.  * the Motorola DSP56000" by Stephen R. Dusse' and Burton S. Kaliski Jr.
  38.  * published in "Advances in Cryptology: Proceedings of EUROCRYPT '90"
  39.  * "Lecture Notes in Computer Science" volume 473, 1991, pg 230-244,
  40.  * published by Springer Verlag.
  41.  */
  42. #include <string.h>
  43. #include "mpi-priv.h"
  44. #include "mplogic.h"
  45. #include "mpprime.h"
  46. #define STATIC
  47. /* #define DEBUG 1  */
  48. #define MAX_WINDOW_BITS 6
  49. #define MAX_ODD_INTS    32   /* 2 ** (WINDOW_BITS - 1) */
  50. typedef struct {
  51.   mp_int       N; /* modulus N */
  52.   mp_digit     n0prime; /* n0' = - (n0 ** -1) mod MP_RADIX */
  53.   mp_size      b; /* R == 2 ** b,  also b = # significant bits in N */
  54. } mp_mont_modulus;
  55. mp_err   s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c, 
  56.                mp_mont_modulus *mmm);
  57. /* computes T = REDC(T), 2^b == R */
  58. STATIC
  59. mp_err s_mp_redc(mp_int *T, mp_mont_modulus *mmm)
  60. {
  61.   mp_err res;
  62.   mp_size i;
  63. #ifdef DEBUG
  64.   mp_int m;
  65.   MP_DIGITS(&m) = 0;
  66. #endif
  67.   i = MP_USED(T) + MP_USED(&mmm->N) + 2;
  68.   MP_CHECKOK( s_mp_pad(T, i) );
  69.   for (i = 0; i < MP_USED(&mmm->N); ++i ) {
  70.     mp_digit m_i = MP_DIGIT(T, i) * mmm->n0prime;
  71.     /* T += N * m_i * (MP_RADIX ** i); */
  72.     MP_CHECKOK( s_mp_mul_d_add_offset(&mmm->N, m_i, T, i) );
  73.   }
  74.   s_mp_clamp(T);
  75.   /* T /= R */
  76. #ifdef DEBUG
  77.   MP_CHECKOK( mp_init(&m) );
  78.   MP_CHECKOK( mp_div_2d(T, mmm->b, T, &m));
  79.   /* here, remainder m should be equal to zero */
  80.   if (mp_cmp_z(&m) != 0) {
  81.     res = MP_UNDEF;
  82.     goto CLEANUP;
  83.   }
  84. #else
  85.   s_mp_div_2d(T, mmm->b); 
  86. #endif
  87.   if ((res = s_mp_cmp(T, &mmm->N)) >= 0) {
  88.     /* T = T - N */
  89.     MP_CHECKOK( s_mp_sub(T, &mmm->N) );
  90. #ifdef DEBUG
  91.     if ((res = mp_cmp(T, &mmm->N)) >= 0) {
  92.       res = MP_UNDEF;
  93.       goto CLEANUP;
  94.     }
  95. #endif
  96.   }
  97.   res = MP_OKAY;
  98. CLEANUP:
  99. #ifdef DEBUG
  100.   mp_clear(&m);
  101. #endif
  102.   return res;
  103. }
  104. #if !defined(MP_ASSEMBLY_MUL_MONT) && !defined(MP_MONT_USE_MP_MUL)
  105. mp_err s_mp_mul_mont(const mp_int *a, const mp_int *b, mp_int *c, 
  106.            mp_mont_modulus *mmm)
  107. {
  108.   mp_digit *pb;
  109.   mp_digit m_i;
  110.   mp_err   res;
  111.   mp_size  ib;
  112.   mp_size  useda, usedb;
  113.   ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);
  114.   if (MP_USED(a) < MP_USED(b)) {
  115.     const mp_int *xch = b; /* switch a and b, to do fewer outer loops */
  116.     b = a;
  117.     a = xch;
  118.   }
  119.   MP_USED(c) = 1; MP_DIGIT(c, 0) = 0;
  120.   ib = MP_USED(a) + MP_MAX(MP_USED(b), MP_USED(&mmm->N)) + 2;
  121.   if((res = s_mp_pad(c, ib)) != MP_OKAY)
  122.     goto CLEANUP;
  123.   useda = MP_USED(a);
  124.   pb = MP_DIGITS(b);
  125.   s_mpv_mul_d(MP_DIGITS(a), useda, *pb++, MP_DIGITS(c));
  126.   s_mp_setz(MP_DIGITS(c) + useda + 1, ib - (useda + 1));
  127.   m_i = MP_DIGIT(c, 0) * mmm->n0prime;
  128.   s_mp_mul_d_add_offset(&mmm->N, m_i, c, 0);
  129.   /* Outer loop:  Digits of b */
  130.   usedb = MP_USED(b);
  131.   for (ib = 1; ib < usedb; ib++) {
  132.     mp_digit b_i    = *pb++;
  133.     /* Inner product:  Digits of a */
  134.     if (b_i)
  135.       s_mpv_mul_d_add_prop(MP_DIGITS(a), useda, b_i, MP_DIGITS(c) + ib);
  136.     m_i = MP_DIGIT(c, ib) * mmm->n0prime;
  137.     s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib);
  138.   }
  139.   if (usedb < MP_USED(&mmm->N)) {
  140.     for (usedb = MP_USED(&mmm->N); ib < usedb; ++ib ) {
  141.       m_i = MP_DIGIT(c, ib) * mmm->n0prime;
  142.       s_mp_mul_d_add_offset(&mmm->N, m_i, c, ib);
  143.     }
  144.   }
  145.   s_mp_clamp(c);
  146.   s_mp_div_2d(c, mmm->b); 
  147.   if (s_mp_cmp(c, &mmm->N) >= 0) {
  148.     MP_CHECKOK( s_mp_sub(c, &mmm->N) );
  149.   }
  150.   res = MP_OKAY;
  151. CLEANUP:
  152.   return res;
  153. }
  154. #endif
  155. STATIC
  156. mp_err s_mp_to_mont(const mp_int *x, mp_mont_modulus *mmm, mp_int *xMont)
  157. {
  158.   mp_err res;
  159.   /* xMont = x * R mod N   where  N is modulus */
  160.   MP_CHECKOK( mpl_lsh(x, xMont, mmm->b) );   /* xMont = x << b */
  161.   MP_CHECKOK( mp_div(xMont, &mmm->N, 0, xMont) ); /*         mod N */
  162. CLEANUP:
  163.   return res;
  164. }
  165. mp_err mp_exptmod(const mp_int *inBase, const mp_int *exponent, 
  166.   const mp_int *modulus, mp_int *result)
  167. {
  168.   const mp_int *base;
  169.   mp_int *pa1, *pa2, *ptmp;
  170.   mp_size bits_in_exponent;
  171.   mp_size i;
  172.   mp_size window_bits, odd_ints;
  173.   mp_err res;
  174.   mp_int square, accum1, accum2, goodBase;
  175.   mp_mont_modulus mmm;
  176.   /* function for computing n0prime only works if n0 is odd */
  177.   if (!mp_isodd(modulus))
  178.     return s_mp_exptmod(inBase, exponent, modulus, result);
  179.   MP_DIGITS(&square) = 0;
  180.   MP_DIGITS(&accum1) = 0;
  181.   MP_DIGITS(&accum2) = 0;
  182.   MP_DIGITS(&goodBase) = 0;
  183.   if (mp_cmp(inBase, modulus) < 0) {
  184.     base = inBase;
  185.   } else {
  186.     MP_CHECKOK( mp_init(&goodBase) );
  187.     base = &goodBase;
  188.     MP_CHECKOK( mp_mod(inBase, modulus, &goodBase) );
  189.   }
  190.   MP_CHECKOK( mp_init_size(&square, 2 * MP_USED(modulus) + 2) );
  191.   MP_CHECKOK( mp_init_size(&accum1, 3 * MP_USED(modulus) + 2) );
  192.   MP_CHECKOK( mp_init_size(&accum2, 3 * MP_USED(modulus) + 2) );
  193.   mmm.N = *modulus; /* a copy of the mp_int struct */
  194.   i = mpl_significant_bits(modulus);
  195.   i += MP_DIGIT_BIT - 1;
  196.   mmm.b = i - i % MP_DIGIT_BIT;
  197.   /* compute n0', given n0, n0' = -(n0 ** -1) mod MP_RADIX
  198.   ** where n0 = least significant mp_digit of N, the modulus.
  199.   */
  200.   mmm.n0prime = 0 - s_mp_invmod_radix( MP_DIGIT(modulus, 0) );
  201.   MP_CHECKOK( s_mp_to_mont(base, &mmm, &square) );
  202.   bits_in_exponent = mpl_significant_bits(exponent);
  203.   if (bits_in_exponent > 480)
  204.     window_bits = 6;
  205.   else if (bits_in_exponent > 160)
  206.     window_bits = 5;
  207.   else
  208.     window_bits = 4;
  209.   odd_ints = 1 << (window_bits - 1);
  210.   i = bits_in_exponent % window_bits;
  211.   if (i != 0) {
  212.     bits_in_exponent += window_bits - i;
  213.   } 
  214.   {
  215.     /* oddPowers[i] = base ** (2*i + 1); */
  216.     int expOff;
  217.     /* power2 = base ** 2; oddPowers[i] = base ** (2*i + 1); */
  218.     mp_int power2, oddPowers[MAX_ODD_INTS];
  219.     MP_CHECKOK( mp_init_copy(oddPowers, &square) );
  220.     mp_init_size(&power2, MP_USED(modulus) + 2 * MP_USED(&square) + 2);
  221.     MP_CHECKOK( mp_sqr(&square, &power2) ); /* square = square ** 2 */
  222.     MP_CHECKOK( s_mp_redc(&power2, &mmm) );
  223.     for (i = 1; i < odd_ints; ++i) {
  224.       mp_init_size(oddPowers + i, MP_USED(modulus) + 2 * MP_USED(&power2) + 2);
  225.       MP_CHECKOK( mp_mul(oddPowers + (i - 1), &power2, oddPowers + i) );
  226.       MP_CHECKOK( s_mp_redc(oddPowers + i, &mmm) );
  227.     }
  228.     mp_set(&accum1, 1);
  229.     MP_CHECKOK( s_mp_to_mont(&accum1, &mmm, &accum1) );
  230.     pa1 = &accum1;
  231.     pa2 = &accum2;
  232. #define SQR(a,b) 
  233.     MP_CHECKOK( mp_sqr(a, b) );
  234.     MP_CHECKOK( s_mp_redc(b, &mmm) )
  235. #if defined(MP_MONT_USE_MP_MUL)
  236. #define MUL(x,a,b) 
  237.     MP_CHECKOK( mp_mul(a, oddPowers + (x), b) ); 
  238.     MP_CHECKOK( s_mp_redc(b, &mmm) ) 
  239. #else
  240. #define MUL(x,a,b) 
  241.     MP_CHECKOK( s_mp_mul_mont(a, oddPowers + (x), b, &mmm) )
  242. #endif
  243. #define SWAPPA ptmp = pa1; pa1 = pa2; pa2 = ptmp
  244.     for (expOff = bits_in_exponent - window_bits; expOff >= 0; expOff -= window_bits) {
  245.       mp_size smallExp;
  246.       MP_CHECKOK( mpl_get_bits(exponent, expOff, window_bits) );
  247.       smallExp = (mp_size)res;
  248.       if (window_bits == 4) {
  249. if (!smallExp) {
  250.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
  251. } else if (smallExp & 1) {
  252.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); 
  253.   MUL(smallExp/2, pa1,pa2); SWAPPA;
  254. } else if (smallExp & 2) {
  255.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); 
  256.   MUL(smallExp/4,pa2,pa1); SQR(pa1,pa2); SWAPPA;
  257. } else if (smallExp & 4) {
  258.   SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/8,pa1,pa2); 
  259.   SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA;
  260. } else if (smallExp & 8) {
  261.   SQR(pa1,pa2); MUL(smallExp/16,pa2,pa1); SQR(pa1,pa2); 
  262.   SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA;
  263. } else {
  264.   abort();
  265. }
  266.       } else if (window_bits == 5) {
  267. if (!smallExp) {
  268.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); 
  269.   SQR(pa1,pa2); SWAPPA;
  270. } else if (smallExp & 1) {
  271.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); 
  272.   SQR(pa1,pa2); MUL(smallExp/2,pa2,pa1);
  273. } else if (smallExp & 2) {
  274.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); 
  275.   MUL(smallExp/4,pa1,pa2); SQR(pa2,pa1);
  276. } else if (smallExp & 4) {
  277.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); 
  278.   MUL(smallExp/8,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
  279. } else if (smallExp & 8) {
  280.   SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/16,pa1,pa2); 
  281.   SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
  282. } else if (smallExp & 0x10) {
  283.   SQR(pa1,pa2); MUL(smallExp/32,pa2,pa1); SQR(pa1,pa2); 
  284.   SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1);
  285. } else {
  286.     abort();
  287. }
  288.       } else if (window_bits == 6) {
  289. if (!smallExp) {
  290.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); 
  291.   SQR(pa1,pa2); SQR(pa2,pa1);
  292. } else if (smallExp & 1) {
  293.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); 
  294.   SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/2,pa1,pa2); SWAPPA;
  295. } else if (smallExp & 2) {
  296.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); 
  297.   SQR(pa1,pa2); MUL(smallExp/4,pa2,pa1); SQR(pa1,pa2); SWAPPA;
  298. } else if (smallExp & 4) {
  299.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); 
  300.   MUL(smallExp/8,pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA;
  301. } else if (smallExp & 8) {
  302.   SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); 
  303.   MUL(smallExp/16,pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); 
  304.   SQR(pa1,pa2); SWAPPA;
  305. } else if (smallExp & 0x10) {
  306.   SQR(pa1,pa2); SQR(pa2,pa1); MUL(smallExp/32,pa1,pa2); 
  307.   SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA;
  308. } else if (smallExp & 0x20) {
  309.   SQR(pa1,pa2); MUL(smallExp/64,pa2,pa1); SQR(pa1,pa2); 
  310.   SQR(pa2,pa1); SQR(pa1,pa2); SQR(pa2,pa1); SQR(pa1,pa2); SWAPPA;
  311. } else {
  312.   abort();
  313. }
  314.       } else {
  315. abort();
  316.       }
  317.     }
  318.     mp_clear(&power2);
  319.     for (i = 0; i < odd_ints; ++i) {
  320.       mp_clear(oddPowers + i);
  321.     }
  322.   }
  323.   res = s_mp_redc(pa1, &mmm);
  324.   mp_exch(pa1, result);
  325. CLEANUP:
  326.   mp_clear(&square);
  327.   mp_clear(&accum1);
  328.   mp_clear(&accum2);
  329.   mp_clear(&goodBase);
  330.   /* Don't mp_clear mmm.N because it is merely a copy of modulus.
  331.   ** Just zap it.
  332.   */
  333.   memset(&mmm, 0, sizeof mmm);
  334.   return res;
  335. }