Back to home page

OSCL-LXR

 
 

    


0001 /* mpi-mul.c  -  MPI functions
0002  * Copyright (C) 1994, 1996, 1998, 2001, 2002,
0003  *               2003 Free Software Foundation, Inc.
0004  *
0005  * This file is part of Libgcrypt.
0006  *
0007  * Note: This code is heavily based on the GNU MP Library.
0008  *   Actually it's the same code with only minor changes in the
0009  *   way the data is stored; this is to support the abstraction
0010  *   of an optional secure memory allocation which may be used
0011  *   to avoid revealing of sensitive data due to paging etc.
0012  */
0013 
0014 #include "mpi-internal.h"
0015 
0016 void mpi_mul(MPI w, MPI u, MPI v)
0017 {
0018     mpi_size_t usize, vsize, wsize;
0019     mpi_ptr_t up, vp, wp;
0020     mpi_limb_t cy;
0021     int usign, vsign, sign_product;
0022     int assign_wp = 0;
0023     mpi_ptr_t tmp_limb = NULL;
0024 
0025     if (u->nlimbs < v->nlimbs) {
0026         /* Swap U and V. */
0027         usize = v->nlimbs;
0028         usign = v->sign;
0029         up    = v->d;
0030         vsize = u->nlimbs;
0031         vsign = u->sign;
0032         vp    = u->d;
0033     } else {
0034         usize = u->nlimbs;
0035         usign = u->sign;
0036         up    = u->d;
0037         vsize = v->nlimbs;
0038         vsign = v->sign;
0039         vp    = v->d;
0040     }
0041     sign_product = usign ^ vsign;
0042     wp = w->d;
0043 
0044     /* Ensure W has space enough to store the result.  */
0045     wsize = usize + vsize;
0046     if (w->alloced < wsize) {
0047         if (wp == up || wp == vp) {
0048             wp = mpi_alloc_limb_space(wsize);
0049             assign_wp = 1;
0050         } else {
0051             mpi_resize(w, wsize);
0052             wp = w->d;
0053         }
0054     } else { /* Make U and V not overlap with W.    */
0055         if (wp == up) {
0056             /* W and U are identical.  Allocate temporary space for U. */
0057             up = tmp_limb = mpi_alloc_limb_space(usize);
0058             /* Is V identical too?  Keep it identical with U.  */
0059             if (wp == vp)
0060                 vp = up;
0061             /* Copy to the temporary space.  */
0062             MPN_COPY(up, wp, usize);
0063         } else if (wp == vp) {
0064             /* W and V are identical.  Allocate temporary space for V. */
0065             vp = tmp_limb = mpi_alloc_limb_space(vsize);
0066             /* Copy to the temporary space.  */
0067             MPN_COPY(vp, wp, vsize);
0068         }
0069     }
0070 
0071     if (!vsize)
0072         wsize = 0;
0073     else {
0074         mpihelp_mul(wp, up, usize, vp, vsize, &cy);
0075         wsize -= cy ? 0:1;
0076     }
0077 
0078     if (assign_wp)
0079         mpi_assign_limb_space(w, wp, wsize);
0080     w->nlimbs = wsize;
0081     w->sign = sign_product;
0082     if (tmp_limb)
0083         mpi_free_limb_space(tmp_limb);
0084 }
0085 EXPORT_SYMBOL_GPL(mpi_mul);
0086 
0087 void mpi_mulm(MPI w, MPI u, MPI v, MPI m)
0088 {
0089     mpi_mul(w, u, v);
0090     mpi_tdiv_r(w, w, m);
0091 }
0092 EXPORT_SYMBOL_GPL(mpi_mulm);