⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 apwrx.c

📁 brew代码里面的一个文件
💻 C
📖 第 1 页 / 共 2 页
字号:
/****************************************************************************************
*
*   Title:    APWRXARM.C
*
*   Author:   R. F. Quick, Jr.
*   Created:  April 21, 1998
*   Modified: January 13, 1999
*
*   Language: Microsoft Visual C++ 5.0; ARM ?
*
*   Description:
*
*     Provides the n-bit a**x mod p function required for Diffie-Hellman
*     key exchange.
*
*     Note: this procedure returns 1 for 0**0.
*     Note: this procedure requires that p be an odd number (lsb must be 1)
*
*     This version implements Montgomery reduction and 4-bit
*     sliding-window exponent.  Also has special squaring routine.
*
*     This version uses 32-bit arithmetic, C only.
*
*   Template:
*
*     int apwrxN(int n, unsigned WORD *a, unsigned WORD *x, unsigned WORD *ax,
*       unsigned WORD *p);
*
*   Calling parameters:
*
*     n Number of bits in a, x and p.
*
*     a Input: N-bit value of a.  Stored as unsigned WORD array, with the 
*       least significant word in a[0].  Not changed during execution.
*       
*     x Input: N-bit value of x.  Stored as unsigned WORD array, with the 
*       least significant word in a[0].  Not changed during execution.
*       
*     ax  Output: N-bit value of a**x mod p.  Stored as unsigned WORD array, 
*       with the least significant word in a[0].
*
*     p Input: N-bit value of p.  Stored as unsigned WORD array, with the 
*       least significant word in a[0].  Not changed during execution.
*       
*   Return value:
*   
*     0 if no error, -1 if error.  The  error return occurs if p is all zero
*     or is an even number.
*         
*   (c) 1998, 1999 QUALCOMM Incorporated
*
Copyright (c) 1998 by QUALCOMM, Incorporated.  All Rights Reserved.
*====*====*====*====*====*====*====*====*====*====*====*====*====*====*====*/

/* <EJECT> */
/*===========================================================================

                        EDIT HISTORY FOR MODULE

This section contains comments describing changes made to the module.
Notice that changes are listed in reverse chronological order.

$PVCSPath: L:/src/asw/MSM5100/CP_REL_A/vcs/apwrx.c_v   1.0.2.0   30 Nov 2001 16:43:58   fchan  $
$Header: //depot/asic/msmshared/1x/cp/MSMSHARED_CP_CDMA.02.00.64B/apwrx.c#1 $ $DateTime: 2004/08/24 16:28:29 $ $Author: louiel $

when       who     what, where, why
--------   ---     ----------------------------------------------------------
11/20/02   va      Fixed compiler warning.
09/30/99   ks      Removed compiler warnings by added casts.
01/25/99   ck      Added code to acknowledge the STOP and OFFLINE signals if
                   they are recd in the middle of exponentiation.
01/20/99   ck      Checked in the Module with changes to generate a random
                   number, report to dog and to abort the processing

===========================================================================*/

/* <EJECT> */
/*===========================================================================

                     INCLUDE FILES FOR MODULE

===========================================================================*/
#include "comdef.h"
#include "target.h"

#if(defined (FEATURE_DH) && defined(FEATURE_DH_EXP))

#include "memory.h"
#include "apwrx.h"
#include "dog.h"
#include "msg.h"
#include "dh.h"
#include "task.h"
#include "mc.h"

/* WindowSize must be a power of 2 from 1 to 3
   (i.e. WindowSize can be 2, 4 or 8 bits) */

#define WindowSize 4
#define WindowStorage ((1 << WindowSize) - 1)
#define WindowMask ((1 << WindowSize) - 1)

static 
void WORD_mul(unsigned WORD xy[2],  /* product */
         unsigned WORD x[2],  /* first multiplier */      
         unsigned WORD y)   /* second multiplier */
{
  unsigned WORD t,u;

  /* create x0y0 and x1y1 terms and store */
  xy[0] = (x[0] & LOW)*(y & LOW);
  xy[1] = (x[0] >> (BITCT/2))*(y >> (BITCT/2));

  /* create cross terms in t and u */
  t = (x[0] & LOW)*(y >> (BITCT/2));
  u = (x[0] >> (BITCT/2))*(y & LOW);

  /* add cross terms with carry to xy[1] */
  t += u;
  if (t < u)
    xy[1] += 1 << (BITCT/2);

  /* add ls part of cross term to xy[0] with carry to xy[1] */
  u = xy[0] + (t << (BITCT/2));
  xy[1] += (u < xy[0]);
  xy[0] = u;

  /* add ms part of cross term to xy[1] */
  xy[1] += t >> (BITCT/2);
}

/* multiply multiple-precision numbers
   the extra word in xy ensures that the addition loop terminates
   with no carry, eliminating the need for checking the index */

static
void mulN(int N,        /* number of unsigned WORDs in x and y */
      unsigned WORD *x,   /* first multiplier */
      unsigned WORD *y,   /* second multiplier */
      unsigned WORD *xy)    /* product (2N+1 in size) */
{
  int i,j,k;
  unsigned WORD t[2], tx[2];

  memset(xy, 0, 2*N*sizeof(unsigned WORD));

  tx[1] = 0;

  for (i = 0; i < N; i++)
  {
    for (j = 0; j < N; j++)
    {
      tx[0] = x[i];
      WORD_mul(t,tx,y[j]);

      for (k = i+j; k < 2*N; k++)
      {
        xy[k] += t[0];
        t[0] = t[1] + (xy[k] < t[0]);
        if (t[0] == 0)
          break;
        t[1] = 0;
      }
    }
  }
}

/* square a multiple-precision number */

static
void squareN(int N,
       unsigned WORD *x,
       unsigned WORD *x2)
{
  int i,j,k;
  unsigned WORD c, d, t[2], tx[2];

  tx[1] = 0;

  for (i = 0; i < N; i++)
  {
    /* put in diagonal terms (sets x2, hence no need to initialize) */

    tx[0] = x[i];
    WORD_mul(&x2[2*i],tx,x[i]);
  }

  for (i = 0; i < N-1; i++)
  {
    /* add in twice the off-diagonal terms */

    for (j = i+1; j < N; j++)
    {
      tx[0] = x[i];
      WORD_mul(t,tx,x[j]);

      /* double t */

      d = t[0] << 1;
      c = (d < t[0]);
      t[0] = d;

      d = (t[1] << 1) + c;
      c = (d < t[1]);
      t[1] = d;
      d = c; /* save carry off end */

      for (k = i+j; k < 2*N; k++)
      {
        /* add lsw with carry to c */

        x2[k] += t[0];
        c = (x2[k] < t[0]);

        /* add c to msw with carry to d */

        t[1] += c;
        d += (t[1] < c);

        if ((t[1]|d) == 0)
          break;

        t[0] = t[1];
        t[1] = d;
        d = 0;
      }
    }
  }
}

/* find the integer quotient from dividing an unsigned WORD into a double unsigned WORD */

static
unsigned WORD divd1(unsigned WORD d[2], unsigned WORD v)
{
  int i, c;
  unsigned WORD q;

  if (v == 0) // actual first word should have been 10...0, just divide by 2**BITCT
  {
    if (d[1])
      return d[1];
    else  // special case where divisor is 0xf...f and d[] is also 0xf...f
      return 1;
  }

  if (d[1] == 0) // ms word is zero
    return d[0]/v;

  q = 0;
  c = 0;
  for (i = 0; i < BITCT; i++)
  {
    q <<= 1;

    if (d[1] & MSB)
      c = 1;
    d[1] <<= 1;
    if (d[0] & MSB)
      d[1]++;
    d[0] <<= 1;

    if (c || (v <= d[1]))
    {
      q++;
      d[1] -= v;
      c = 0;
    }
  }
  return q;
}

/* take xy % p.  p_mspos is the position of the most-significant nonzero word in p */

int modpN(int N,      /* number of unsigned WORDs in p */
      unsigned WORD *xy, /* product to be reduced (2N in size) */
      unsigned WORD *p, /* modulus */
      int xy_order    /* number of unsigned WORDs in xy */
     )
{
  int i,j,k,p_mspos;
  unsigned WORD q,t[2],tx[2],d;

  /* start with shifted p aligned with msw of xy, and step to the right,
     subtracting multiples of shifted p until xy is less than shifted p */

  /* find ms word of p */

  for (p_mspos = N-1; p_mspos >= 0; p_mspos--)
    if (p[p_mspos] != 0)
      break;

  if (p_mspos < 0)
  /* p is zero; divide would hang */
  {
    return(-1);
  }

  /* set d to msw of divisor (doesn't change during this function) */
  
  d = p[p_mspos];
  tx[1] = 0;

  for (i = xy_order-1; i >= p_mspos; i--)
  {
    if (i < xy_order-1)
      t[1] = xy[i+1];
    else
      t[1] = 0;
    t[0] = xy[i];
    while (t[1] || (t[0] >= d))
    /* loop until xy is less than shifted p */
    {
      /* Get q = approximate quotient for this step.  Compute it using
         d+1 instead of d to allow for rounding error (thereby ensuring no
         overflow during the multiplication of p by q).
         
         q can be anywhere from half the actual quotient to
         the actual quotient, depending on how much larger d+1 is compared
         to d. (With left-justified p, the range is much
         tighter, speeding up the division.) */

      if (t[1] || (t[0] > d))
        q = divd1(t, (unsigned WORD)(d+1));
      else if (t[0] < d)
        q = 0;
      else
      /* see if xy is really >= shifted p */
      {
        q = 1;
        for (j = i-1; j >= i - p_mspos; j--)
        {
          if (xy[j] > p[p_mspos+j-i])
          /* it's bigger, go do the subtraction */
            break;
          else if (xy[j] < p[p_mspos+j-i])
          /* it's smaller, stop */
          {
            q = 0;
            break;
          }
          /* continue only if the words are equal */
        }
      }

      if (q == 0)
      /* xy is less than shifted p, break out of while loop */
        break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -