119 lines · c
1/* mpi-add.c - MPI functions2 * 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 the9 * way the data is stored; this is to support the abstraction10 * of an optional secure memory allocation which may be used11 * to avoid revealing of sensitive data due to paging etc.12 */13 14#include "mpi-internal.h"15 16int mpi_add(MPI w, MPI u, MPI v)17{18 mpi_ptr_t wp, up, vp;19 mpi_size_t usize, vsize, wsize;20 int usign, vsign, wsign;21 int err;22 23 if (u->nlimbs < v->nlimbs) { /* Swap U and V. */24 usize = v->nlimbs;25 usign = v->sign;26 vsize = u->nlimbs;27 vsign = u->sign;28 wsize = usize + 1;29 err = RESIZE_IF_NEEDED(w, wsize);30 if (err)31 return err;32 /* These must be after realloc (u or v may be the same as w). */33 up = v->d;34 vp = u->d;35 } else {36 usize = u->nlimbs;37 usign = u->sign;38 vsize = v->nlimbs;39 vsign = v->sign;40 wsize = usize + 1;41 err = RESIZE_IF_NEEDED(w, wsize);42 if (err)43 return err;44 /* These must be after realloc (u or v may be the same as w). */45 up = u->d;46 vp = v->d;47 }48 wp = w->d;49 wsign = 0;50 51 if (!vsize) { /* simple */52 MPN_COPY(wp, up, usize);53 wsize = usize;54 wsign = usign;55 } else if (usign != vsign) { /* different sign */56 /* This test is right since USIZE >= VSIZE */57 if (usize != vsize) {58 mpihelp_sub(wp, up, usize, vp, vsize);59 wsize = usize;60 MPN_NORMALIZE(wp, wsize);61 wsign = usign;62 } else if (mpihelp_cmp(up, vp, usize) < 0) {63 mpihelp_sub_n(wp, vp, up, usize);64 wsize = usize;65 MPN_NORMALIZE(wp, wsize);66 if (!usign)67 wsign = 1;68 } else {69 mpihelp_sub_n(wp, up, vp, usize);70 wsize = usize;71 MPN_NORMALIZE(wp, wsize);72 if (usign)73 wsign = 1;74 }75 } else { /* U and V have same sign. Add them. */76 mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);77 wp[usize] = cy;78 wsize = usize + cy;79 if (usign)80 wsign = 1;81 }82 83 w->nlimbs = wsize;84 w->sign = wsign;85 return 0;86}87EXPORT_SYMBOL_GPL(mpi_add);88 89int mpi_sub(MPI w, MPI u, MPI v)90{91 int err;92 MPI vv;93 94 vv = mpi_copy(v);95 if (!vv)96 return -ENOMEM;97 98 vv->sign = !vv->sign;99 err = mpi_add(w, u, vv);100 mpi_free(vv);101 102 return err;103}104EXPORT_SYMBOL_GPL(mpi_sub);105 106int mpi_addm(MPI w, MPI u, MPI v, MPI m)107{108 return mpi_add(w, u, v) ?:109 mpi_mod(w, w, m);110}111EXPORT_SYMBOL_GPL(mpi_addm);112 113int mpi_subm(MPI w, MPI u, MPI v, MPI m)114{115 return mpi_sub(w, u, v) ?:116 mpi_mod(w, w, m);117}118EXPORT_SYMBOL_GPL(mpi_subm);119