18c2ecf20Sopenharmony_ci/* mpi-mul.c - MPI functions 28c2ecf20Sopenharmony_ci * Copyright (C) 1994, 1996, 1998, 2001, 2002, 38c2ecf20Sopenharmony_ci * 2003 Free Software Foundation, Inc. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * This file is part of Libgcrypt. 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * Note: This code is heavily based on the GNU MP Library. 88c2ecf20Sopenharmony_ci * Actually it's the same code with only minor changes in the 98c2ecf20Sopenharmony_ci * way the data is stored; this is to support the abstraction 108c2ecf20Sopenharmony_ci * of an optional secure memory allocation which may be used 118c2ecf20Sopenharmony_ci * to avoid revealing of sensitive data due to paging etc. 128c2ecf20Sopenharmony_ci */ 138c2ecf20Sopenharmony_ci 148c2ecf20Sopenharmony_ci#include "mpi-internal.h" 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_civoid mpi_mul(MPI w, MPI u, MPI v) 178c2ecf20Sopenharmony_ci{ 188c2ecf20Sopenharmony_ci mpi_size_t usize, vsize, wsize; 198c2ecf20Sopenharmony_ci mpi_ptr_t up, vp, wp; 208c2ecf20Sopenharmony_ci mpi_limb_t cy; 218c2ecf20Sopenharmony_ci int usign, vsign, sign_product; 228c2ecf20Sopenharmony_ci int assign_wp = 0; 238c2ecf20Sopenharmony_ci mpi_ptr_t tmp_limb = NULL; 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_ci if (u->nlimbs < v->nlimbs) { 268c2ecf20Sopenharmony_ci /* Swap U and V. */ 278c2ecf20Sopenharmony_ci usize = v->nlimbs; 288c2ecf20Sopenharmony_ci usign = v->sign; 298c2ecf20Sopenharmony_ci up = v->d; 308c2ecf20Sopenharmony_ci vsize = u->nlimbs; 318c2ecf20Sopenharmony_ci vsign = u->sign; 328c2ecf20Sopenharmony_ci vp = u->d; 338c2ecf20Sopenharmony_ci } else { 348c2ecf20Sopenharmony_ci usize = u->nlimbs; 358c2ecf20Sopenharmony_ci usign = u->sign; 368c2ecf20Sopenharmony_ci up = u->d; 378c2ecf20Sopenharmony_ci vsize = v->nlimbs; 388c2ecf20Sopenharmony_ci vsign = v->sign; 398c2ecf20Sopenharmony_ci vp = v->d; 408c2ecf20Sopenharmony_ci } 418c2ecf20Sopenharmony_ci sign_product = usign ^ vsign; 428c2ecf20Sopenharmony_ci wp = w->d; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci /* Ensure W has space enough to store the result. */ 458c2ecf20Sopenharmony_ci wsize = usize + vsize; 468c2ecf20Sopenharmony_ci if (w->alloced < wsize) { 478c2ecf20Sopenharmony_ci if (wp == up || wp == vp) { 488c2ecf20Sopenharmony_ci wp = mpi_alloc_limb_space(wsize); 498c2ecf20Sopenharmony_ci assign_wp = 1; 508c2ecf20Sopenharmony_ci } else { 518c2ecf20Sopenharmony_ci mpi_resize(w, wsize); 528c2ecf20Sopenharmony_ci wp = w->d; 538c2ecf20Sopenharmony_ci } 548c2ecf20Sopenharmony_ci } else { /* Make U and V not overlap with W. */ 558c2ecf20Sopenharmony_ci if (wp == up) { 568c2ecf20Sopenharmony_ci /* W and U are identical. Allocate temporary space for U. */ 578c2ecf20Sopenharmony_ci up = tmp_limb = mpi_alloc_limb_space(usize); 588c2ecf20Sopenharmony_ci /* Is V identical too? Keep it identical with U. */ 598c2ecf20Sopenharmony_ci if (wp == vp) 608c2ecf20Sopenharmony_ci vp = up; 618c2ecf20Sopenharmony_ci /* Copy to the temporary space. */ 628c2ecf20Sopenharmony_ci MPN_COPY(up, wp, usize); 638c2ecf20Sopenharmony_ci } else if (wp == vp) { 648c2ecf20Sopenharmony_ci /* W and V are identical. Allocate temporary space for V. */ 658c2ecf20Sopenharmony_ci vp = tmp_limb = mpi_alloc_limb_space(vsize); 668c2ecf20Sopenharmony_ci /* Copy to the temporary space. */ 678c2ecf20Sopenharmony_ci MPN_COPY(vp, wp, vsize); 688c2ecf20Sopenharmony_ci } 698c2ecf20Sopenharmony_ci } 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_ci if (!vsize) 728c2ecf20Sopenharmony_ci wsize = 0; 738c2ecf20Sopenharmony_ci else { 748c2ecf20Sopenharmony_ci mpihelp_mul(wp, up, usize, vp, vsize, &cy); 758c2ecf20Sopenharmony_ci wsize -= cy ? 0:1; 768c2ecf20Sopenharmony_ci } 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci if (assign_wp) 798c2ecf20Sopenharmony_ci mpi_assign_limb_space(w, wp, wsize); 808c2ecf20Sopenharmony_ci w->nlimbs = wsize; 818c2ecf20Sopenharmony_ci w->sign = sign_product; 828c2ecf20Sopenharmony_ci if (tmp_limb) 838c2ecf20Sopenharmony_ci mpi_free_limb_space(tmp_limb); 848c2ecf20Sopenharmony_ci} 858c2ecf20Sopenharmony_ci 868c2ecf20Sopenharmony_civoid mpi_mulm(MPI w, MPI u, MPI v, MPI m) 878c2ecf20Sopenharmony_ci{ 888c2ecf20Sopenharmony_ci mpi_mul(w, u, v); 898c2ecf20Sopenharmony_ci mpi_tdiv_r(w, w, m); 908c2ecf20Sopenharmony_ci} 918c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(mpi_mulm); 92