Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 | /* mpi-mod.c - Modular reduction * Copyright (C) 1998, 1999, 2001, 2002, 2003, * 2007 Free Software Foundation, Inc. * * This file is part of Libgcrypt. */ #include "mpi-internal.h" #include "longlong.h" /* Context used with Barrett reduction. */ struct barrett_ctx_s { MPI m; /* The modulus - may not be modified. */ int m_copied; /* If true, M needs to be released. */ int k; MPI y; MPI r1; /* Helper MPI. */ MPI r2; /* Helper MPI. */ MPI r3; /* Helper MPI allocated on demand. */ }; void mpi_mod(MPI rem, MPI dividend, MPI divisor) { mpi_fdiv_r(rem, dividend, divisor); } /* This function returns a new context for Barrett based operations on * the modulus M. This context needs to be released using * _gcry_mpi_barrett_free. If COPY is true M will be transferred to * the context and the user may change M. If COPY is false, M may not * be changed until gcry_mpi_barrett_free has been called. */ mpi_barrett_t mpi_barrett_init(MPI m, int copy) { mpi_barrett_t ctx; MPI tmp; mpi_normalize(m); ctx = kcalloc(1, sizeof(*ctx), GFP_KERNEL); if (!ctx) return NULL; if (copy) { ctx->m = mpi_copy(m); ctx->m_copied = 1; } else ctx->m = m; ctx->k = mpi_get_nlimbs(m); tmp = mpi_alloc(ctx->k + 1); /* Barrett precalculation: y = floor(b^(2k) / m). */ mpi_set_ui(tmp, 1); mpi_lshift_limbs(tmp, 2 * ctx->k); mpi_fdiv_q(tmp, tmp, m); ctx->y = tmp; ctx->r1 = mpi_alloc(2 * ctx->k + 1); ctx->r2 = mpi_alloc(2 * ctx->k + 1); return ctx; } void mpi_barrett_free(mpi_barrett_t ctx) { if (ctx) { mpi_free(ctx->y); mpi_free(ctx->r1); mpi_free(ctx->r2); if (ctx->r3) mpi_free(ctx->r3); if (ctx->m_copied) mpi_free(ctx->m); kfree(ctx); } } /* R = X mod M * * Using Barrett reduction. Before using this function * _gcry_mpi_barrett_init must have been called to do the * precalculations. CTX is the context created by this precalculation * and also conveys M. If the Barret reduction could no be done a * straightforward reduction method is used. * * We assume that these conditions are met: * Input: x =(x_2k-1 ...x_0)_b * m =(m_k-1 ....m_0)_b with m_k-1 != 0 * Output: r = x mod m */ void mpi_mod_barrett(MPI r, MPI x, mpi_barrett_t ctx) { MPI m = ctx->m; int k = ctx->k; MPI y = ctx->y; MPI r1 = ctx->r1; MPI r2 = ctx->r2; int sign; mpi_normalize(x); if (mpi_get_nlimbs(x) > 2*k) { mpi_mod(r, x, m); return; } sign = x->sign; x->sign = 0; /* 1. q1 = floor( x / b^k-1) * q2 = q1 * y * q3 = floor( q2 / b^k+1 ) * Actually, we don't need qx, we can work direct on r2 */ mpi_set(r2, x); mpi_rshift_limbs(r2, k-1); mpi_mul(r2, r2, y); mpi_rshift_limbs(r2, k+1); /* 2. r1 = x mod b^k+1 * r2 = q3 * m mod b^k+1 * r = r1 - r2 * 3. if r < 0 then r = r + b^k+1 */ mpi_set(r1, x); if (r1->nlimbs > k+1) /* Quick modulo operation. */ r1->nlimbs = k+1; mpi_mul(r2, r2, m); if (r2->nlimbs > k+1) /* Quick modulo operation. */ r2->nlimbs = k+1; mpi_sub(r, r1, r2); if (mpi_has_sign(r)) { if (!ctx->r3) { ctx->r3 = mpi_alloc(k + 2); mpi_set_ui(ctx->r3, 1); mpi_lshift_limbs(ctx->r3, k + 1); } mpi_add(r, r, ctx->r3); } /* 4. while r >= m do r = r - m */ while (mpi_cmp(r, m) >= 0) mpi_sub(r, r, m); x->sign = sign; } void mpi_mul_barrett(MPI w, MPI u, MPI v, mpi_barrett_t ctx) { mpi_mul(w, u, v); mpi_mod_barrett(w, w, ctx); } |