^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /* mpi-add.c - MPI functions
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * Copyright (C) 1994, 1996, 1998, 2001, 2002,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) * 2003 Free Software Foundation, Inc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * This file is part of Libgcrypt.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) * Note: This code is heavily based on the GNU MP Library.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Actually it's the same code with only minor changes in the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) * way the data is stored; this is to support the abstraction
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * of an optional secure memory allocation which may be used
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * to avoid revealing of sensitive data due to paging etc.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) #include "mpi-internal.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) /****************
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) * Add the unsigned integer V to the mpi-integer U and store the
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) * result in W. U and V may be the same.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) void mpi_add_ui(MPI w, MPI u, unsigned long v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) mpi_ptr_t wp, up;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) mpi_size_t usize, wsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) int usign, wsign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) usize = u->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27) usign = u->sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) wsign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) /* If not space for W (and possible carry), increase space. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) wsize = usize + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) if (w->alloced < wsize)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) mpi_resize(w, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) /* These must be after realloc (U may be the same as W). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) up = u->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) wp = w->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) if (!usize) { /* simple */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) wp[0] = v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) wsize = v ? 1:0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) } else if (!usign) { /* mpi is not negative */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) mpi_limb_t cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) cy = mpihelp_add_1(wp, up, usize, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) wp[usize] = cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) wsize = usize + cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) /* The signs are different. Need exact comparison to determine
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * which operand to subtract from which.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) if (usize == 1 && up[0] < v) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) wp[0] = v - up[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) wsize = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) mpihelp_sub_1(wp, up, usize, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) /* Size can decrease with at most one limb. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) wsize = usize - (wp[usize-1] == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) wsign = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) w->nlimbs = wsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) w->sign = wsign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) void mpi_add(MPI w, MPI u, MPI v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) mpi_ptr_t wp, up, vp;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) mpi_size_t usize, vsize, wsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) int usign, vsign, wsign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73) if (u->nlimbs < v->nlimbs) { /* Swap U and V. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) usize = v->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) usign = v->sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76) vsize = u->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) vsign = u->sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) wsize = usize + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) RESIZE_IF_NEEDED(w, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) /* These must be after realloc (u or v may be the same as w). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) up = v->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) vp = u->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) usize = u->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) usign = u->sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) vsize = v->nlimbs;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) vsign = v->sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) wsize = usize + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) RESIZE_IF_NEEDED(w, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) /* These must be after realloc (u or v may be the same as w). */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) up = u->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) vp = v->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) wp = w->d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) wsign = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) if (!vsize) { /* simple */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) MPN_COPY(wp, up, usize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) wsize = usize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) wsign = usign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) } else if (usign != vsign) { /* different sign */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* This test is right since USIZE >= VSIZE */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) if (usize != vsize) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) mpihelp_sub(wp, up, usize, vp, vsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) wsize = usize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) MPN_NORMALIZE(wp, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) wsign = usign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) } else if (mpihelp_cmp(up, vp, usize) < 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) mpihelp_sub_n(wp, vp, up, usize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) wsize = usize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) MPN_NORMALIZE(wp, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) if (!usign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) wsign = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) mpihelp_sub_n(wp, up, vp, usize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) wsize = usize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) MPN_NORMALIZE(wp, wsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) if (usign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) wsign = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) } else { /* U and V have same sign. Add them. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) mpi_limb_t cy = mpihelp_add(wp, up, usize, vp, vsize);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) wp[usize] = cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) wsize = usize + cy;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) if (usign)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) wsign = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) w->nlimbs = wsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) w->sign = wsign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) EXPORT_SYMBOL_GPL(mpi_add);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) void mpi_sub(MPI w, MPI u, MPI v)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) MPI vv = mpi_copy(v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) vv->sign = !vv->sign;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) mpi_add(w, u, vv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) mpi_free(vv);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) void mpi_addm(MPI w, MPI u, MPI v, MPI m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) mpi_add(w, u, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) mpi_mod(w, w, m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) EXPORT_SYMBOL_GPL(mpi_addm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) void mpi_subm(MPI w, MPI u, MPI v, MPI m)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) mpi_sub(w, u, v);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) mpi_mod(w, w, m);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) EXPORT_SYMBOL_GPL(mpi_subm);