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