linux/lib/mpi/mpi-mul.c
<<
>>
Prefs
   1/* mpi-mul.c  -  MPI functions
   2 * Copyright (C) 1994, 1996, 1998, 2001, 2002,
   3 *               2003 Free Software Foundation, Inc.
   4 *
   5 * This file is part of Libgcrypt.
   6 *
   7 * Note: This code is heavily based on the GNU MP Library.
   8 *       Actually it's the same code with only minor changes in the
   9 *       way the data is stored; this is to support the abstraction
  10 *       of an optional secure memory allocation which may be used
  11 *       to avoid revealing of sensitive data due to paging etc.
  12 */
  13
  14#include "mpi-internal.h"
  15
  16void mpi_mul(MPI w, MPI u, MPI v)
  17{
  18        mpi_size_t usize, vsize, wsize;
  19        mpi_ptr_t up, vp, wp;
  20        mpi_limb_t cy;
  21        int usign, vsign, sign_product;
  22        int assign_wp = 0;
  23        mpi_ptr_t tmp_limb = NULL;
  24
  25        if (u->nlimbs < v->nlimbs) {
  26                /* Swap U and V. */
  27                usize = v->nlimbs;
  28                usign = v->sign;
  29                up    = v->d;
  30                vsize = u->nlimbs;
  31                vsign = u->sign;
  32                vp    = u->d;
  33        } else {
  34                usize = u->nlimbs;
  35                usign = u->sign;
  36                up    = u->d;
  37                vsize = v->nlimbs;
  38                vsign = v->sign;
  39                vp    = v->d;
  40        }
  41        sign_product = usign ^ vsign;
  42        wp = w->d;
  43
  44        /* Ensure W has space enough to store the result.  */
  45        wsize = usize + vsize;
  46        if (w->alloced < wsize) {
  47                if (wp == up || wp == vp) {
  48                        wp = mpi_alloc_limb_space(wsize);
  49                        assign_wp = 1;
  50                } else {
  51                        mpi_resize(w, wsize);
  52                        wp = w->d;
  53                }
  54        } else { /* Make U and V not overlap with W.    */
  55                if (wp == up) {
  56                        /* W and U are identical.  Allocate temporary space for U. */
  57                        up = tmp_limb = mpi_alloc_limb_space(usize);
  58                        /* Is V identical too?  Keep it identical with U.  */
  59                        if (wp == vp)
  60                                vp = up;
  61                        /* Copy to the temporary space.  */
  62                        MPN_COPY(up, wp, usize);
  63                } else if (wp == vp) {
  64                        /* W and V are identical.  Allocate temporary space for V. */
  65                        vp = tmp_limb = mpi_alloc_limb_space(vsize);
  66                        /* Copy to the temporary space.  */
  67                        MPN_COPY(vp, wp, vsize);
  68                }
  69        }
  70
  71        if (!vsize)
  72                wsize = 0;
  73        else {
  74                mpihelp_mul(wp, up, usize, vp, vsize, &cy);
  75                wsize -= cy ? 0:1;
  76        }
  77
  78        if (assign_wp)
  79                mpi_assign_limb_space(w, wp, wsize);
  80        w->nlimbs = wsize;
  81        w->sign = sign_product;
  82        if (tmp_limb)
  83                mpi_free_limb_space(tmp_limb);
  84}
  85
  86void mpi_mulm(MPI w, MPI u, MPI v, MPI m)
  87{
  88        mpi_mul(w, u, v);
  89        mpi_tdiv_r(w, w, m);
  90}
  91EXPORT_SYMBOL_GPL(mpi_mulm);
  92